splint-fileserver-volserver-cleanup-20030602
[openafs.git] / src / vol / volume.h
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11         System:         VICE-TWO
12         Module:         volume.h
13         Institution:    The Information Technology Center, Carnegie-Mellon University
14
15  */
16
17 #ifndef __volume_h
18 #define __volume_h  1
19
20 #include <afs/afssyscalls.h>
21 #include "voldefs.h"
22 #include "ihandle.h"
23 #define VolumeWriteable(vp)             (V_type(vp)==readwriteVolume)
24 #define VolumeWriteable2(vol)           (vol.type == readwriteVolume)
25 typedef bit32                           FileOffset; /* Offset in this file */
26 #define Date afs_uint32
27
28 #ifdef AFS_PTHREAD_ENV
29 #include <assert.h>
30 #include <pthread.h>
31 extern pthread_mutex_t vol_glock_mutex;
32 extern pthread_mutex_t vol_attach_mutex;
33 extern pthread_cond_t vol_put_volume_cond;
34 extern pthread_cond_t vol_sleep_cond;
35 #define VATTACH_LOCK \
36     assert(pthread_mutex_lock(&vol_attach_mutex) == 0);
37 #define VATTACH_UNLOCK \
38     assert(pthread_mutex_unlock(&vol_attach_mutex) == 0);
39 #define VOL_LOCK \
40     assert(pthread_mutex_lock(&vol_glock_mutex) == 0);
41 #define VOL_UNLOCK \
42     assert(pthread_mutex_unlock(&vol_glock_mutex) == 0);
43 #else /* AFS_PTHREAD_ENV */
44 #define VATTACH_LOCK
45 #define VATTACH_UNLOCK
46 #define VOL_LOCK
47 #define VOL_UNLOCK
48 #endif /* AFS_PTHREAD_ENV */
49
50 typedef enum {fileServer, volumeUtility, salvager} ProgramType;
51 extern ProgramType programType; /* The type of program using the package */
52
53 /* Some initialization parameters for the volume package */
54 /* Add new initialization parameters here */
55 extern int (*V_BreakVolumeCallbacks)();
56 extern int (*vol_PollProc)();
57 #define DOPOLL  ((vol_PollProc)? (*vol_PollProc)() : 0)
58
59 struct versionStamp {           /* Version stamp for critical volume files */
60     bit32       magic;          /* Magic number */
61     bit32       version;        /* Version number of this file, or software
62                                    that created this file */
63 };
64
65 /* Magic numbers and version stamps for each type of file */
66 #define VOLUMEHEADERMAGIC       ((bit32)0x88a1bb3c)
67 #define VOLUMEINFOMAGIC         ((bit32)0x78a1b2c5)
68 #define SMALLINDEXMAGIC         0x99776655
69 #define LARGEINDEXMAGIC         0x88664433
70 #define MOUNTMAGIC              0x9a8b7c6d
71 #define ACLMAGIC                0x88877712
72 #define LINKTABLEMAGIC          0x99877712
73
74 #define VOLUMEHEADERVERSION     1
75 #define VOLUMEINFOVERSION       1
76 #define SMALLINDEXVERSION       1
77 #define LARGEINDEXVERSION       1
78 #define MOUNTVERSION            1
79 #define ACLVERSION              1
80 #define LINKTABLEVERSION        1
81
82 /*
83  * Define whether we are keeping detailed statistics on volume dealings.
84  */
85 #define OPENAFS_VOL_STATS       1
86
87 #if OPENAFS_VOL_STATS
88 /*
89  * Define various indices and counts used in keeping volume-level statistics.
90  */
91 #define VOL_STATS_NUM_RWINFO_FIELDS 4
92
93 #define VOL_STATS_SAME_NET      0       /*Within same site (total)*/
94 #define VOL_STATS_SAME_NET_AUTH 1       /*Within same site (authenticated);
95                                           (must be 1 more than above)*/
96 #define VOL_STATS_DIFF_NET      2       /*From external site (total)*/
97 #define VOL_STATS_DIFF_NET_AUTH 3       /*From external site (authenticated)
98                                           (must be 1 more than above)*/
99
100 #define VOL_STATS_NUM_TIME_RANGES 6
101
102 #define VOL_STATS_TIME_CAP_0        60  /*60 seconds*/
103 #define VOL_STATS_TIME_CAP_1       600  /*10 minutes, in seconds*/
104 #define VOL_STATS_TIME_CAP_2      3600  /*1 hour, in seconds*/
105 #define VOL_STATS_TIME_CAP_3     86400  /*1 day, in seconds*/
106 #define VOL_STATS_TIME_CAP_4    604800  /*1 week, in seconds*/
107
108 #define VOL_STATS_NUM_TIME_FIELDS 6
109
110 #define VOL_STATS_TIME_IDX_0    0       /*0 secs to 60 secs*/
111 #define VOL_STATS_TIME_IDX_1    1       /*1 min to 10 mins*/
112 #define VOL_STATS_TIME_IDX_2    2       /*10 mins to 60 mins*/
113 #define VOL_STATS_TIME_IDX_3    3       /*1 hr to 24 hrs*/
114 #define VOL_STATS_TIME_IDX_4    4       /*1 day to 7 days*/
115 #define VOL_STATS_TIME_IDX_5    5       /*Greater than 1 week*/
116 #endif /* OPENAFS_VOL_STATS */
117
118 /* Volume header.  This is the contents of the named file representing
119  * the volume.  Read-only by the file server!
120  */
121 typedef struct VolumeHeader {
122     struct versionStamp stamp;/* Must be first field */
123     VolumeId    id;           /* Volume number */
124     VolumeId    parent;       /* Read-write volume number (or this volume
125                                  number if this is a read-write volume) */
126     Inode       volumeInfo;
127     Inode       smallVnodeIndex;
128     Inode       largeVnodeIndex;
129     Inode       volumeAcl;
130     Inode       volumeMountTable;
131     Inode       linkTable;
132 } VolumeHeader_t;
133
134
135 typedef struct VolumeDiskHeader {
136     struct versionStamp stamp;/* Must be first field */
137     VolumeId    id;           /* Volume number */
138     VolumeId    parent;       /* Read-write volume number (or this volume
139                                  number if this is a read-write volume) */
140     afs_int32       volumeInfo_lo;
141     afs_int32       smallVnodeIndex_lo;
142     afs_int32       largeVnodeIndex_lo;
143     afs_int32       volumeAcl_lo;
144     afs_int32       volumeMountTable_lo;
145     afs_int32   volumeInfo_hi;
146     afs_int32   smallVnodeIndex_hi;
147     afs_int32   largeVnodeIndex_hi;
148     afs_int32   volumeAcl_hi;
149     afs_int32   volumeMountTable_hi;
150     afs_int32   linkTable_lo;
151     afs_int32   linkTable_hi;
152     /* If you add fields, add them before here and reduce the size of  array */
153     bit32       reserved[3];
154 } VolumeDiskHeader_t;
155
156 /* A vnode index file header */
157 struct IndexFileHeader {
158     struct versionStamp stamp;
159 };
160
161
162 /******************************************************************************/
163 /* Volume Data which is stored on disk and can also be maintained in memory.  */
164 /******************************************************************************/
165 typedef struct VolumeDiskData {
166     struct versionStamp stamp;  /* Must be first field */
167     VolumeId    id;             /* Volume id--unique over all systems */
168 #define VNAMESIZE 32            /* including 0 byte */
169     char        name[VNAMESIZE];/* Unofficial name for the volume */
170     byte        inUse;          /* Volume is being used (perhaps it is online),
171                                    or the system crashed while it was used */
172     byte        inService;      /* Volume in service, not necessarily on line
173                                    This bit is set by an operator/system
174                                    programmer.  Manually taking a volume offline
175                                    always clears the inService bit. Taking
176                                    it out of service also takes it offline */
177     byte        blessed;        /* Volume is administratively blessed with
178                                    the ability to go on line.  Set by a system
179                                    administrator. Clearing this bit will
180                                    take the volume offline */
181     byte        needsSalvaged;  /* Volume needs salvaged--an unrecoverable
182                                    error occured to the volume.  Note:  a volume
183                                    may still require salvage even if this
184                                    flag isn't set--e.g. if a system crash
185                                    occurred while the volume was on line. */
186     bit32       uniquifier;     /* Next vnode uniquifier for this volume */
187     int         type;           /* */
188     VolId       parentId;       /* Id of parent, if type==readonly */
189     VolId       cloneId;        /* Latest read-only clone, if type==readwrite,
190                                    0 if the volume has never been cloned.  Note: the
191                                    indicated volume does not necessarily exist (it
192                                    may have been deleted since cloning). */
193     VolId       backupId;       /* Latest backup copy of this read write volume */
194     VolId       restoredFromId; /* The id in the dump this volume was restored from--used simply
195                                    to make sure that an incremental dump is not restored on top
196                                    of something inappropriate:  Note:  this field itself is NEVER
197                                    dumped!!! */
198     byte        needsCallback;  /* Set by the salvager if anything was changed
199                                    about the volume.  Note:  this is not set by
200                                    clone/makebackups when setting the copy-on-write
201                                    flag in directories; this flag is not seen by
202                                    the clients. */
203 #define DESTROY_ME      0xD3
204     byte        destroyMe;      /* If this is set to DESTROY_ME, then the salvager should destroy
205                                    this volume; it is bogus (left over from an aborted  volume move,
206                                    for example).  Note:  if this flag is on, then inService should
207                                    be OFF--only the salvager checks this flag */
208 #ifdef ALPHA_DUX40_ENV
209 #define DONT_SALVAGE    0xE6
210 #else /* ALPHA_DUX40_ENV */
211 #define DONT_SALVAGE    0xE5
212 #endif /* ALPHA_DUX40_ENV */
213     byte        dontSalvage;    /* If this is on, then don't bother salvaging this volume*/
214     byte        reserveb3;
215
216     bit32       reserved1[6];
217
218
219     /* Administrative stuff */
220     int         maxquota;       /* Quota maximum, 1K blocks */
221     int         minquota;       /* Quota minimum, 1K blocks */
222     int         maxfiles;       /* Maximum number of files (i.e. inodes) */
223     bit32       accountNumber;  /* Uninterpreted account number */
224     bit32       owner;          /* The person administratively responsible
225                                    for this volume */
226     int         reserved2[8];   /* Other administrative constraints */
227
228     /* Resource usage & statistics */
229     int         filecount;      /* Actual number of files */
230     int         diskused;       /* Actual disk space used, 1K blocks */
231     int         dayUse;         /* Metric for today's usage of this volume so far */
232     int         weekUse[7];     /* Usage of the volume for the last week.
233                                    weekUse[0] is for most recent complete 24 hour period
234                                    of measurement; week[6] is 7 days ago */
235     Date        dayUseDate;     /* Date the dayUse statistics refer to; the week use stats
236                                    are the preceding 7 days */
237     int         reserved3[11];  /* Other stats here */
238     
239     /* Server supplied dates */
240     Date        creationDate;   /* Creation date for a read/write
241                                    volume; cloning date for original copy of
242                                    a readonly volume (replicated volumes have
243                                    the same creation date) */
244     Date        accessDate;     /* Last access time by a user, large granularity */
245     Date        updateDate;     /* Last modification by user */
246     Date        expirationDate; /* 0 if it never expires */
247     Date        backupDate;     /* last time a backup clone was taken */
248
249     /* Time that this copy of this volume was made.  NEVER backed up.  This field is only
250        set when the copy is created */
251     Date        copyDate;
252
253 #if OPENAFS_VOL_STATS
254     bit32       stat_initialized;  /*Are the stat fields below set up?*/
255     bit32       reserved4[7];
256 #else
257     bit32       reserved4[8];
258 #endif /* OPENAFS_VOL_STATS */
259
260     /* messages */
261 #define VMSGSIZE 128
262     char        offlineMessage[VMSGSIZE]; /* Why the volume is offline */
263 #if OPENAFS_VOL_STATS
264 #define VOL_STATS_BYTES 128
265    /*
266     * Keep per-volume aggregate statistics on type and distance of access,
267     * along with authorship info.
268     */
269    bit32        stat_reads[VOL_STATS_NUM_RWINFO_FIELDS];
270    bit32        stat_writes[VOL_STATS_NUM_RWINFO_FIELDS];
271    bit32        stat_fileSameAuthor[VOL_STATS_NUM_TIME_FIELDS];
272    bit32        stat_fileDiffAuthor[VOL_STATS_NUM_TIME_FIELDS];
273    bit32        stat_dirSameAuthor[VOL_STATS_NUM_TIME_FIELDS];
274    bit32        stat_dirDiffAuthor[VOL_STATS_NUM_TIME_FIELDS];
275 #else
276     char        motd[VMSGSIZE];           /* Volume "message of the day" */
277 #endif /* OPENAFS_VOL_STATS */
278
279 } VolumeDiskData;
280
281
282 /**************************************/
283 /* Memory resident volume information */
284 /**************************************/
285 typedef struct Volume {
286     struct      Volume  *hashNext; /* Next in hash resolution table */
287     VolumeId    hashid;         /* Volume number -- for hash table lookup */
288     struct      volHeader *header; /* Cached disk data */
289     Device      device;         /* Unix device for the volume */ 
290     struct DiskPartition
291                 *partition;     /* Information about the Unix partition */
292     struct vnodeIndex {
293       IHandle_t *handle;        /* Unix inode holding this index */
294       byte      *bitmap;        /* Index bitmap */
295       afs_uint32        bitmapSize;     /* length of bitmap, in bytes */
296       afs_uint32        bitmapOffset;   /* Which byte address of the first long to
297                                    start search from in bitmap */
298     } vnodeIndex[nVNODECLASSES];
299     IHandle_t   *linkHandle;
300     Unique      nextVnodeUnique;/* Derived originally from volume uniquifier.
301                                    This is the actual next version number to
302                                    assign; the uniquifier is bumped by 200 and
303                                    and written to disk every 200 file creates
304                                    If the volume is shutdown gracefully, the
305                                    uniquifier should be rewritten with the
306                                    value nextVnodeVersion*/
307     IHandle_t   *diskDataHandle;/* Unix inode holding general volume info */
308     bit16       vnodeHashOffset;/* Computed by HashOffset function in vnode.h.
309                                    Assigned to the volume when initialized. 
310                                    Added to vnode number for hash table index */
311     byte        shuttingDown;   /* This volume is going to be detached */
312     byte        goingOffline;   /* This volume is going offline */
313     bit32       cacheCheck;     /* Online sequence number to be used to invalidate vnode cache entries
314                                    that stayed around while a volume was offline */
315     short       nUsers;         /* Number of users of this volume header */
316     byte        needsPutBack;   /* For a volume utility, this flag is set if we need
317                                    to give the volume back when we detach it.  The server has
318                                    certain modes where it doesn't detach the volume, and
319                                    if we give it back spuriously, the server aborts.  This field
320                                    is meaningless on the file server */
321     byte        specialStatus;  /* An error code to return on VGetVolume: the
322                                    volume is unavailable for the reason quoted,
323                                    currently VBUSY or VMOVED */
324     afs_uint32  updateTime;     /* Time that this volume was put on the updated
325                                    volume list--the list of volumes that will be
326                                    salvaged should the file server crash */
327 } Volume;
328
329 struct volHeader {
330     struct volHeader *prev, *next;/* LRU pointers */
331     VolumeDiskData diskstuff;   /* General volume info read from disk */
332     Volume *back;               /* back pointer to current volume structure */
333 };
334
335 /* These macros are used to export fields within the volume header.  This was added
336    to facilitate changing the actual representation */
337
338 #define V_device(vp)            ((vp)->device)
339 #define V_partition(vp)         ((vp)->partition)
340 #define V_diskDataHandle(vp)    ((vp)->diskDataHandle)
341 #define V_vnodeIndex(vp)        ((vp)->vnodeIndex)
342 #define V_nextVnodeUnique(vp)   ((vp)->nextVnodeUnique)
343 #define V_linkHandle(vp)        ((vp)->linkHandle)
344
345 /* N.B. V_id must be this, rather than vp->id, or some programs will break, probably */
346 #define V_stamp(vp)             ((vp)->header->diskstuff.stamp)
347 #define V_id(vp)                ((vp)->header->diskstuff.id)
348 #define V_name(vp)              ((vp)->header->diskstuff.name)
349 #define V_inUse(vp)             ((vp)->header->diskstuff.inUse)
350 #define V_inService(vp)         ((vp)->header->diskstuff.inService)
351 #define V_blessed(vp)           ((vp)->header->diskstuff.blessed)
352 #define V_needsSalvaged(vp)     ((vp)->header->diskstuff.needsSalvaged)
353 #define V_uniquifier(vp)        ((vp)->header->diskstuff.uniquifier)
354 #define V_type(vp)              ((vp)->header->diskstuff.type)
355 #define V_parentId(vp)          ((vp)->header->diskstuff.parentId)
356 #define V_cloneId(vp)           ((vp)->header->diskstuff.cloneId)
357 #define V_backupId(vp)          ((vp)->header->diskstuff.backupId)
358 #define V_restoredFromId(vp)    ((vp)->header->diskstuff.restoredFromId)
359 #define V_needsCallback(vp)     ((vp)->header->diskstuff.needsCallback)
360 #define V_destroyMe(vp)         ((vp)->header->diskstuff.destroyMe)
361 #define V_dontSalvage(vp)       ((vp)->header->diskstuff.dontSalvage)
362 #define V_maxquota(vp)          ((vp)->header->diskstuff.maxquota)
363 #define V_minquota(vp)          ((vp)->header->diskstuff.minquota)
364 #define V_maxfiles(vp)          ((vp)->header->diskstuff.maxfiles)
365 #define V_accountNumber(vp)     ((vp)->header->diskstuff.accountNumber)
366 #define V_owner(vp)             ((vp)->header->diskstuff.owner)
367 #define V_filecount(vp)         ((vp)->header->diskstuff.filecount)
368 #define V_diskused(vp)          ((vp)->header->diskstuff.diskused)
369 #define V_dayUse(vp)            ((vp)->header->diskstuff.dayUse)
370 #define V_weekUse(vp)           ((vp)->header->diskstuff.weekUse)
371 #define V_dayUseDate(vp)        ((vp)->header->diskstuff.dayUseDate)
372 #define V_creationDate(vp)      ((vp)->header->diskstuff.creationDate)
373 #define V_accessDate(vp)        ((vp)->header->diskstuff.accessDate)
374 #define V_updateDate(vp)        ((vp)->header->diskstuff.updateDate)
375 #define V_expirationDate(vp)    ((vp)->header->diskstuff.expirationDate)
376 #define V_backupDate(vp)        ((vp)->header->diskstuff.backupDate)
377 #define V_copyDate(vp)          ((vp)->header->diskstuff.copyDate)
378 #define V_offlineMessage(vp)    ((vp)->header->diskstuff.offlineMessage)
379 #define V_disk(vp)              ((vp)->header->diskstuff)
380 #define V_motd(vp)              ((vp)->header->diskstuff.motd)
381 #if OPENAFS_VOL_STATS
382 #define V_stat_initialized(vp)  ((vp)->header->diskstuff.stat_initialized)
383 #define V_stat_area(vp)         (((vp)->header->diskstuff.stat_reads))
384 #define V_stat_reads(vp, idx)   (((vp)->header->diskstuff.stat_reads)[idx])
385 #define V_stat_writes(vp, idx)  (((vp)->header->diskstuff.stat_writes)[idx])
386 #define V_stat_fileSameAuthor(vp, idx) (((vp)->header->diskstuff.stat_fileSameAuthor)[idx])
387 #define V_stat_fileDiffAuthor(vp, idx) (((vp)->header->diskstuff.stat_fileDiffAuthor)[idx])
388 #define V_stat_dirSameAuthor(vp, idx)  (((vp)->header->diskstuff.stat_dirSameAuthor)[idx])
389 #define V_stat_dirDiffAuthor(vp, idx)  (((vp)->header->diskstuff.stat_dirDiffAuthor)[idx])
390 #endif /* OPENAFS_VOL_STATS */
391
392 /* File offset computations.  The offset values in the volume header are
393    computed with these macros -- when the file is written only!! */
394 #define VOLUME_MOUNT_TABLE_OFFSET(Volume)       (sizeof (VolumeDiskData))
395 #define VOLUME_BITMAP_OFFSET(Volume)    \
396         (sizeof (VolumeDiskData) + (Volume)->disk.mountTableSize)
397
398
399 extern char *VSalvageMessage;   /* Canonical message when a volume is forced
400                                    offline */
401 extern Volume * VGetVolume();
402 extern Volume * VGetVolume_r();
403 extern void VPutVolume(Volume *);
404 extern void VPutVolume_r(Volume *);
405 extern void VOffline(Volume *vp, char *message);
406 extern void VOffline_r(Volume *vp, char *message);
407 extern int VConnectFS(void);
408 extern int VConnectFS_r(void);
409 extern Volume * VAttachVolume();
410 extern Volume * VAttachVolume_r();
411 extern Volume * VCreateVolume();
412 extern Volume * VCreateVolume_r();
413 extern VnodeId VAllocBitmapEntry(Error *ec, Volume *vp,
414                                  struct vnodeIndex *index);
415 extern VnodeId VAllocBitmapEntry_r(Error *ec, Volume *vp,
416                                    struct vnodeIndex *index);
417 extern void VFreeBitMapEntry(Error *ec, register struct vnodeIndex *index,
418                              unsigned bitNumber);
419 extern void VFreeBitMapEntry_r(Error *ec, register struct vnodeIndex *index,
420                                unsigned bitNumber);
421 extern int VolumeNumber();
422 extern int VolumeNumber_r();
423 extern char * VolumeExternalName();
424 extern char * VolumeExternalName_r();
425 extern Volume * VAttachVolumeByName();
426 extern Volume * VAttachVolumeByName_r();
427 extern void VShutdown(void);
428 extern void VUpdateVolume(Error *ec,Volume *vp);
429 extern void VUpdateVolume_r(Error *ec,Volume *vp);
430 extern void VAddToVolumeUpdateList(Error *ec, Volume *vp);
431 extern void VAddToVolumeUpdateList_r(Error *ec, Volume *vp);
432 extern void VDetachVolume(Error *ec, Volume *vp);
433 extern void VDetachVolume_r(Error *ec, Volume *vp);
434 extern void VForceOffline(Volume *vp);
435 extern void VForceOffline_r(Volume *vp);
436 extern void VBumpVolumeUsage(register Volume *vp);
437 extern void VBumpVolumeUsage_r(register Volume *vp);
438 extern void VSetDiskUsage(void);
439 extern void VPrintCacheStats(void);
440 extern void VReleaseVnodeFiles_r(Volume *vp);
441 extern void VCloseVnodeFiles_r(Volume *vp);
442 extern struct DiskPartition *VGetPartition(char *name, int abortp);
443 extern struct DiskPartition *VGetPartition_r(char *name, int abortp);
444 extern int VInitVolumePackage(ProgramType pt, int nLargeVnodes,
445                               int nSmallVnodes,
446                               int connect, int volcache);
447 extern void DiskToVolumeHeader(VolumeHeader_t *h, VolumeDiskHeader_t *dh);
448 extern void VolumeHeaderToDisk(VolumeDiskHeader_t *dh, VolumeHeader_t *h);
449
450
451 /* Naive formula relating number of file size to number of 1K blocks in file */
452 /* Note:  we charge 1 block for 0 length files so the user can't store
453    an inifite number of them; for most files, we give him the inode, vnode,
454    and indirect block overhead, for FREE! */
455 #define nBlocks(bytes) ((bytes) == 0? 1: ((bytes)+1023)/1024)
456
457 /* Client process id -- file server sends a Check volumes signal back to the client at this pid */
458 #define CLIENTPID       "/vice/vol/clientpid"
459
460 /* Modes of attachment, for VAttachVolume[ByName] to convey to the file server */
461 #define V_READONLY 1    /* Absolutely no updates will be done to the volume */
462 #define V_CLONE    2    /* Cloning the volume:  if it is read/write, then directory
463                            version numbers will change.  Header will be updated.  If
464                            the volume is read-only, the file server may continue to
465                            server it; it may also continue to server it in read/write
466                            mode if the writes are deferred */
467 #define V_VOLUPD   3    /* General update or volume purge is possible.  Volume must
468                            go offline */
469 #define V_DUMP     4    /* A dump of the volume is requested; the volume can be served
470                            read-only during this time */
471 #define V_SECRETLY 5    /* Secret attach of the volume.  This is used to attach a volume
472                            which the file server doesn't know about--and which it shouldn't
473                            know about yet, since the volume has just been created and
474                            is somewhat bogus.  Required to make sure that a file server
475                            never knows about more than one copy of the same volume--when
476                            a volume is moved from one partition to another on a single
477                            server */
478
479 #if     defined(NEARINODE_HINT)
480 #define V_pref(vp,nearInode)  nearInodeHash(V_id(vp),(nearInode)); (nearInode) %= V_partition(vp)->f_files 
481 #else                   
482 #define V_pref(vp,nearInode)   nearInode = 0 
483 #endif                  /* NEARINODE_HINT */
484
485 #endif /* __volume_h */