\begindata{text, 268771096}
\textdsversion{11}
\define{italic
menu:[Font,Italic]
attr:[FontFace Italic Int Set]}
\define{bold
menu:[Font,Bold]
attr:[FontFace Bold Int Set]}
\define{chapter
menu:[Title,Chapter]
attr:[Justification Centered Point 0]
attr:[FontFace Bold Int Set]
attr:[FontSize PreviousFontSize Point 4]}
\define{section
menu:[Title,Section]
attr:[Justification Centered Point 0]
attr:[FontFace Bold Int Set]
attr:[FontSize PreviousFontSize Point 4]}
\define{subsection
menu:[Title,Subsection]
attr:[Justification LeftJustified Point 0]
attr:[FontSize PreviousFontSize Point 4]}
\define{paragraph
menu:[Title,Paragraph]
attr:[Justification LeftJustified Point 0]
attr:[FontFace Italic Int Set]
attr:[FontSize PreviousFontSize Point 4]}
\define{bigger
menu:[Font,Bigger]
attr:[FontSize PreviousFontSize Point 2]}
\define{indent
menu:[Region,Indent]
attr:[LeftMargin LeftMargin Inch 32768]
attr:[RightMargin RightMargin Inch 32768]}
\define{typewriter
menu:[Font,Typewriter]
attr:[FontFace FixedFace Int Set]
attr:[FontFamily AndyType Int 0]}
\define{display
menu:[Region,Display]
attr:[LeftMargin LeftMargin Inch 32768]
attr:[RightMargin RightMargin Inch 32768]
attr:[Justification LeftJustified Point 0]}
\define{example
menu:[Region,Example]
attr:[LeftMargin LeftMargin Inch 32768]
attr:[Justification LeftJustified Point 0]
attr:[FontFace FixedFace Int Set]
attr:[FontFamily AndyType Int 0]}
\define{description
menu:[Region,Description]
attr:[LeftMargin LeftMargin Inch 32768]
attr:[Indent LeftEdge Inch -32768]}
\define{quotation
menu:[Region,Quotation]
attr:[LeftMargin LeftMargin Inch 32768]
attr:[RightMargin RightMargin Inch 32768]
attr:[FontFace Italic Int Set]}
\define{subscript
menu:[Font,Subscript]
attr:[Script PreviousScriptMovement Point 131072]
attr:[FontSize PreviousFontSize Point -2]}
\define{superscript
menu:[Font,Superscript]
attr:[Script PreviousScriptMovement Point -393216]
attr:[FontSize PreviousFontSize Point -2]}
\define{smaller
menu:[Font,Smaller]
attr:[FontSize PreviousFontSize Point -2]}
\define{heading
menu:[Title,Heading]
attr:[LeftMargin LeftMargin Inch -13107]
attr:[Justification LeftJustified Point 0]
attr:[FontFace Bold Int Set]}
\define{majorheading
menu:[Title,MajorHeading]
attr:[Justification Centered Point 0]
attr:[FontSize PreviousFontSize Point 4]}
\define{formatnote
menu:[Region,FormatNote]
attr:[Flags PassThru Int Set]}
\define{subheading
menu:[Title,Subheading]
attr:[Justification LeftJustified Point 0]
attr:[FontFace Bold Int Set]}
\define{center
menu:[Justify,Center]
attr:[Justification Centered Point 0]}
\define{flushleft
menu:[Justify,FlushLeft]
attr:[Justification LeftJustified Point 0]}
\define{flushright
menu:[Justify,FlushRight]
attr:[Justification RightJustified Point 0]}
\define{leftindent
menu:[Region,LeftIndent]
attr:[LeftMargin LeftMargin Inch 32768]}
\define{article
menu:[Title,Article]
attr:[Justification Centered Point 0]
attr:[FontFace Bold Int Set]
attr:[FontSize ConstantFontSize Point 24]}
\define{subpara
menu:[Title,Subpara]
attr:[Justification LeftJustified Point 0]
attr:[FontFace Bold Int Set]}
\define{subsubpara
menu:[Title,Subsubpara]
attr:[Justification LeftJustified Point 0]
attr:[FontFace Italic Int Set]}

\subsection{Volume Package}

\paragraph{Introduction}

The volume package is a collection of header files, macros and procedures which are used by the Andrew File Manager software and the various volume utilities to manipulate volumes and UNIX file system partitions containing volumes.  It includes partition and volume synchronization mechanisms and some odds and ends to manipulate the volume location data base.  Since the volume package was developed simply as a collection of cooperating routines, some of which became programs (volume utilities), to support the File Manager, the functionality is not cleanly separated.  It should really be called the \italic{volume bundle}, rather than the volume package, to emphasize its rather haphazard nature.  The final word on all issues raised by this documentation rests with the source code.

\paragraph{Description}

\subpara{Volume Structure}

A volume is a collection of information, comprising a partial subtree of the file system hierarchy (for more information on this, see the discussion of volumes in the Andrew File System Operation section of this document).  A volume resides within a UNIX file system partition on an Andrew server.  For each volume, there is a named file within this partition called the \italic{volume header}.  For example, volume number 1234 residing on partition /vicepb of a server would have an associated file named /vicepb/V00001234.vol.  This file simply lists the inode numbers of the \italic{volume label}, the \italic{large vnode index}, and the \italic{small vnode index}.  These inode numbers have no corresponding Unix file names; the kernel changes described in System Interface Package section of this document are used to maintain these inodes outside of the UNIX file system name space.

The \bold{volume label }contains the following disk resident information:

The volume number, \italic{id}.  This is assigned at volume creation and remains constant over the life of the volume.

The \italic{name} of the volume.  This is 31 characters max, plus a null byte at the end.  This may be updated directly by any caller of the volume package.

An \italic{inUse} flag.  If this flag is on (i.e. 1), then the volume is being used by either the File Manager or some volume utility--or it was in use but the File Manager, volume utility or kernel crashed while it was using the volume.  This is normally maintained by the volume package.

An \italic{inService} flag.  This was intended to allow operations personnel to remove a volume from service temporarily, while leaving it on disk.  Not normally used:  it should always be 1.  This may be updated by the caller of the volume package.

A \italic{blessed} flag.  This was intended to allow a system administrator to force a volume to be removed from service for administrative reasons.  This is also not normally used:  it should always be 1.  This may be updated by the caller of the volume package.

A \italic{needsSalvaged} flag.  The volume package sets this flag if the volume has apparently become corrupted.  The File Manager will refuse to attach this volume until this flag has been cleared (which is only done by the salvager).  This is normally maintained by the volume package.

A \italic{uniquifier} for the volume.  This field is the next unique identifier that will be assigned to a vnode (the  \italic{uniquifier} field of the vnode) on a file creation operation.  It is normally updated by the File Manager.

A volume \italic{type}.  This has any of the values r\italic{eadwriteVolume}, \italic{readonlyVolume} or\italic{ backupVolume}.

The parent volume number, \italic{parentId}.  If this is a read/write volume, this field is the same as the volume number.  If it is a read-only volume, it is normally the volume number of the read/write volume the volume was cloned from.  If it wasn't cloned from a read/write volume (restored as a read-only volume, for example), this will be a dummy read/write volume number that was allocated specifically as a placeholder for this parent.  This is normally assigned by the volume package.

The most recent read-only cloned volume number, \italic{cloneId}.  If this volume is read/write, then cloneId will be 0 if the volume has never been cloned, or the read-only volume number of the most recently cloned volume.  That volume need not actually exist (it may have been purged since).  This may be updated by a caller of the volume package, with discretion.

The most recent backup volume number, \italic{backupId}.  If this volume is read/write, then this will be the volume number of the most recent backup volume.  The vo,lume need not actually exist (it may have been purged since creation).  This may be updated by a caller of the volume package, with discretion.

A rather special field, \italic{restoredFromId}.  If this is non-zero, then this volume was restored from a dump, and the volume that was originally dumped had this number.  This field is used by the vol-restore program to ensure that an incremental dump can only be restored on top of another volume which is ancestrally related.

Another special field, \italic{needsCallback}.  This field is set by the salvager if it changed anything about the volume, or by any other utility that significantly changes the volume while it is offline from the File Manager.  If the File Manager sees this field, it should generate a callback message for this volume to any clients of the volume.

And another, \italic{destroyMe}.  If this field is set to \italic{DESTROY_ME}, then the salvager should destroy this volume.  This flag should be set whenever a volume is created by the volume package.  It should be cleared by the caller if he wants the volume to stay around.  This serves to protect against a volume utility crashing halfway through recreating a volume (restoring it from a dump, moving it, etc.).  If that occurs, this flag should be set, and the volume will be treated as the trash it really is.

And one final, special flag, \italic{dontSalvage}.  If this field is set to \italic{DONT_SALVAGE}, then the salvager need not bother salvaging this volume (unless a full partition salvage has been forced by vfsck(8v) or the caller of vol-salvage(8v)).  The File Manager periodically sets this flag when a volume hasn't been used for a while and is consistent on disk.

Administrative information in the volume label includes \italic{maxquota} and \italic{minquota,} the maximum number of 1K blocks to assign to this volume (enforced by the File Manager), and the minimum, i.e. the minimum number of blocks guaranteed to be available for this volume (only the guarantee is worthless because this is \italic{not} enforced); \italic{maxfiles}, the maximum number of data files and directories that can be in the volume, also not enforced; and \italic{accountNumbe}r, a 32-bit number to be used for accounting, and \italic{owner}, the Andrew File System id of the user administratively responsible for this volume (neither of these are currently examined by any of the software, with the exception of the dump and restore utilities).

Resource usage information in the volume label includes \italic{filecount}, the number of files and directories in the volume; \italic{diskused}, the approximate total 1K blocks of disk space allocated to this volume; \italic{dayUse}, \italic{weekUse}, and \italic{dayUseDate} are used to count the number of \italic{VGetVolume} calls for this volume by the File Manager in the last seven complete 24 hours periods (midnight to midnight in local time).  These statistics are maintained by the volume package on behalf of the File Manager.

Several significant dates are maintained with the volume.  These include the \italic{creationDate}, which is the creation date for a read/write volume, the cloning date for a backup volume and the cloning date of the original copy of a read-only volume (all replicated copies of a read-only volume will have the same creation date); the \italic{copyDate}, which is the time that this copy of the volume was made (the restore date, for example, of a read/write volume, or the creation date of a particular copy of a read-only clone); the \italic{updateDate}, which is the time of last modification of the volume by a user; and the \italic{backupDate}, which is the last time a backup clone of this volume was taken (used by the vol-makebackups program to determine whether a particular volume should be backed up again, if the program is re-run).  The fields \italic{accessDate} and \italic{expirationDate} are not used.

There are two messages associated with the volume, \italic{offlineMessage} and \italic{motd}.  These are not used in practice.

The \bold{large vnode index,} whose inode is listed in the volume header, is a file addressed by \italic{directory vnode number. } The \bold{small vnode index} ,whose inode is also listed in the volume header, is addressed by \italic{symbolic link vnode numbers} and \italic{file vnode numbers}. Various macros, described in the interface section below, are provided to index into these vnode indices.  The file system hierarchy is built from the vnodes in these indices, in much the same way as a UNIX file system is built from inodes.  Directory vnode number one is the root vnode for a volume; each directory vnode points to a file containing a directory maintained by the \italic{dir package}.  This directory contains name to vnode mappings for each file or directory in the root, and subordinate directories contain similar mappings.  Directory vnodes are in a separate index because they are larger than other vnodes:  a directory vnode is 256 bytes long, 64 bytes of basic vnode, and 192 bytes of access control list for the directory.  A vnode for an ordinary file or for a symbolic link is always 64 bytes long since it uses the access control list for its parent directory.  Vnodes are indexed linearly in their respective indicies; directory vnodes are always odd, and the other vnodes are even.

Each \bold{vnode} contains the following disk-resident information, most of which is not maintained directly by the volume package but simply made available to higher level software:

The \italic{type} of the vnode: \italic{vNull}, not allocated; \italic{vFile}, an ordinary file; \italic{vDirectory} a directory; and \italic{VSymlink}, a symbolic link (also used as a mount point by the Andrew Cache Manager).

A \italic{cloned} flag.  This is set whenever the volume is cloned for every directory in the volume.  If this flag is on, the directory must be copied before it can be updated.

The UNIX \italic{modeBits}.  12 bits of UNIX mode information (the protection mode and SUID/SGID and sticky bits).

The \italic{linkCount}.  Used to maintain a count of the number of times this vnode is referred to from within directories in this volume.  This is just there for show--so that the link count shown with an "ls -l" at a user workstation will agree with the user's intuition (if he or she uses UNIX) as to what it should be.

The \italic{length} of the file.  This is the actual length of a normal data file or symbolic link.  For directories, it is the length of the \italic{dir package-}maintained directory stored at the server.  Note that this does not correspond to the UNIX idea of the directory length (the Andrew File System directory format is different from the UNIX directory format).

A \italic{uniquifier}, assigned from the volume header's uniquifier, is used to make file identifiers (volume, vnode, unique) unique.

The \italic{dataVersion} of the file, which is incremented whenever the data within the file or directory is modified.

The \italic{inodeNumber} of the associated directory or file.  Both directories and files are actually plain UNIX files, that is, directories are not represented as UNIX directories.  The contents of a directory are maintained by the \italic{dir package}.  Files are not modified, but are replaced by the File Manager on every file store.  The link count of the inode (as opposed to the link count of the vnode) is used to indicate how many volumes reference the inode.  When a volume is cloned, the vnode indices are simply copied, and each inode's link count is incremented (with iinc(2v)).  When a file is stored, the File Manager decrements the link count on the old inode--if it is shared by another volume, UNIX will not deallocate it.

A date, \italic{unixModifyTime}, is set by the File Manager according to instructions from the workstation storing the file.  This is the time seen by users when they execute "ls -l" on a file.

The File Manager also maintains its own idea of the modification time, \italic{serverModifyTime}, which cannot be set by the workstation.  This allows incremental backups to be performed relative to a given modification time with the assurance that the modification time being compared against is the actual modification time of the file (rather than one set by utimes(2)).

The \italic{author} of the vnode is recorded.  This is the Andrew userid of the last user to store the file or update the directory.

The\italic{ owner} of the vnode is also recorded.  This is the Andrew userid of the user who originally created the file.

The \italic{lock} field is used by the File Manager to implement UNIX advisory locks.

Finally, there is a \italic{vnodeMagic} field, which should always be set to \italic{SMALLVNODEMAGIC} for small vnodes, and \italic{LARGEVNODEMAGIC} for large vnodes.  This is used by the volume package as a data integrity check.

For large (directory) vnodes, there is an additional 192 bytes of access control list following the basic vnode information.  This is maintained by the File Manager using the Access List Package.

\subpara{Initialization}

All programs wishing to use this package must call \italic{VInitVolumePackage} beforehand. The program must identify itself as being the \italic{File Manager}, the \italic{salvager} (if a full system salvage is being performed), or a random \italic{volume utility}.  This information is necessary for synchronization purposes.  There are three synchronization mechanisms:  a global lock file, a lock file for each file system partition containing Andrew volumes and a volume synchronization  server.  These mechanisms are all provided by this package, and are generally applied automatically.

\subpara{Program Synchronization Lock}

The global lock file is normally kept open with a UNIX exclusive advisory lock by the File Manager process (i.e. the single process which declared itself to be the File Manager when it called \italic{VInitVolumePackage}).  One function of this lock is to prevent two File Managers from \italic{ever} running on the same machine at the same time.  Volume utilities (that is, offline programs which wish to create volumes, dump volumes, etc.) use this lock as a means of ensuring that the File Manager is running continuously throughout the operation they are performing.  This necessary because (1) the File Manager acts as a synchronizer for the various offline operations, and (2) if the File Manager should crash, it is necessary that long-running operations, such as dump, be terminated so that the system may be salvaged and the File Manager restarted as soon as possible (as long as a dump is running, the system cannot be salvaged or the integrity of the dump might be compromised. An example is the salvager modifying the volume that was being dumped).  Every volume utility therefore forks (this is done by \italic{VInitVolumePackage}) and the child process actually does the required operation.  Meanwhile, the parent process attempts to obtain the file system lock in shared mode.  If it ever succeeds, the File Manager must have crashed.  In this event, a \italic{SIG_INT} is sent to the child process.  The parent exits with an exit code of 64 (\italic{VUTIL_RESTART}), which is, by convention, a "retriable" exit code.  That is, higher level software that is attempting to run the volume utility should reschedule the activity at a later time, when the File Manager is likely to be up.

The salvager (vol-salvage) also uses the global lock file, except that it obtains the lock as a shared lock when doing a full system salvage or partition salvage (again, this is handled by \italic{VInitVolumePackage}).  This ensures that the File Manager is NOT running if the salvager manages to acquire this lock.  By acquiring the lock in shared mode, there is a guarantee that volume utilities will also not stay around (as long as nothing has an exclusive lock on the file, the volume utilities will not run).  It also prevents the File Manager from starting up until the salvager has finished.  If the salvager wishes to do a single volume salvage, it identifies itself to \italic{VInitVolumePackage} as a volume utility.

To summarize: the File Manager and the salvager do not run at the same time, unless only one volume is being salvaged.  Volume utilities may run at the same time as the File Manager, but not at the same time as the salvager.  When the File Manager crashes, all volume utilities should die to make way for the salvager.  This is accomplished by a single file which is locked in exclusive mode by the File Manager, in shared mode by the salvager and in shared mode by the parent of a forked volume utility.  If the parent ever obtains the lock, it kills the child and exits with a retriable exit code.

\subpara{Partition Locks}

In addition to the global lock described above, there is a lock associated with each UNIX file system partition containing Andrew volumes (partitions named /vicep?).  The lock is obtained on the partition root.  It is obtained automatically by \italic{VAttachVolume} and \italic{VCreateVolume} for utility programs which declare themselves to be volume utilities in \italic{VInitVolumePackage}, and is also obtained explicitly by the salvager.  This lock is a conservative measure designed to prevent any utility from changing anything on a partition at the same time as another utility.  If two volume utilities attempt to deal with the same partition, one of them will wait.  Higher level software should take pains to avoid deadlock when more than one partition in the system is used (moving a volume, for example).  The File Manager does not obtain this lock; the File Manager volume synchronization mechanism, discussed below, is used instead.

\subpara{File Manager Volume Synchronization}

The File Manager (i.e. the program that declares itself to be the File Manager to \italic{VInitVolumePackage}) provides a synchronization mechanism for external volume utilities, that is, programs which are invoked to do something to a UNIX file system partition containing Andrew File System volumes.  This package gives a utility the capability to notify the File Manager when it is necessary to make an external change to a volume or when it simply wishes to examine a volume but requires that the volume remain in a consistent state.  It is also possible to notify the File Manager of the creation of new volumes.  This synchronization is automatically instantiated within the File Manager by the volume package.

\subpara{Accessing Volume Internals}

The File Manager and volume utilities must call \italic{VAttachVolume} before using a volume (because of its special nature, the volume salvager program uses very little of the volume package routines.  It must be prepared to deal with volumes which would be sufficiently corrupted to completely befuddle the normal interface routines).  If the program is a volume utility, an exclusive lock will be obtained for the partition containing the volume.  Also, the appropriate request message will be sent to the File Manager, depending upon the attachment mode specified by the caller.  Once a volume is attached, a pointer to an in-core volume header will be returned.  When a volume utility is finished with a volume, the volume header information may be updated with \italic{VUpdateVolume} and it should be detached with \italic{VDetachVolume}.  When the volume is detached, the File Manager is notified and resumes normal operations with the volume (if it hasn't been purged).

\italic{VAttachVolume} returns a pointer to an internal volume structure.  This pointer can also be obtained after attachment by \italic{VGetVolume}, which returns a volume pointer.  It is released by \italic{VPutVolume}.  Releasing a volume is only necessary within the File Manager, where the volume package keeps track of which volumes are in use.  This is done for the purpose of shutting down the File Manager, updating volume headers periodically, synchronization with external volume utilities and maintaining a volume header cache.  Once a pointer to a volume header is obtained, various macros can be used to directly modify fields within the header.

Individual vnodes may be manipulated by first obtaining a pointer to them via \italic{VGetVnode}.  The fields within the vnode may be directly modified, then the vnode released with \italic{VPutVnode}.  A cache of vnodes is maintained in virtual memory.

Such programs as the salvager and makebackups may use only a subset of these routines.  Both of these programs, for example, scan the vnode indices directly, using the supplied macros to make the computation of disk offsets easier.

\paragraph{Interface specification
}
\subpara{Volume Procedures}

Many of the procedures described below use pointers to in-core volume structures, of the following type:
\formatnote{.bp}
\smaller{\typewriter{\smaller{typedef struct Volume \{
  struct Volume    *hashNext;/* Next in hash resolution table */
  VolumeId          hashid;  /* Volume number -- for hash table lookup */
  struct volHeader *header;  /* Cached disk data */
  Device            device;  /* Unix device for the volume */ 
  struct DiskPartition *partition; /* Information about the Unix partition */
  struct vnodeIndex \{
    Inode           inode;   /* Unix inode holding this index */
    byte           *bitmap;  /* Index bitmap */
    unsigned short  bitmapSize;  /* length of bitmap, in bytes */
    unsigned short  bitmapOffset;/* Which byte address of the first long to
                                   start search from in bitmap */
  \} vnodeIndex[nVNODECLASSES];
  Unique  nextVnodeUnique;   /* Derived originally from volume uniquifier.
                                This is the actual next version number to
                                assign; the uniquifier is bumped by 50 and
                                and written to disk every 50 file creates
                                If the volume is shutdown gracefully, the
                                uniquifier should be rewritten with the
                                value nextVnodeVersion*/
  Inode   diskDataInode;     /* Unix inode holding general volume info */
  bit16   vnodeHashOffset;   /* Computed by HashOffset function in vnode.h.
                                Assigned to the volume when initialized. 
                                Added to vnode number for hash table index */
  byte    shuttingDown;      /* This volume is going to be detached */
  byte    goingOffline;      /* This volume is going offline */
  bit16   cacheCheck;        /* Online sequence number to be used to
                                invalidate vnode cache entries that
                                stayed around while a volume was offline */
  short   nUsers;            /* Number of users of this volume header */
  byte    specialStatus;     /* An error code to return on VGetVolume: the
                                volume is unavailable for the reason quoted,
                                currently VBUSY or VMOVED */
  long    updateTime;        /* Time that this volume was put on the updated
                                volume list--the list of volumes that will be
                                salvaged should the file manager crash */
\} Volume;

struct volHeader \{
  struct volHeader  *prev, *next;/* LRU pointers */
  VolumeDiskData     diskstuff;  /* General volume info read from disk */
  Volume            *back;       /* back pointer to current volume structure */
\};
}}}\formatnote{.bp}
The previous structures reference this structure, which is the actual copy of the volume label:\typewriter{\smaller{\smaller{

typedef struct VolumeDiskData \{
  struct versionStamp stamp; /* Must be first field */
  VolumeId id;               /* Volume id--unique over all systems */
#define VNAMESIZE 32         /* including 0 byte */
  char    name[VNAMESIZE];   /* The volume name */
  byte    inUse;             /* Volume is being used (perhaps it is online),
                                or the system crashed while it was used */
  byte    inService;         /* Volume in service, not necessarily on line
                                This bit is set by an operator/system
                                programmer.  Manually taking a volume offline
                                always clears the inService bit. Taking
                                it out of service also takes it offline */
  byte    blessed;           /* Volume is administratively blessed with
                                the ability to go on line.  Set by a system
                                administrator. Clearing this bit will
                                take the volume offline */
  byte    needsSalvaged;     /* Volume needs salvaged--an unrecoverable
                                error occured to the volume.  Note:  a volume
                                may still require salvage even if this
                                flag isn't set--e.g. if a system crash
                                occurred while the volume was on line. */
  bit32   uniquifier;        /* Next vnode uniquifier for this volume */
  int     type;              /* The volume type */
  VolId   parentId;          /* Id of parent, if type==readonly */
  VolId   cloneId;           /* Latest read-only clone, if type==readwrite,
                                0 if the volume has never been cloned.  Note: the
                                indicated volume does not necessarily exist (it
                                may have been deleted since cloning). */
  VolId   backupId;          /* Latest backup copy of this read write volume */
  VolId   restoredFromId     /* The id in the dump this volume was restored
                                from--used simply to make sure that an
                                incremental dump is not restored on top
                                of something inappropriate:  Note: this
                                field itself is NEVER dumped!!! */
  byte    needsCallback;     /* Set by the salvager if anything was changed
                                about the volume.  Note:  this is not set by
                                clone/makebackups when setting the copy-on-write
                                flag in directories; this flag is not seen by
                                the clients. */
#define DESTROY_ME    0xD3
  byte    destroyMe;         /* If this is set to DESTROY_ME, then the salvager
                                should destroy this volume; it is bogus (left
                                over from an aborted  volume move, for example).
                                Note:  if this flag is on, then inService should
                                be OFF--only the salvager checks this flag */
#define DONT_SALVAGE    0xE5
  byte    dontSalvage;       /* If this is on, then don't bother salvaging this volume*/
  byte    reserveb3;
  bit32   reserved1[6];
/* Administrative stuff */
  int     maxquota;          /* Quota maximum, 1K blocks */
  int     minquota;          /* Quota minimum, 1K blocks */
  int     maxfiles;          /* Maximum number of files (i.e. inodes) */
  bit32   accountNumber;     /* Uninterpreted account number */
  bit32   owner;             /* The person administratively responsible
                                for this volume */
  int     reserved2[8];      /* Other administrative constraints */
/* Resource usage & statistics */
  int     filecount;         /* Actual number of files */
  int     diskused;          /* Actual disk space used, 1K blocks */
  int     dayUse;            /* Metric for today's usage of this volume so far */
  int     weekUse[7];        /* Usage of the volume for the last week.
                                weekUse[0] is for most recent complete
                                24 hour period of measurement;
                                week[6] is 7 days ago */
  Date    dayUseDate;        /* Date the dayUse statistics refer to;
                                the week use stats are the preceding 7 days */
  int     reserved3[11];     /* Other stats here */
/* Server supplied dates */
  Date    creationDate;      /* Creation date for a read/write
                                volume; cloning date for original copy of
                                a readonly volume (replicated volumes have
                                the same creation date) */
  Date    accessDate;        /* Last access time by a user, large granularity */
  Date    updateDate;        /* Last modification by user */
  Date    expirationDate;    /* 0 if it never expires */
  Date    backupDate;        /* last time a backup clone was taken */

  /* Time that this copy of this volume was made.  NEVER backed up.
     This field is only set when the copy is created */
  Date    copyDate;
  bit32   reserved4[8];

  /* messages */
#define VMSGSIZE 128
  char    offlineMessage[VMSGSIZE]; /* Why the volume is offline */
  char    motd[VMSGSIZE];           /* Volume "message of the day" */
\} VolumeDiskData;
\formatnote{.bp}}}}
The fields in the permanent portion of these structures (VolumeDiskData) are described previously in this document.  Most of the fields in the structures are accessible via the following macros:

\typewriter{\smaller{\smaller{#define V_device(vp)           ((vp)->device)
#define V_partition(vp)        ((vp)->partition)
#define V_inode(vp)            ((vp)->inode)
#define V_diskDataInode(vp)    ((vp)->diskDataInode)
#define V_vnodeIndex(vp)       ((vp)->vnodeIndex)
#define V_nextVnodeUnique(vp)  ((vp)->nextVnodeUnique)
#define V_stamp(vp)            ((vp)->header->diskstuff.stamp)
#define V_id(vp)               ((vp)->header->diskstuff.id)
#define V_name(vp)             ((vp)->header->diskstuff.name)
#define V_inUse(vp)            ((vp)->header->diskstuff.inUse)
#define V_inService(vp)        ((vp)->header->diskstuff.inService)
#define V_blessed(vp)          ((vp)->header->diskstuff.blessed)
#define V_needsSalvaged(vp)    ((vp)->header->diskstuff.needsSalvaged)
#define V_uniquifier(vp)       ((vp)->header->diskstuff.uniquifier)
#define V_type(vp)             ((vp)->header->diskstuff.type)
#define V_parentId(vp)         ((vp)->header->diskstuff.parentId)
#define V_cloneId(vp)          ((vp)->header->diskstuff.cloneId)
#define V_backupId(vp)         ((vp)->header->diskstuff.backupId)
#define V_restoredFromId(vp)   ((vp)->header->diskstuff.restoredFromId)
#define V_needsCallback(vp)    ((vp)->header->diskstuff.needsCallback)
#define V_destroyMe(vp)        ((vp)->header->diskstuff.destroyMe)
#define V_dontSalvage(vp)      ((vp)->header->diskstuff.dontSalvage)
#define V_maxquota(vp)         ((vp)->header->diskstuff.maxquota)
#define V_minquota(vp)         ((vp)->header->diskstuff.minquota)
#define V_maxfiles(vp)         ((vp)->header->diskstuff.maxfiles)
#define V_accountNumber(vp)    ((vp)->header->diskstuff.accountNumber)
#define V_owner(vp)            ((vp)->header->diskstuff.owner)
#define V_filecount(vp)        ((vp)->header->diskstuff.filecount)
#define V_diskused(vp)         ((vp)->header->diskstuff.diskused)
#define V_dayUse(vp)           ((vp)->header->diskstuff.dayUse)
#define V_weekUse(vp)          ((vp)->header->diskstuff.weekUse)
#define V_dayUseDate(vp)       ((vp)->header->diskstuff.dayUseDate)
#define V_creationDate(vp)     ((vp)->header->diskstuff.creationDate)
#define V_accessDate(vp)       ((vp)->header->diskstuff.accessDate)
#define V_updateDate(vp)       ((vp)->header->diskstuff.updateDate)
#define V_expirationDate(vp)   ((vp)->header->diskstuff.expirationDate)
#define V_backupDate(vp)       ((vp)->header->diskstuff.backupDate)
#define V_copyDate(vp)         ((vp)->header->diskstuff.copyDate)
#define V_offlineMessage(vp)   ((vp)->header->diskstuff.offlineMessage)
#define V_motd(vp)             ((vp)->header->diskstuff.motd)
#define V_disk(vp)             ((vp)->header->diskstuff)}
\formatnote{.bp}}}
The following are the procedures supported by this portion of the package:

\bold{\leftindent{VInitVolumePackage(pt, nLargeVnodes, nSmallVnodes, connect)
    ProgramType pt;
    int nLargeVnodes, nSmallVnodes;
    int connect;}}

Initialize the volume package.  \italic{Pt} is one of \italic{fileServer, volumeUtility,} or \italic{salvager}, as described above; \italic{nLargeVnodes} is the number of in-core cache entries for directory vnodes; \italic{nSmallVnodes} is the number of in-core cache entries for file and symbolic link vnodes.  \italic{Connect} is ignored if this is not a program of type \italic{volumeUtility}.  If it is and connect is 1, then a connection is established for this process to the File Manager volume synchronization code.  If connect is 0, the connection must be established using \italic{VConnectFS.}

\bold{\indent{int VConnectFS()}}

Connect to the File Manager volume synchronization code.  The type of the calling program, as specified to \italic{VInitVolumePackage}, must be \italic{volumeUtility}.  Normally this connection is made automatically.  If the program wishes to fork, however, each child must independently connect to the File Manager.  An example of this is found in the program \italic{vol-makebackups}.  The return value of this routine is 1 if it succeeded, 0 if it failed.  If the File Manager is not running, it will fail.

\bold{\indent{VDisconnectFS()}}

Disconnect from the File Manager synchronization code.  Any volumes that this utility requested to be offline (or some other state) will be placed back online, if they still exist.

\bold{\indent{VCheckVolumes()}}\indent{ or }\bold{\indent{VListVolumes()}}

This is intended to be called by the File Manager only.  It produces a list of the online volumes on the current File Manager in \italic{/vice/vol/VolumeList}.  This list is used by the \italic{makevldb(8v)} program to produce the volume location data base.  The File Manager can be prodded by an external utility into producing this list by calling \italic{FSYNC_askfs} in the appropriate manner.  These procedures have identical semantics (historically, they didn't).

\bold{\indent{VGetVolumeInfo(ec, key, info)
    Error *ec;
    char *key;
    VolumeInfo *info;}}\indent{
}
This routine is called by the File Manager to get information from the volume location data base about a volume.  \italic{Ec} is a pointer to an error code word, and will be set to 0 if successful or \italic{VNOVOL} if the volume is not located.  \italic{Key} is either the name of a volume or its number.  In either case it is encoded as the string representation of the name or number (in decimal).  Information is returned in the \italic{info} structure:

\leftindent{\smaller{\typewriter{\smaller{struct VolumeInfo \{
    u_long Vid;
    long Type;
    u_long Type0;
    u_long Type1;
    u_long Type2;
    u_long Type3;
    u_long Type4;
    u_long ServerCount;
    u_long Server0;
    u_long Server1;
    u_long Server2;
    u_long Server3;
    u_long Server4;
    u_long Server5;
    u_long Server6;
    u_long Server7;
\};}}}}\typewriter{\smaller{\smaller{
}}}
The layout of this structure reflects its history.  \italic{Vid} is the volume id of the volume looked up (this will be useful if the lookup key was the name of the volume).  \italic{Type} is the type of the volume (\italic{readwriteVolume} or \italic{RWVOL}, \italic{readonlyVolume} or \italic{ROVOL}, and \italic{backupVolume} or \italic{BACKVOL}).  These correspond to the integers 0, 1 and 2.  The array of volume id's, Type0 through Type4 give the corresponding volumes of the appropriate types (types 3 and 4 are reserved for future extensions).  So, for example, if the looked-up volume is read/write, then \italic{((u_long[])&Type0)[BACKVOL]} will be the number of backup volume corresponding to this volume.  \italic{ServerCount} is the number of servers serving this volume.  This should be 1 for anything but read-only volumes.  Read-only volumes may be replicated to up to 8 servers, whose IP addresses are specified in \italic{Server0} through \italic{Server7}.

Note:  if the volume has been moved off this server within the last hour or so, then the known real location of this volume will be substituted for the information from the VLDB.  This is important, because the workstation software will contact the server last known to contain the volume to discover the new location of the volume.  The File Manager will call \italic{VGetVolumeInfo} to satisfy the request.  After about an hour, this extra information is discarded--the presumption being that the VLDB will now be up to date.

\bold{\indent{VShutdown()}}

This routine is called by the File Manager (not by random volume utilities) to cleanly shut down all online volumes, making sure that their \italic{inUse} flags are cleared and everything is written to disk.  The routine will wait for any volume which is in use, until the lwp using it has relinquished it with a call to \italic{VPutVolume}.

\bold{\indent{Volume *VAttachVolume(ec, volumeId, mode)
    Error *ec;
    VolumeId volumeId;
    int mode;
}
\indent{Volume *VAttachVolumeByName(ec, partition, name, mode)
    Error *ec;
    char *partition;
    char *name;
    int mode;}}

These two routines are used to attach a volume to the current process.  The first interface allows the volume to be specified by volume number.  The volume package converts this number into a partition/filename combination and calls \italic{VAttachVolumeByName}.  The second interface requires that both the partition (e.g. "/vicepa") and \italic{file name} of the volume (e.g. "V0000001234.vol") be specified.  It does \italic{not} allow a volume to be attached by the internal name of the volume.  The second interface is especially useful when the volume name may appear twice as, for example, when a volume is being moved from one partition to another on the same server.  This guarantees that the expected volume is attached.

The attachment mode is one of:

\italic{\leftindent{V_READONLY}}\leftindent{\indent{: The external volume utility guarantees that it will not update the volume.  The volume will be left on line, and may change during this request.}

\italic{V_CLONE}:  \indent{The external volume utility wishes to clone the volume.  The File Manager guarantees not to update the volume while the clone operation is proceeding.  Update requests will be rejected by the File Manager with a V_BUSY error code; the workstation should retry those operations periodically.}

\italic{V_UPDATE}:  \indent{The volume is to go offline for general update, or purging.}

\italic{V_DUMP}:  \indent{A dump of the volume is requested; the volume may be served read-only during this time, but must not be updated.}

\italic{V_SECRETLY}:  }\indent{\leftindent{This is used to attach a volume when the File Manager shouldn't know about the volume.  This is used by vol-restore(8v) for moving a volume from one partition to another on a single server.  No message is sent to the File Manager.}}

These routines both return a pointer to a volume header, the contents of which can be accessed using the macros defined in volume.h.  These macros parallel the definitions supplied above.  In addition, macros are provided to access memory resident fields of the volume structure.

\bold{\indent{Volume *VGetVolume(ec, volumeId)
    Error *ec;
    VolId volumeId;}}

This routine is used to return a pointer to an already attached volume.  If the volume has not been attached, \italic{VNOVOL} will be returned.  If this is the File Manager, \italic{VMOVED, VOFFLINE, VNOSERVICE,} or \italic{VBUSY} may also be returned.  \italic{VMOVED} is returned if the volume was moved to another File Manager; \italic{VOFFLINE} if the volume is offline (it may have been taken offline because it needed to be salvaged, or by an external volume utility); \italic{VNOSERVICE} if the volume is either not in service (\italic{inService} in the volume label is 0), or is not administratively blessed (\italic{blessed} in the volume label is 0); and \italic{VBUSY} if the volume is temporarily offline for a clone request.
\indent{
}\bold{\indent{VPutVolume(vp)
    Volume *vp;}}

This routine is used to release a pointer to a volume.  This may be called by any volume utility, and must be called by the File Manager for every call to \italic{VAttachVolume, VAttachVolumeByName }and \italic{VGetVolume. } Note:  If any vnodes have been obtained with \italic{VAllocVnode,} or \italic{VGetVnode,} then these should be released using \italic{VPutVnode} before \italic{VPutVolume} is called.
\bold{
\indent{VForceOffline(vp)
    Volume *vp;}
}
This routine is invoked by the File Manager only.  The indicated volume is forced offline and the salvage flag (\italic{needsSalvaged}, in the volume label) is set.  This should only be called if the File Manager detects an internal error in the volume.  This prevents the server from having to deal with the volume until it has been successfully salvaged.
\indent{
}\bold{\indent{VOffline(vp, message)
    Volume *vp;
    char *message;}}

This is called by the File Manager to shutdown a volume.  The volume label is written to disk, with the \italic{inUse} bit turned off.  A copy of the header is maintained in memory, so that the File Manager can respond with a \italic{VOFFLINE} error when this volume is referenced.  The \italic{message} parameter is essentially not used.  It is, however, written into the volume label as the last offline message.

\bold{\indent{VDetachVolume(ec, vp)
    Error *ec;
    Volume *vp;}}

This is called by volume utilities when they are finished with a volume.  It removes the volume label from memory and notifies the File Manager that this utility is finished with the volume.  The File Manager is then free to reattach the volume.

\bold{\indent{VUpdateVolume(ec, vp)
    Error *ec;
    Volume *vp;}}

This routine is called to make sure that a volume header is written to disk.  It is called periodically by the File Manager, and \italic{must} be called by volume utilities before detaching a volume with a modified header.  The only error that can be returned in \italic{*ec }is \italic{VSALVAGE}--if the header could not be written to disk.

\bold{\indent{VSyncVolume(ec, vp)
    Error *ec;
    Error *vp;}}

This routine does a VUpdateVolume and fsync's the volume header to disk.  It is called by the File Manager.  It may return a \italic{VSALVAGE} error in \italic{*ec }if the header could not be updated.

\bold{\indent{VolumeId VolumeNumber(filename)
    char *filename;}}

Given the relative filename of a volume (not the full pathname), this returns the volume number.

\bold{\indent{char *VolumeExternalName(volumeId)
    VolumeId volumeId;}}

This returns a pointer to the filename corresponding to \italic{volumeId}.  This is simply formatted according to the predefined format string, \italic{VFORMAT}.

\bold{\indent{VSetDiskUsage()}}

This is a routine which should be called every five minutes by the File Manager (it should be named \italic{VFiveMinuteTimeOut}, but isn't).  It is responsible for calling the internal volume package routines \italic{VResetDiskUsage} every five minutes, and\italic{ VScanUpdateList} every 15 minutes.  \italic{VResetDiskUsage }causes the volume package's idea of how much space is available on each partition (which is an estimate), to be updated to match reality.  \italic{VScanUpdateList} has the effect of setting the \italic{dontSalvage} flag for volumes which have not been updated within the last 15 minutes.

\bold{\indent{VPrintCacheStats()}}

This routine may be called by the File Manager to print out volume and vnode caching statistics.

\bold{\leftindent{VAllocateVolumeId(ec)}}

This routine allocates a new unique volume id by incrementing the number stored in /vice/vol/maxvolid on this server.  It returns the inappropriate error \italic{VSALVAGE} if /vice/vol/maxvolid cannot be udpated correctly.
\bold{\leftindent{
Volume *VCreateVolume(ec, partition, volumeId, parentId)
    Error *ec;
    char *partition;
    VolId volumeId;
    VolId parentId;    }}

This routine can be used by a volume utility to create a volume on the specified partition with the specified volume number.  A parent volume number must be specified.  If this is a read/write volume, the number specified for the parent should be the new volume's volume number.   A pointer to a volume header is returned.  Possible errors that can be returned are \italic{VVOLEXISTS}, the volume already exists; \italic{VNOVOL}, the volume could not be created; as well as any of the errors that could be returned from VAttachVolume, since the volume is attached after creating it.

The File Manager is not informed of the creation of this volume; it is attached with mode \italic{V_SECRETLY}.  Detaching the volume will the cause the File Manager to be informed of the existence of the new volume.  The volume created is minimal:  the only significant values in the volume label that are initialized are the \italic{volumeId}, the volume's \italic{parentId}, and the \italic{destroyMe} flag.  If nothing further is done to the volume it will not be attached by the File Manager and it will be destroyed on the next salvage.

\bold{\leftindent{Volume *MakeBackupVolume(vp, sacrifice, verbose)
    Volume *vp;
    Volume *sacrifice;}}

This routine makes a new backup volume for the specified volume, \italic{vp}.  If \italic{sacrifice} is supplied, it is deleted in an efficient manner (this is much more efficient than deleting \italic{sacrifice} separately, then creating the backup volume).  A pointer to the new volume is returned.  The new backup volume has all the appropriate stuff in it; it is not a skeletal volume as is created by VCreateVolume.

\bold{\leftindent{AssignVolumeName(vol, name, ext)
    VolumeDiskData *vol;
    char *name, *ext;}}

This routine takes a pointer to the in-core copy of the volume label, and builds within that copy a reasonable name for the volume with the supplied extension.  If the name supplied has any of the extensions ".backup", ".readonly", or ".restored", then this is removed first.  The supplied extension is added to the name in such a way that the entire extension is preserved, but the name truncated if the total length would exceed 31 characters.

\bold{\leftindent{CopyVolumeHeader(from, to)
    VolumeDiskData *from, *to;}}

This routine copies most of the data from the in-core copy of a volume label to another.  The fields \italic{id, parentId }and \italic{copyDate }within the destination are\italic{ not }copied.  The \italic{destroyMe} field in the destination is set to \italic{DESTROY_ME}.

\bold{\leftindent{ClearVolumeStats(vol)
    VolumeDiskData *vol;}}

This routine clears the volume usage statistics information from an in-core copy of a volume label.  By using this routine, the caller need not know which fields in the volume header are included in the usage information.

\bold{\leftindent{CloneVolume(ec, original, new, old)
    Error *error;
    Volume *original, *new, *old;}}

The volume \italic{original} is cloned to\italic{ new}, which must have been created with\italic{ VCreateVolume.}  The new volume will be  identical to the old, except for the volume\italic{ id, parentId} and\italic{ copyDate. } \italic{DestroyMe} will be set in the volume label.  If the caller wants the volume to stick around, \italic{DestroyMe} must be set to 0 and the volume updated (\italic{VUpdateVolume}).  Other parameters in the volume label, such as the volume type, volume name, and volume creation date must be set explicitly by the caller if they are not to remain identical to the original volume.  If an \italic{old} volume is provided, it is deleted during the cloning process.  This is \italic{much} more efficient than deleting the volume separately, because idec(2v)'s to inodes in the vnode indices of \italic{old} are matched, when possible, to iinc(2v)'s to inodes that are now included in the vnode indices of \italic{new.}  When both an iinc and an idec of the same inode are required, they can be optimized away altogether.

\bold{\leftindent{VPurgeVolume(ec, vp)
    Error *ec;
    Volume *vp;}}

This routine is used to purge a volume, which must have been previously attached.  When the volume has been successfully purged, the File Manager is notified.
\formatnote{.bp}
\subpara{Vnode Procedures}

Vnode procedures deal with in-core vnode objects, of the following type:

\typewriter{\smaller{\smaller{typedef struct Vnode \{
  struct Vnode *hashNext;  /* Next vnode on hash conflict chain */
  struct Vnode *lruNext;   /* Less recently used vnode than this one */
  struct Vnode *lruPrev;   /* More recently used vnode than this one */
                           /* The lruNext, lruPrev fields are not
                              meaningful if the vnode is in use */
  bit16    hashIndex;      /* Hash table index */
  byte     changed:1;      /* 1 if the vnode has been changed */
  byte     delete:1;       /* 1 if the vnode should be deleted; in
                              this case, changed must also be 1 */
  VnodeId  vnodeNumber;
  struct Volume *volumePtr;/* Pointer to the volume containing this file*/
  byte     nUsers;         /* Number of lwp's who have done a VGetVnode */
  bit16    cacheCheck;     /* Must equal the value in the volume Header
                              for the cache entry to be valid */
  struct   Lock lock;      /* Internal lock */
  PROCESS  writer;         /* Process id having write lock */
  VnodeDiskObject disk;    /* The actual disk data for the vnode */
\} Vnode;

typedef struct VnodeDiskObject \{
  VnodeType  type:3;       /* Vnode is file, directory, symbolic link
                              or not allocated */
  unsigned   cloned:1;     /* This vnode was cloned--therefore the inode
                              is copy-on-write; only set for directories*/
  unsigned   modeBits:12;  /* Unix mode bits */
  bit16      linkCount;    /* Number of directory references to vnode
                              (from single directory only!) */
  bit32      length;       /* Number of bytes in this file */
  Unique     uniquifier;   /* Uniquifier for the vnode; assigned
                              from the volume uniquifier (actually
                              from nextVnodeUnique in the Volume
                              structure) */
  FileVersion dataVersion; /* version number of the data */
  Inode      inodeNumber;  /* inode number of the data attached to
                              this vnode */
  Date       unixModifyTime; /* set by user */
  UserId     author;       /* Userid of the last user storing the file */
  UserId     owner;        /* Userid of the user who created the file */
  VnodeId    parent;       /* Parent directory vnode */
  bit32      vnodeMagic;   /* Magic number--mainly for file server
                              paranoia checks */
# define SMALLVNODEMAGIC 0xda8c041F
# define LARGEVNODEMAGIC 0xad8765fe
    /* Vnode magic can be removed, someday, if we run need the room.  Simply
       have to be sure that the thing we replace can be VNODEMAGIC, rather
       than 0 (in an old file system).  Or go through and zero the fields,
       when we notice a version change (the index version number) */
  ViceLock   lock;         /* Advisory lock */
  Date       serverModifyTime; /* Used only by the server; for incremental
                                  backup purposes */
  bit32      reserved4;
  bit32      reserved5;
  bit32      reserved6;
    /* Missing:
       archiving/migration
       encryption key
     */
\} VnodeDiskObject;
}}}
The following procedures are provided to deal with vnodes:
\bold{
\indent{Vnode *VAllocVnode(ec, vp, type)
    Error *ec;
    Volume *vp;
    VnodeType type;}}

This function allocates a vnode of the specified \italic{type} (\italic{vNull, vFile, vDirectory} or \italic{vSymlink}) within the specified volume and returns a pointer to the in-core cached copy of the vnode.  The user is free to modify fields within the vnode directly (with great caution, of course).  The volume package will fill in the following fields of the disk-resident part of the vnode:  \italic{vnodeMagic, type, uniquifier}.  Other fields are set to zero.  The pointer returned is actually a pointer to an in-core object which contains the disk copy of the vnode.  Extra information includes the\italic{ vnodeNumber }assigned (this is not recorded in the disk-resident section of the vnode) and a \italic{volumePtr,} which is the pointer to the parent volume structure for this vnode.

Error codes that can be returned in \italic{*ec} are:  \italic{VOFFLINE}, the volume is offline; \italic{VREADONLY}, the volume is a read-only volume, and therefore new vnodes cannot be allocated; or \italic{VSALVAGE}, the volume is in need of salvaging.

\indent{\bold{Vnode *VGetVnode(ec,vp,vnodeNumber,locktype)
    Error *ec;
    Volume *vp;
    VnodeId vnodeNumber;
    int locktype;}}

This procedure returns a pointer to an in-core version of a vnode, as in\italic{ VAllocVnode}.  \italic{Locktype} should be one of \italic{\italic{READ_LOCK}} or \italic{\italic{WRITE_LOCK}}, as defined in lock.h.  If \italic{locktype} is \italic{READ_LOCK}, the vnode is obtained with an internal read lock, so that it is guaranteed to remain unchanged until the vnode is released with \italic{VPutVnode}.  If \italic{locktype} is \italic{WRITE_LOCK}, an exclusive lock is obtained for the vnode so that no other \italic{VGetVnode} will be honored until this vnode is released.  If the vnode is obtained with a write lock, then the memory-resident flags \italic{changed} and \italic{delete} may be both set to 1.  These will cause the vnode to be flushed to disk or deleted respectively when the vnode is released with \italic{VPutVnode}.  Note: if \italic{delete} is set, then \italic{changed }should be set also.

The error flag returned in \italic{*ec} will be 0, if a pointer was returned satisfactorily; \italic{\italic{VNOVNODE,}} if the vnode was not found; \italic{VOFFLINE} if the volume was offline; \italic{VREADONLY}, if the volume is a read/write volume and \italic{locktype} is \italic{WRITE_LOCK; } or \italic{VSALVAGE, }if the volume needs salvaging; 

\bold{\indent{VPutVnode(ec, vnp)
    Error *ec;
    Vnode *vnp;}}

This routine is used to release a vnode obtained with \italic{VAllocVnode} or \italic{VGetVnode}.  This routine should always be called on any active vnodes, before\italic{ VPutVolume} is called.

In addition to the procedures listed above, several macros are available for calculating index offsets for vnodes, etc.  Look in vnode.h for their definition.
\formatnote{.bp}
\subpara{Partition Procedures}

The following routines are provided to deal with UNIX disk partitions containing Andrew volumes.  Most of these are called internally by the volume package.  These routines deal with the disk partition data structure:

\typewriter{\smaller{\smaller{struct DiskPartition \{
  struct DiskPartition *next;
  char   name[32];   /* Mounted partition name */
  char   devName[32];/* Device mounted on */
  Device device;     /* device number */
  int    lock_fd;    /* File descriptor of this partition
                        if locked; otherwise -1;
                        Not used by the file server */
  int    free;       /* Total number of blocks (1K) presumed
                        available on this partition (accounting
                        for the minfree parameter for the
                        partition).  This is adjusted
                        approximately by the sizes of files
                        and directories read/written, and
                        periodically the superblock is read and
                        this is recomputed.  This number can
                        be negative, if the partition starts
                        out too full */
  int    totalUsable;/* Total number of blocks available on this
                        partition, taking into account the minfree
                        parameter for the partition (see the
                        4.2bsd command tunefs, but note that the
                        bug mentioned there--that the superblock
                        is not reread--does not apply here.  The
                        superblock is re-read periodically by
                        VSetPartitionDiskUsage().) */
  int    minFree;    /* Percentage to be kept free, as last read
                        from the superblock */
\};
}}}
These are the procedures:

\bold{\indent{VInitPartition(path, devname, dev)
    char *path;
    char *devname;
    Device dev;}}

A partition structure is created for the specified partition, and added to the list of partitions maintained by this package.  This is called automatically by \italic{VInitVolumePackage} for all of the Andrew File System partitions on the server.

\indent{\bold{struct DiskPartition *VGetPartition(name)
    char *name;}}

A pointer to the structure representing the named partition is returned.

\bold{\indent{VSetPartitionDiskUsage(dp)
    struct DiskPartition *dp;}}

The superblock of the specified disk partition is consulted, and the appropriate parameters within the disk partition structure are updated.  This should be called periodically by the File Manager, which maintains estimates of the resources used by each partition by calling \italic{VAdjustDiskUsage} on each file system operation.

\bold{\indent{VResetDiskUsage()}}

This routine calls \italic{VSetPartitionDiskUsage} for each known disk partition, and calls \italic{LWP_DispatchProcess} between each of these calls.
\bold{
\indent{VAdjustDiskUsage(ec, vp, blocks)
    Error *ec;
    Volume *vp;
    int blocks;}}

This routine is used by the File Manager to adjust the estimate of the number of blocks used within a disk partition by the number of blocks specified (up or down).  This number is applied against the volume quota of the volume \italic{vp}, and if it would exceed the quota, the error code \italic{VOVERQUOTA} is returned.  If the disk partition would be full to within the percentage margin specified in the superblock, the request is refused and the error \italic{VDISKFULL} is returned.
\indent{
}\bold{\indent{VGetPartitionStatus(vp, totalBlocks, freeBlocks)
    Volume *vp;
    int *totalBlocks;
    int *freeBlocks;}}

The total number of usable file system blocks on the partition containing volume \italic{vp}, and the total usable free blocks are returned in \italic{*totalBlocks} and \italic{*freeBlocks}, respectively.

\bold{\indent{VPrintDiskStats()}}

For each known partition, the statistics for that partition are printed.  These include the number of usable blocks allocated to the partition and the number of free or overallocated blocks.

\bold{\indent{VLockPartition(name)
    char *name;}}

The indicated partition is locked by opening the mount point for the partition and obtaining a UNIX advisory lock for it.  See the discussion of partition locks above.  This is done automatically for volume utilities by the volume package.

\bold{\indent{VUnlockPartition(name)
    char *name;}}

Unlocks a lock obtained with \italic{VLockPartition}.

\subpara{File Manager Volume Synchronization Procedures}

The following procedures are used by volume utility programs to advise the File Manager of their manipulation of volumes.  These procedures are generally invoked on the behalf of the volume utility by the routines listed in the volume procedures section above.

\bold{\leftindent{FSYNC_clientInit()}}

This routine intitializes a connection with the File Manager synchronization routines provided by this package.  This routine is invoked by VInitVolumePackage, and VConnectFS.

\bold{\leftindent{FSYNC_clientFinis()}}

This routine closes a connection with the File Manager synchronization routines provided by this package.  This routine is invoked by VDisconnectFS.  Exiting the program does just as good a job.

\bold{\leftindent{int FSYNC_askfs(volume, com, reason)
    VolumeId volume;
    int com, reason;}}

This sends a simple message to the File Manager.  The message concerns the specified \italic{volume} number, for which the specified command, \italic{com}, is to be applied for the \italic{reason} specified.  The possible commands are:

\italic{\leftindent{FSYNC_ON}}\leftindent{:  the volume should be put online by the File Manager.
\italic{
FSYNC_OFF}:  the volume should go offline.
\italic{
FSYNC_LISTVOLUMES}:  \leftindent{the File Manager should recompute the local volume list for that machine (this is written to /vice/vol/VolumeList).}
\italic{
FSYNC_NEEDVOLUME}:  \leftindent{the volume should be put in the mode specified by \italic{reason.}  This command essentially obsoletes \italic{FSYNC_ON} and \italic{FSYNC_OFF}.}

FSYNC_MOVEVOLUME:  \leftindent{generate temporary relocation information for this volume to another site; this is used by the vol-dump program when it is cooperating with the vol-restore program to move a volume between two sites.}
}
The \italic{reason} parameter is currently ignored unless \italic{com} is \italic{FSYNC_NEEDVOLUME or FSYNC_MOVEVOLUME.}  In the former case, the possible values for \italic{reason} are \italic{V_READONLY, V_CLONE, V_DUMP} and \italic{V_UPDATE,} the semantics of which are as specified in the discussion of \italic{VAttachVolume}.  In the latter case, the "reason" is the IP address of the site the volume was moved to.  This is remembered as the relocation site for the volume for the \italic{FSYNC_CheckRelocationSite} procedure call.

The possible return values from this routine are \italic{FSYNC_OK} and \italic{FSYNC_DENIED}, which pretty well mean what you'd think.  For most purposes, the automatic calling of this routine by VAttachVolume and VDetachVolume will suffice.

Lumped into this package is a routine to deal with volume relocation:

\bold{\leftindent{unsigned int FSYNC_CheckRelocationSite(volumeId)
    VolumeId volumeId;
    }}
Checks the set of temporary volume relocations setup by a for the specified volume by the receipt of \italic{FSYNC_MOVEVOLUME} messages.  If the volume has been relocated, the IP address of the new site is returned, otherwise 0.  This routine is called by the File Manager or by the volume package on the File Manager's behalf.  Temporary relocations are only kept for a small amount of time, roughly an hour, or until there are too many relocations.  These parameters are defined in fssync.c.

\formatnote{.bp}
\enddata{text,268771096}
