viced: Add options for interrupting clients
[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  * Portions Copyright (c) 2006-2008 Sine Nomine Associates
10  */
11
12 /*
13         System:         VICE-TWO
14         Module:         volume.h
15         Institution:    The Information Technology Center, Carnegie-Mellon University
16
17  */
18
19 #ifndef __volume_h
20 #define __volume_h  1
21
22 #include <afs/afssyscalls.h>
23 #include "voldefs.h"
24 #include "ihandle.h"
25 #define VolumeWriteable(vp)             (V_type(vp)==readwriteVolume)
26 #define VolumeWriteable2(vol)           (vol.type == readwriteVolume)
27 typedef bit32 FileOffset;       /* Offset in this file */
28 #define Date afs_uint32
29 #include "daemon_com.h"
30 #include "fssync.h"
31
32 #if 0
33 /** turn this on if you suspect a volume package locking bug */
34 #define VOL_LOCK_DEBUG 1
35 #endif
36
37 #ifdef VOL_LOCK_DEBUG
38 #define VOL_LOCK_ASSERT_HELD \
39     osi_Assert(vol_glock_holder == pthread_self())
40 #define VOL_LOCK_ASSERT_UNHELD \
41     osi_Assert(vol_glock_holder == 0)
42 #define _VOL_LOCK_SET_HELD \
43     vol_glock_holder = pthread_self()
44 #define _VOL_LOCK_SET_UNHELD \
45     vol_glock_holder = 0
46 #define VOL_LOCK_DBG_CV_WAIT_END \
47     do { \
48         VOL_LOCK_ASSERT_UNHELD; \
49         _VOL_LOCK_SET_HELD; \
50     } while(0)
51 #define VOL_LOCK_DBG_CV_WAIT_BEGIN \
52     do { \
53          VOL_LOCK_ASSERT_HELD; \
54          _VOL_LOCK_SET_UNHELD; \
55     } while(0)
56 #else
57 #define VOL_LOCK_ASSERT_HELD
58 #define VOL_LOCK_ASSERT_UNHELD
59 #define VOL_LOCK_DBG_CV_WAIT_BEGIN
60 #define VOL_LOCK_DBG_CV_WAIT_END
61 #endif
62
63
64 #ifdef AFS_PTHREAD_ENV
65 #include <pthread.h>
66 extern pthread_mutex_t vol_glock_mutex;
67 extern pthread_mutex_t vol_trans_mutex;
68 extern pthread_cond_t vol_put_volume_cond;
69 extern pthread_cond_t vol_sleep_cond;
70 extern pthread_cond_t vol_vinit_cond;
71 extern ih_init_params vol_io_params;
72 extern int vol_attach_threads;
73 #ifdef VOL_LOCK_DEBUG
74 extern pthread_t vol_glock_holder;
75 #define VOL_LOCK \
76     do { \
77         MUTEX_ENTER(&vol_glock_mutex); \
78         VOL_LOCK_ASSERT_UNHELD; \
79         _VOL_LOCK_SET_HELD; \
80     } while (0)
81 #define VOL_UNLOCK \
82     do { \
83         VOL_LOCK_ASSERT_HELD; \
84         _VOL_LOCK_SET_UNHELD; \
85         MUTEX_EXIT(&vol_glock_mutex); \
86     } while (0)
87 #define VOL_CV_WAIT(cv) \
88     do { \
89         VOL_LOCK_DBG_CV_WAIT_BEGIN; \
90         CV_WAIT((cv), &vol_glock_mutex); \
91         VOL_LOCK_DBG_CV_WAIT_END; \
92     } while (0)
93 #else /* !VOL_LOCK_DEBUG */
94 #define VOL_LOCK MUTEX_ENTER(&vol_glock_mutex)
95 #define VOL_UNLOCK MUTEX_EXIT(&vol_glock_mutex)
96 #define VOL_CV_WAIT(cv) CV_WAIT((cv), &vol_glock_mutex)
97 #endif /* !VOL_LOCK_DEBUG */
98
99 /**
100  * @param[in] cv cond var
101  * @param[in] ts deadline, or NULL to wait forever
102  * @param[out] timedout  set to 1 if we returned due to the deadline, 0 if we
103  *                       returned due to the cond var getting signalled. If
104  *                       NULL, it is ignored.
105  */
106 static_inline void
107 VOL_CV_TIMEDWAIT(pthread_cond_t *cv, const struct timespec *ts, int *timedout)
108 {
109     int code;
110     if (timedout) {
111         *timedout = 0;
112     }
113     if (!ts) {
114         VOL_CV_WAIT(cv);
115         return;
116     }
117     VOL_LOCK_DBG_CV_WAIT_BEGIN;
118     code = CV_TIMEDWAIT(cv, &vol_glock_mutex, ts);
119     VOL_LOCK_DBG_CV_WAIT_END;
120     if (code == ETIMEDOUT) {
121         code = 0;
122         if (timedout) {
123             *timedout = 1;
124         }
125     }
126     osi_Assert(code == 0);
127 }
128
129 #define VSALVSYNC_LOCK MUTEX_ENTER(&vol_salvsync_mutex)
130 #define VSALVSYNC_UNLOCK MUTEX_EXIT(&vol_salvsync_mutex)
131 #define VTRANS_LOCK MUTEX_ENTER(&vol_trans_mutex)
132 #define VTRANS_UNLOCK MUTEX_EXIT(&vol_trans_mutex)
133 #else /* AFS_PTHREAD_ENV */
134 #define VOL_LOCK
135 #define VOL_UNLOCK
136 #define VSALVSYNC_LOCK
137 #define VSALVSYNC_UNLOCK
138 #define VTRANS_LOCK
139 #define VTRANS_UNLOCK
140 #endif /* AFS_PTHREAD_ENV */
141
142 /**
143  * volume package program type enumeration.
144  */
145 typedef enum {
146     fileServer          = 1,    /**< the fileserver process */
147     volumeUtility       = 2,    /**< any miscellaneous volume utility */
148     salvager            = 3,    /**< standalone whole-partition salvager */
149     salvageServer       = 4,    /**< dafs online salvager */
150     debugUtility        = 5,    /**< fssync-debug or similar utility */
151     volumeServer        = 6,    /**< the volserver process */
152     volumeSalvager      = 7     /**< the standalone single-volume salvager */
153 } ProgramType;
154 extern ProgramType programType; /* The type of program using the package */
155
156 /* Some initialization parameters for the volume package */
157 /* Add new initialization parameters here */
158 extern int (*V_BreakVolumeCallbacks) (VolumeId);
159 extern int (*vol_PollProc) (void);
160
161 #define DOPOLL  ((vol_PollProc)? (*vol_PollProc)() : 0)
162
163 #ifdef AFS_DEMAND_ATTACH_FS
164 /**
165  * variable error return code based upon programType and DAFS presence
166  */
167 #define DAFS_VSALVAGE   ((programType == fileServer) ? VSALVAGING : VSALVAGE)
168 #else
169 #define DAFS_VSALVAGE   (VSALVAGE)
170 #endif
171
172 struct versionStamp {           /* Version stamp for critical volume files */
173     bit32 magic;                /* Magic number */
174     bit32 version;              /* Version number of this file, or software
175                                  * that created this file */
176 };
177
178 #ifdef AFS_DEMAND_ATTACH_FS
179 /**
180  * demand attach volume state enumeration.
181  *
182  * @note values must be contiguous in order for VIsValidState() to work correctly
183  */
184 typedef enum {
185     VOL_STATE_UNATTACHED        = 0,    /**< volume is unattached */
186     VOL_STATE_PREATTACHED       = 1,    /**< volume has been pre-attached */
187     VOL_STATE_ATTACHING         = 2,    /**< volume is transitioning to fully attached */
188     VOL_STATE_ATTACHED          = 3,    /**< volume has been fully attached */
189     VOL_STATE_UPDATING          = 4,    /**< volume is updating on-disk structures */
190     VOL_STATE_GET_BITMAP        = 5,    /**< volume is getting bitmap entries */
191     VOL_STATE_HDR_LOADING       = 6,    /**< volume is loading disk header */
192     VOL_STATE_HDR_ATTACHING     = 7,    /**< volume is getting a header from the LRU */
193     VOL_STATE_SHUTTING_DOWN     = 8,    /**< volume is shutting down */
194     VOL_STATE_GOING_OFFLINE     = 9,    /**< volume is going offline */
195     VOL_STATE_OFFLINING         = 10,   /**< volume is transitioning to offline */
196     VOL_STATE_DETACHING         = 11,   /**< volume is transitioning to detached */
197     VOL_STATE_SALVSYNC_REQ      = 12,   /**< volume is blocked on a salvsync request */
198     VOL_STATE_SALVAGING         = 13,   /**< volume is being salvaged */
199     VOL_STATE_ERROR             = 14,   /**< volume is in an error state */
200     VOL_STATE_VNODE_ALLOC       = 15,   /**< volume is busy allocating a new vnode */
201     VOL_STATE_VNODE_GET         = 16,   /**< volume is busy getting vnode disk data */
202     VOL_STATE_VNODE_CLOSE       = 17,   /**< volume is busy closing vnodes */
203     VOL_STATE_VNODE_RELEASE     = 18,   /**< volume is busy releasing vnodes */
204     VOL_STATE_VLRU_ADD          = 19,   /**< volume is busy being added to a VLRU queue */
205     VOL_STATE_DELETED           = 20,   /**< volume has been deleted by the volserver */
206     VOL_STATE_SALVAGE_REQ       = 21,   /**< volume has been requested to be salvaged,
207                                          *   but is waiting for other users to go away
208                                          *   so it can be offlined */
209     VOL_STATE_SCANNING_RXCALLS  = 22,   /**< volume is scanning vp->rx_call_list
210                                          *   to interrupt RX calls */
211     /* please add new states directly above this line */
212     VOL_STATE_FREED             = 23,   /**< debugging aid */
213     VOL_STATE_COUNT             = 24    /**< total number of valid states */
214 } VolState;
215
216 /**
217  * V_attachFlags bits.
218  */
219 enum VolFlags {
220     VOL_HDR_ATTACHED      = 0x1,     /**< volume header is attached to Volume struct */
221     VOL_HDR_LOADED        = 0x2,     /**< volume header contents are valid */
222     VOL_HDR_IN_LRU        = 0x4,     /**< volume header is in LRU */
223     VOL_IN_HASH           = 0x8,     /**< volume is in hash table */
224     VOL_ON_VBYP_LIST      = 0x10,    /**< volume is on VByP list */
225     VOL_IS_BUSY           = 0x20,    /**< volume is not to be free()d */
226     VOL_ON_VLRU           = 0x40,    /**< volume is on the VLRU */
227     VOL_HDR_DONTSALV      = 0x80,    /**< volume header DONTSALVAGE flag is set */
228     VOL_LOCKED            = 0x100    /**< volume is disk-locked (@see VLockVolumeNB) */
229 };
230
231 /* VPrintExtendedCacheStats flags */
232 #define VOL_STATS_PER_CHAIN   0x1  /**< compute simple per-chain stats */
233 #define VOL_STATS_PER_CHAIN2  0x2  /**< compute per-chain stats that require scanning
234                                     *   every element of the chain */
235
236 /* VLRU_SetOptions options */
237 #define VLRU_SET_THRESH       1
238 #define VLRU_SET_INTERVAL     2
239 #define VLRU_SET_MAX          3
240 #define VLRU_SET_ENABLED      4
241
242 /**
243  * VLRU queue names.
244  */
245 typedef enum {
246     VLRU_QUEUE_NEW        = 0,  /**< LRU queue for new volumes */
247     VLRU_QUEUE_MID        = 1,  /**< survivor generation */
248     VLRU_QUEUE_OLD        = 2,  /**< old generation */
249     VLRU_QUEUE_CANDIDATE  = 3,  /**< soft detach candidate pool */
250     VLRU_QUEUE_HELD       = 4,  /*   volumes which are not allowed
251                                  *   to be soft detached */
252     VLRU_QUEUE_INVALID    = 5   /**< invalid queue id */
253 } VLRUQueueName;
254
255 /* default scanner timing parameters */
256 #define VLRU_DEFAULT_OFFLINE_THRESH (60*60*2) /* 2 hours */
257 #define VLRU_DEFAULT_OFFLINE_INTERVAL (60*2) /* 2 minutes */
258 #define VLRU_DEFAULT_OFFLINE_MAX 8 /* 8 volumes */
259
260
261 /**
262  * DAFS thread-specific options structure
263  */
264 typedef struct VThreadOptions {
265      int disallow_salvsync;     /**< whether or not salvsync calls are allowed
266                                  *   on this thread (deadlock prevention). */
267 } VThreadOptions_t;
268 extern pthread_key_t VThread_key;
269 extern VThreadOptions_t VThread_defaults;
270
271 #endif /* AFS_DEMAND_ATTACH_FS */
272
273 typedef struct VolumePackageOptions {
274     afs_uint32 nLargeVnodes;      /**< size of large vnode cache */
275     afs_uint32 nSmallVnodes;      /**< size of small vnode cache */
276     afs_uint32 volcache;          /**< size of volume header cache */
277
278     afs_int32 canScheduleSalvage; /**< can we schedule salvages? (DAFS) */
279                                   /* (if 'no', we will just error out if we
280                                    * find a bad vol) */
281     afs_int32 canUseFSSYNC;       /**< can we use the FSSYNC channel? */
282     afs_int32 canUseSALVSYNC;     /**< can we use the SALVSYNC channel? (DAFS) */
283     afs_int32 unsafe_attach;      /**< can we bypass checking the inUse vol
284                                    *   header on attach? */
285     void (*interrupt_rxcall) (struct rx_call *call, afs_int32 error);
286                                   /**< callback to interrupt RX calls accessing
287                                    *   a going-offline volume */
288     afs_int32 offline_timeout;    /**< how long (in seconds) to wait before
289                                    *   interrupting RX calls accessing a
290                                    *   going-offline volume. -1 disables,
291                                    *   0 means immediately. */
292     afs_int32 offline_shutdown_timeout;
293                                   /**< how long (in seconds) to wait before
294                                    *   interrupting RX calls accessing a
295                                    *   going-offline volume during shutdown.
296                                    *   -1 disables, 0 means immediately.
297                                    *   Note that the timeout time is calculated
298                                    *   once, when we encounter the first going-
299                                    *   offline volume during shutdown. So if we
300                                    *   encounter multiple going-offline volumes
301                                    *   during shutdown, we will still only wait
302                                    *   for this amount of time in total, not e.g.
303                                    *   for each going-offline volume encountered. */
304 } VolumePackageOptions;
305
306 /* Magic numbers and version stamps for each type of file */
307 #define VOLUMEHEADERMAGIC       ((bit32)0x88a1bb3c)
308 #define VOLUMEINFOMAGIC         ((bit32)0x78a1b2c5)
309 #define SMALLINDEXMAGIC         0x99776655
310 #define LARGEINDEXMAGIC         0x88664433
311 #define MOUNTMAGIC              0x9a8b7c6d
312 #define ACLMAGIC                0x88877712
313 #define LINKTABLEMAGIC          0x99877712
314
315 #define VOLUMEHEADERVERSION     1
316 #define VOLUMEINFOVERSION       1
317 #define SMALLINDEXVERSION       1
318 #define LARGEINDEXVERSION       1
319 #define MOUNTVERSION            1
320 #define ACLVERSION              1
321 #define LINKTABLEVERSION        1
322
323 /*
324  * Define whether we are keeping detailed statistics on volume dealings.
325  */
326 #define OPENAFS_VOL_STATS       1
327
328 #if OPENAFS_VOL_STATS
329 /*
330  * Define various indices and counts used in keeping volume-level statistics.
331  */
332 #define VOL_STATS_NUM_RWINFO_FIELDS 4
333
334 #define VOL_STATS_SAME_NET      0       /*Within same site (total) */
335 #define VOL_STATS_SAME_NET_AUTH 1       /*Within same site (authenticated);
336                                          * (must be 1 more than above) */
337 #define VOL_STATS_DIFF_NET      2       /*From external site (total) */
338 #define VOL_STATS_DIFF_NET_AUTH 3       /*From external site (authenticated)
339                                          * (must be 1 more than above) */
340
341 #define VOL_STATS_NUM_TIME_RANGES 6
342
343 #define VOL_STATS_TIME_CAP_0        60  /*60 seconds */
344 #define VOL_STATS_TIME_CAP_1       600  /*10 minutes, in seconds */
345 #define VOL_STATS_TIME_CAP_2      3600  /*1 hour, in seconds */
346 #define VOL_STATS_TIME_CAP_3     86400  /*1 day, in seconds */
347 #define VOL_STATS_TIME_CAP_4    604800  /*1 week, in seconds */
348
349 #define VOL_STATS_NUM_TIME_FIELDS 6
350
351 #define VOL_STATS_TIME_IDX_0    0       /*0 secs to 60 secs */
352 #define VOL_STATS_TIME_IDX_1    1       /*1 min to 10 mins */
353 #define VOL_STATS_TIME_IDX_2    2       /*10 mins to 60 mins */
354 #define VOL_STATS_TIME_IDX_3    3       /*1 hr to 24 hrs */
355 #define VOL_STATS_TIME_IDX_4    4       /*1 day to 7 days */
356 #define VOL_STATS_TIME_IDX_5    5       /*Greater than 1 week */
357 #endif /* OPENAFS_VOL_STATS */
358
359 /* Volume header.  This is the contents of the named file representing
360  * the volume.  Read-only by the file server!
361  */
362 typedef struct VolumeHeader {
363     struct versionStamp stamp;  /* Must be first field */
364     VolumeId id;                /* Volume number */
365     VolumeId parent;            /* Read-write volume number (or this volume
366                                  * number if this is a read-write volume) */
367     Inode volumeInfo;
368     Inode smallVnodeIndex;
369     Inode largeVnodeIndex;
370     Inode volumeAcl;
371     Inode volumeMountTable;
372     Inode linkTable;
373 } VolumeHeader_t;
374
375
376 typedef struct VolumeDiskHeader {
377     struct versionStamp stamp;  /* Must be first field */
378     VolumeId id;                /* Volume number */
379     VolumeId parent;            /* Read-write volume number (or this volume
380                                  * number if this is a read-write volume) */
381     afs_int32 volumeInfo_lo;
382     afs_int32 smallVnodeIndex_lo;
383     afs_int32 largeVnodeIndex_lo;
384     afs_int32 volumeAcl_lo;
385     afs_int32 volumeMountTable_lo;
386     afs_int32 volumeInfo_hi;
387     afs_int32 smallVnodeIndex_hi;
388     afs_int32 largeVnodeIndex_hi;
389     afs_int32 volumeAcl_hi;
390     afs_int32 volumeMountTable_hi;
391     afs_int32 linkTable_lo;
392     afs_int32 linkTable_hi;
393     /* If you add fields, add them before here and reduce the size of  array */
394     bit32 reserved[3];
395 } VolumeDiskHeader_t;
396
397 /* A vnode index file header */
398 struct IndexFileHeader {
399     struct versionStamp stamp;
400 };
401
402
403 /******************************************************************************/
404 /* Volume Data which is stored on disk and can also be maintained in memory.  */
405 /******************************************************************************/
406 typedef struct VolumeDiskData {
407     struct versionStamp stamp;  /* Must be first field */
408     VolumeId id;                /* Volume id--unique over all systems */
409 #define VNAMESIZE 32            /* including 0 byte */
410     char name[VNAMESIZE];       /* Unofficial name for the volume */
411     byte inUse;                 /* Volume is being used (perhaps it is online),
412                                  * or the system crashed while it was used */
413     byte inService;             /* Volume in service, not necessarily on line
414                                  * This bit is set by an operator/system
415                                  * programmer.  Manually taking a volume offline
416                                  * always clears the inService bit. Taking
417                                  * it out of service also takes it offline */
418     byte blessed;               /* Volume is administratively blessed with
419                                  * the ability to go on line.  Set by a system
420                                  * administrator. Clearing this bit will
421                                  * take the volume offline */
422     byte needsSalvaged;         /* Volume needs salvaged--an unrecoverable
423                                  * error occured to the volume.  Note:  a volume
424                                  * may still require salvage even if this
425                                  * flag isn't set--e.g. if a system crash
426                                  * occurred while the volume was on line. */
427     bit32 uniquifier;           /* Next vnode uniquifier for this volume */
428     int type;                   /* */
429     VolId parentId;             /* Id of parent, if type==readonly */
430     VolId cloneId;              /* Latest read-only clone, if type==readwrite,
431                                  * 0 if the volume has never been cloned.  Note: the
432                                  * indicated volume does not necessarily exist (it
433                                  * may have been deleted since cloning). */
434     VolId backupId;             /* Latest backup copy of this read write volume */
435     VolId restoredFromId;       /* The id in the dump this volume was restored from--used simply
436                                  * to make sure that an incremental dump is not restored on top
437                                  * of something inappropriate:  Note:  this field itself is NEVER
438                                  * dumped!!! */
439     byte needsCallback;         /* Set by the salvager if anything was changed
440                                  * about the volume.  Note:  this is not set by
441                                  * clone/makebackups when setting the copy-on-write
442                                  * flag in directories; this flag is not seen by
443                                  * the clients. */
444 #define DESTROY_ME      0xD3
445     byte destroyMe;             /* If this is set to DESTROY_ME, then the salvager should destroy
446                                  * this volume; it is bogus (left over from an aborted  volume move,
447                                  * for example).  Note:  if this flag is on, then inService should
448                                  * be OFF--only the salvager checks this flag */
449 #ifdef ALPHA_DUX40_ENV
450 #define DONT_SALVAGE    0xE6
451 #else                           /* ALPHA_DUX40_ENV */
452 #define DONT_SALVAGE    0xE5
453 #endif                          /* ALPHA_DUX40_ENV */
454     byte dontSalvage;           /* If this is on, then don't bother salvaging this volume */
455     byte reserveb3;
456
457     bit32 reserved1[6];
458
459
460     /* Administrative stuff */
461     int maxquota;               /* Quota maximum, 1K blocks */
462     int minquota;               /* Quota minimum, 1K blocks */
463     int maxfiles;               /* Maximum number of files (i.e. inodes) */
464     bit32 accountNumber;        /* Uninterpreted account number */
465     bit32 owner;                /* The person administratively responsible
466                                  * for this volume */
467     int reserved2[8];           /* Other administrative constraints */
468
469     /* Resource usage & statistics */
470     int filecount;              /* Actual number of files */
471     int diskused;               /* Actual disk space used, 1K blocks */
472     int dayUse;                 /* Metric for today's usage of this volume so far */
473     int weekUse[7];             /* Usage of the volume for the last week.
474                                  * weekUse[0] is for most recent complete 24 hour period
475                                  * of measurement; week[6] is 7 days ago */
476     Date dayUseDate;            /* Date the dayUse statistics refer to; the week use stats
477                                  * are the preceding 7 days */
478     unsigned int volUpdateCounter; /*incremented at every update of volume*/
479     int reserved3[10];          /* Other stats here */
480
481     /* Server supplied dates */
482     Date creationDate;          /* Creation date for a read/write
483                                  * volume; cloning date for original copy of
484                                  * a readonly volume (replicated volumes have
485                                  * the same creation date) */
486     Date accessDate;            /* Last access time by a user, large granularity */
487     Date updateDate;            /* Last modification by user */
488     Date expirationDate;        /* 0 if it never expires */
489     Date backupDate;            /* last time a backup clone was taken */
490
491     /* Time that this copy of this volume was made.  NEVER backed up.  This field is only
492      * set when the copy is created */
493     Date copyDate;
494
495 #if OPENAFS_VOL_STATS
496     bit32 stat_initialized;     /*Are the stat fields below set up? */
497     bit32 reserved4[7];
498 #else
499     bit32 reserved4[8];
500 #endif                          /* OPENAFS_VOL_STATS */
501
502     /* messages */
503 #define VMSGSIZE 128
504     char offlineMessage[VMSGSIZE];      /* Why the volume is offline */
505 #if OPENAFS_VOL_STATS
506 #define VOL_STATS_BYTES 128
507     /*
508      * Keep per-volume aggregate statistics on type and distance of access,
509      * along with authorship info.
510      */
511     bit32 stat_reads[VOL_STATS_NUM_RWINFO_FIELDS];
512     bit32 stat_writes[VOL_STATS_NUM_RWINFO_FIELDS];
513     bit32 stat_fileSameAuthor[VOL_STATS_NUM_TIME_FIELDS];
514     bit32 stat_fileDiffAuthor[VOL_STATS_NUM_TIME_FIELDS];
515     bit32 stat_dirSameAuthor[VOL_STATS_NUM_TIME_FIELDS];
516     bit32 stat_dirDiffAuthor[VOL_STATS_NUM_TIME_FIELDS];
517 #else
518     char motd[VMSGSIZE];        /* Volume "message of the day" */
519 #endif                          /* OPENAFS_VOL_STATS */
520
521 } VolumeDiskData;
522
523
524 /**************************************/
525 /* Memory resident volume information */
526 /**************************************/
527
528 /**
529  * global volume package stats.
530  */
531 typedef struct VolPkgStats {
532 #ifdef AFS_DEMAND_ATTACH_FS
533     /*
534      * demand attach fs
535      * extended volume package statistics
536      */
537
538     /* levels */
539     afs_uint32 state_levels[VOL_STATE_COUNT]; /**< volume state transition counters */
540
541     /* counters */
542     afs_uint64 hash_looks;           /**< number of hash chain element traversals */
543     afs_uint64 hash_reorders;        /**< number of hash chain reorders */
544     afs_uint64 salvages;             /**< online salvages since fileserver start */
545     afs_uint64 vol_ops;              /**< volume operations since fileserver start */
546 #endif /* AFS_DEMAND_ATTACH_FS */
547
548     afs_uint64 hdr_loads;            /**< header loads from disk */
549     afs_uint64 hdr_gets;             /**< header pulls out of LRU */
550     afs_uint64 attaches;             /**< volume attaches since fileserver start */
551     afs_uint64 soft_detaches;        /**< soft detach ops since fileserver start */
552
553     /* configuration parameters */
554     afs_uint32 hdr_cache_size;       /**< size of volume header cache */
555 } VolPkgStats;
556 extern VolPkgStats VStats;
557
558 /*
559  * volume header cache supporting structures
560  */
561 struct volume_hdr_LRU_stats {
562     afs_uint32 free;
563     afs_uint32 used;
564     afs_uint32 attached;
565 };
566
567 struct volume_hdr_LRU_t {
568     struct rx_queue lru;
569     struct volume_hdr_LRU_stats stats;
570 };
571 extern struct volume_hdr_LRU_t volume_hdr_LRU;
572
573 /*
574  * volume hash chain supporting structures
575  */
576 typedef struct VolumeHashChainHead {
577     struct rx_queue queue;
578     int len;
579     /* someday we could put a per-chain lock here... */
580 #ifdef AFS_DEMAND_ATTACH_FS
581     int busy;
582     int cacheCheck;
583
584     /* per-chain statistics */
585     afs_uint64 looks;
586     afs_uint64 gets;
587     afs_uint64 reorders;
588
589     pthread_cond_t chain_busy_cv;
590 #endif /* AFS_DEMAND_ATTACH_FS */
591 } VolumeHashChainHead;
592
593 typedef struct VolumeHashTable {
594     int Size;
595     int Mask;
596     VolumeHashChainHead * Table;
597 } VolumeHashTable_t;
598 extern VolumeHashTable_t VolumeHashTable;
599
600 struct VolumeHashChainStats {
601     afs_int32 table_size;
602     afs_int32 chain_len;
603 #ifdef AFS_DEMAND_ATTACH_FS
604     afs_int32 chain_cacheCheck;
605     afs_int32 chain_busy;
606     afs_uint64 chain_looks;
607     afs_uint64 chain_gets;
608     afs_uint64 chain_reorders;
609 #endif
610 };
611
612
613 #ifdef AFS_DEMAND_ATTACH_FS
614 /**
615  * DAFS extended per-volume statistics.
616  *
617  * @note this data lives across the entire
618  *       lifetime of the fileserver process
619  */
620 typedef struct VolumeStats {
621     /* counters */
622     afs_uint64 hash_lookups;         /**< hash table lookups */
623     afs_uint64 hash_short_circuits;  /**< short circuited hash lookups (due to cacheCheck) */
624     afs_uint64 hdr_loads;            /**< header loads from disk */
625     afs_uint64 hdr_gets;             /**< header pulls out of LRU */
626     afs_uint16 attaches;             /**< attaches of this volume since fileserver start */
627     afs_uint16 soft_detaches;        /**< soft detaches of this volume */
628     afs_uint16 salvages;             /**< online salvages since fileserver start */
629     afs_uint16 vol_ops;              /**< volume operations since fileserver start */
630
631     /* timestamps */
632     afs_uint32 last_attach;      /**< unix timestamp of last VAttach */
633     afs_uint32 last_get;         /**< unix timestamp of last VGet/VHold */
634     afs_uint32 last_promote;     /**< unix timestamp of last VLRU promote/demote */
635     afs_uint32 last_hdr_get;     /**< unix timestamp of last GetVolumeHeader() */
636     afs_uint32 last_hdr_load;    /**< unix timestamp of last LoadVolumeHeader() */
637     afs_uint32 last_salvage;     /**< unix timestamp of last initiation of an online salvage */
638     afs_uint32 last_salvage_req; /**< unix timestamp of last SALVSYNC request */
639     afs_uint32 last_vol_op;      /**< unix timestamp of last volume operation */
640 } VolumeStats;
641
642
643 #define SALVAGE_PRIO_UPDATE_INTERVAL 3      /**< number of seconds between prio updates */
644 #define SALVAGE_COUNT_MAX 16                /**< number of online salvages we
645                                              *   allow before moving the volume
646                                              *   into a permanent error state
647                                              *
648                                              *   once this threshold is reached,
649                                              *   the operator will have to manually
650                                              *   issue a 'bos salvage' to bring
651                                              *   the volume back online
652                                              */
653
654 /**
655  * DAFS online salvager state.
656  */
657 typedef struct VolumeOnlineSalvage {
658     afs_uint32 prio;            /**< number of VGetVolume's since salvage requested */
659     int reason;                 /**< reason for requesting online salvage */
660     byte requested;             /**< flag specifying that salvage should be scheduled */
661     byte scheduled;             /**< flag specifying whether online salvage scheduled */
662     byte scheduling;            /**< if nonzero, this volume has entered
663                                  *   VCheckSalvage(), so if we recurse into
664                                  *   VCheckSalvage() with this set, exit immediately
665                                  *   to avoid recursing forever */
666     byte reserved[1];           /**< padding */
667 } VolumeOnlineSalvage;
668
669 /**
670  * DAFS Volume LRU state.
671  */
672 typedef struct VolumeVLRUState {
673     struct rx_queue lru;        /**< VLRU queue for this generation */
674     VLRUQueueName idx;          /**< VLRU generation index */
675 } VolumeVLRUState;
676 #endif /* AFS_DEMAND_ATTACH_FS */
677
678 /**
679  * node for a volume's rx_call_list.
680  */
681 struct VCallByVol {
682     struct rx_queue q;
683     struct rx_call *call;
684 };
685
686 typedef struct Volume {
687     struct rx_queue q;          /* Volume hash chain pointers */
688     VolumeId hashid;            /* Volume number -- for hash table lookup */
689     struct volHeader *header;   /* Cached disk data */
690     Device device;              /* Unix device for the volume */
691     struct DiskPartition64
692      *partition;                /* Information about the Unix partition */
693     struct vnodeIndex {
694         IHandle_t *handle;      /* Unix inode holding this index */
695         byte *bitmap;           /* Index bitmap */
696         afs_uint32 bitmapSize;  /* length of bitmap, in bytes */
697         afs_uint32 bitmapOffset;        /* Which byte address of the first long to
698                                          * start search from in bitmap */
699     } vnodeIndex[nVNODECLASSES];
700     IHandle_t *linkHandle;
701     Unique nextVnodeUnique;     /* Derived originally from volume uniquifier.
702                                  * This is the actual next version number to
703                                  * assign; the uniquifier is bumped by 200 and
704                                  * and written to disk every 200 file creates
705                                  * If the volume is shutdown gracefully, the
706                                  * uniquifier should be rewritten with the
707                                  * value nextVnodeVersion */
708     IHandle_t *diskDataHandle;  /* Unix inode holding general volume info */
709     bit16 vnodeHashOffset;      /* Computed by HashOffset function in vnode.h.
710                                  * Assigned to the volume when initialized.
711                                  * Added to vnode number for hash table index */
712     byte shuttingDown;          /* This volume is going to be detached */
713     byte goingOffline;          /* This volume is going offline */
714     bit32 cacheCheck;           /* Online sequence number to be used to invalidate vnode cache entries
715                                  * that stayed around while a volume was offline */
716     short nUsers;               /* Number of users of this volume header */
717 #define VOL_PUTBACK 1
718 #define VOL_PUTBACK_DELETE 2
719     byte needsPutBack;          /* For a volume utility, this flag is set to VOL_PUTBACK if we
720                                  * need to give the volume back when we detach it.  The server has
721                                  * certain modes where it doesn't detach the volume, and
722                                  * if we give it back spuriously, the server aborts. If set to
723                                  * VOL_PUTBACK_DELETE, it indicates that we need to tell the
724                                  * fileserver that the volume is gone entirely, instead of just
725                                  * giving the volume back to the fileserver. This field
726                                  * is meaningless on the file server */
727     byte specialStatus;         /* An error code to return on VGetVolume: the
728                                  * volume is unavailable for the reason quoted,
729                                  * currently VBUSY or VMOVED */
730     afs_uint32 checkoutMode;    /* for volume utilities, mode number for current checkout */
731     afs_uint32 updateTime;      /* Time that this volume was put on the updated
732                                  * volume list--the list of volumes that will be
733                                  * salvaged should the file server crash */
734     struct rx_queue vnode_list; /**< linked list of cached vnodes for this volume */
735     struct rx_queue rx_call_list; /**< linked list of split RX calls using this
736                                    *   volume (fileserver only) */
737 #ifdef AFS_DEMAND_ATTACH_FS
738     VolState attach_state;      /* what stage of attachment has been completed */
739     afs_uint32 attach_flags;    /* flags related to attachment state */
740     pthread_cond_t attach_cv;   /* state change condition variable */
741     short nWaiters;             /* volume package internal ref count */
742     int chainCacheCheck;        /* Volume hash chain cache check */
743     struct rx_queue vol_list;   /* per-partition volume list (VByPList) */
744
745     VolumeOnlineSalvage salvage;  /* online salvager state */
746     VolumeStats stats;            /* per-volume statistics */
747     VolumeVLRUState vlru;         /* state specific to the VLRU */
748     FSSYNC_VolOp_info * pending_vol_op;  /* fssync command info for any pending vol ops */
749 #endif /* AFS_DEMAND_ATTACH_FS */
750 } Volume;
751
752 struct volHeader {
753     struct rx_queue lru;
754     VolumeDiskData diskstuff;   /* General volume info read from disk */
755     Volume *back;               /* back pointer to current volume structure */
756 };
757
758 /* These macros are used to export fields within the volume header.  This was added
759    to facilitate changing the actual representation */
760
761 #define V_device(vp)            ((vp)->device)
762 #define V_partition(vp)         ((vp)->partition)
763 #define V_diskDataHandle(vp)    ((vp)->diskDataHandle)
764 #define V_vnodeIndex(vp)        ((vp)->vnodeIndex)
765 #define V_nextVnodeUnique(vp)   ((vp)->nextVnodeUnique)
766 #define V_linkHandle(vp)        ((vp)->linkHandle)
767 #define V_checkoutMode(vp)      ((vp)->checkoutMode)
768 #ifdef AFS_DEMAND_ATTACH_FS
769 #define V_attachState(vp)       ((vp)->attach_state)
770 #define V_attachFlags(vp)       ((vp)->attach_flags)
771 #define V_attachCV(vp)          ((vp)->attach_cv)
772 #endif /* AFS_DEMAND_ATTACH_FS */
773
774 /* N.B. V_id must be this, rather than vp->id, or some programs will break, probably */
775 #define V_stamp(vp)             ((vp)->header->diskstuff.stamp)
776 #define V_id(vp)                ((vp)->header->diskstuff.id)
777 #define V_name(vp)              ((vp)->header->diskstuff.name)
778 #define V_inUse(vp)             ((vp)->header->diskstuff.inUse)
779 #define V_inService(vp)         ((vp)->header->diskstuff.inService)
780 #define V_blessed(vp)           ((vp)->header->diskstuff.blessed)
781 #define V_needsSalvaged(vp)     ((vp)->header->diskstuff.needsSalvaged)
782 #define V_uniquifier(vp)        ((vp)->header->diskstuff.uniquifier)
783 #define V_type(vp)              ((vp)->header->diskstuff.type)
784 #define V_parentId(vp)          ((vp)->header->diskstuff.parentId)
785 #define V_cloneId(vp)           ((vp)->header->diskstuff.cloneId)
786 #define V_backupId(vp)          ((vp)->header->diskstuff.backupId)
787 #define V_restoredFromId(vp)    ((vp)->header->diskstuff.restoredFromId)
788 #define V_needsCallback(vp)     ((vp)->header->diskstuff.needsCallback)
789 #define V_destroyMe(vp)         ((vp)->header->diskstuff.destroyMe)
790 #define V_dontSalvage(vp)       ((vp)->header->diskstuff.dontSalvage)
791 #define V_maxquota(vp)          ((vp)->header->diskstuff.maxquota)
792 #define V_minquota(vp)          ((vp)->header->diskstuff.minquota)
793 #define V_maxfiles(vp)          ((vp)->header->diskstuff.maxfiles)
794 #define V_accountNumber(vp)     ((vp)->header->diskstuff.accountNumber)
795 #define V_owner(vp)             ((vp)->header->diskstuff.owner)
796 #define V_filecount(vp)         ((vp)->header->diskstuff.filecount)
797 #define V_diskused(vp)          ((vp)->header->diskstuff.diskused)
798 #define V_dayUse(vp)            ((vp)->header->diskstuff.dayUse)
799 #define V_weekUse(vp)           ((vp)->header->diskstuff.weekUse)
800 #define V_dayUseDate(vp)        ((vp)->header->diskstuff.dayUseDate)
801 #define V_creationDate(vp)      ((vp)->header->diskstuff.creationDate)
802 #define V_accessDate(vp)        ((vp)->header->diskstuff.accessDate)
803 #define V_updateDate(vp)        ((vp)->header->diskstuff.updateDate)
804 #define V_expirationDate(vp)    ((vp)->header->diskstuff.expirationDate)
805 #define V_backupDate(vp)        ((vp)->header->diskstuff.backupDate)
806 #define V_copyDate(vp)          ((vp)->header->diskstuff.copyDate)
807 #define V_offlineMessage(vp)    ((vp)->header->diskstuff.offlineMessage)
808 #define V_disk(vp)              ((vp)->header->diskstuff)
809 #define V_motd(vp)              ((vp)->header->diskstuff.motd)
810 #if OPENAFS_VOL_STATS
811 #define V_stat_initialized(vp)  ((vp)->header->diskstuff.stat_initialized)
812 #define V_stat_area(vp)         (((vp)->header->diskstuff.stat_reads))
813 #define V_stat_reads(vp, idx)   (((vp)->header->diskstuff.stat_reads)[idx])
814 #define V_stat_writes(vp, idx)  (((vp)->header->diskstuff.stat_writes)[idx])
815 #define V_stat_fileSameAuthor(vp, idx) (((vp)->header->diskstuff.stat_fileSameAuthor)[idx])
816 #define V_stat_fileDiffAuthor(vp, idx) (((vp)->header->diskstuff.stat_fileDiffAuthor)[idx])
817 #define V_stat_dirSameAuthor(vp, idx)  (((vp)->header->diskstuff.stat_dirSameAuthor)[idx])
818 #define V_stat_dirDiffAuthor(vp, idx)  (((vp)->header->diskstuff.stat_dirDiffAuthor)[idx])
819 #endif /* OPENAFS_VOL_STATS */
820 #define V_volUpCounter(vp)              ((vp)->header->diskstuff.volUpdateCounter)
821
822 /* File offset computations.  The offset values in the volume header are
823    computed with these macros -- when the file is written only!! */
824 #define VOLUME_MOUNT_TABLE_OFFSET(Volume)       (sizeof (VolumeDiskData))
825 #define VOLUME_BITMAP_OFFSET(Volume)    \
826         (sizeof (VolumeDiskData) + (Volume)->disk.mountTableSize)
827
828
829 extern char *VSalvageMessage;   /* Canonical message when a volume is forced
830                                  * offline */
831 extern Volume *VGetVolume(Error * ec, Error * client_ec, VolId volumeId);
832 extern Volume *VGetVolumeWithCall(Error * ec, Error * client_ec, VolId volumeId,
833                                   const struct timespec *ts, struct VCallByVol *cbv);
834 extern Volume *VGetVolume_r(Error * ec, VolId volumeId);
835 extern void VPutVolume(Volume *);
836 extern void VPutVolumeWithCall(Volume *vp, struct VCallByVol *cbv);
837 extern void VPutVolume_r(Volume *);
838 extern void VOffline(Volume * vp, char *message);
839 extern void VOffline_r(Volume * vp, char *message);
840 extern int VConnectFS(void);
841 extern int VConnectFS_r(void);
842 extern void VDisconnectFS(void);
843 extern void VDisconnectFS_r(void);
844 extern int VChildProcReconnectFS(void);
845 extern Volume *VAttachVolume(Error * ec, VolumeId volumeId, int mode);
846 extern Volume *VAttachVolume_r(Error * ec, VolumeId volumeId, int mode);
847 extern Volume *VCreateVolume(Error * ec, char *partname, VolId volumeId,
848                              VolId parentId);
849 extern Volume *VCreateVolume_r(Error * ec, char *partname, VolId volumeId,
850                                VolId parentId);
851 extern int VAllocBitmapEntry(Error * ec, Volume * vp,
852                              struct vnodeIndex *index);
853 extern int VAllocBitmapEntry_r(Error * ec, Volume * vp,
854                                struct vnodeIndex *index, int flags);
855 extern void VFreeBitMapEntry(Error * ec, struct vnodeIndex *index,
856                              unsigned bitNumber);
857 extern void VFreeBitMapEntry_r(Error * ec, struct vnodeIndex *index,
858                                unsigned bitNumber);
859 extern int VolumeNumber(char *name);
860 extern char *VolumeExternalName(VolumeId volumeId);
861 extern int VolumeExternalName_r(VolumeId volumeId, char *name, size_t len);
862 extern Volume *VAttachVolumeByName(Error * ec, char *partition, char *name,
863                                    int mode);
864 extern Volume *VAttachVolumeByName_r(Error * ec, char *partition, char *name,
865                                      int mode);
866 extern void VShutdown(void);
867 extern void VSetTranquil(void);
868 extern void VUpdateVolume(Error * ec, Volume * vp);
869 extern void VUpdateVolume_r(Error * ec, Volume * vp, int flags);
870 extern void VAddToVolumeUpdateList(Error * ec, Volume * vp);
871 extern void VAddToVolumeUpdateList_r(Error * ec, Volume * vp);
872 extern void VDetachVolume(Error * ec, Volume * vp);
873 extern void VDetachVolume_r(Error * ec, Volume * vp);
874 extern void VForceOffline(Volume * vp);
875 extern void VForceOffline_r(Volume * vp, int flags);
876 extern void VBumpVolumeUsage(Volume * vp);
877 extern void VBumpVolumeUsage_r(Volume * vp);
878 extern void VSetDiskUsage(void);
879 extern void VPrintCacheStats(void);
880 extern void VReleaseVnodeFiles_r(Volume * vp);
881 extern void VCloseVnodeFiles_r(Volume * vp);
882 extern struct DiskPartition64 *VGetPartition(char *name, int abortp);
883 extern struct DiskPartition64 *VGetPartition_r(char *name, int abortp);
884 extern void VOptDefaults(ProgramType pt, VolumePackageOptions * opts);
885 extern int VInitVolumePackage2(ProgramType pt, VolumePackageOptions * opts);
886 extern int VInitAttachVolumes(ProgramType pt);
887 extern void DiskToVolumeHeader(VolumeHeader_t * h, VolumeDiskHeader_t * dh);
888 extern void VolumeHeaderToDisk(VolumeDiskHeader_t * dh, VolumeHeader_t * h);
889 extern void AssignVolumeName(VolumeDiskData * vol, char *name, char *ext);
890 extern void VTakeOffline_r(Volume * vp);
891 extern void VTakeOffline(Volume * vp);
892 extern Volume * VLookupVolume_r(Error * ec, VolId volumeId, Volume * hint);
893 extern void VGetVolumePath(Error * ec, VolId volumeId, char **partitionp,
894                            char **namep);
895 extern char *vol_DevName(dev_t adev, char *wpath);
896 extern afs_int32 VIsGoingOffline(struct Volume *vp);
897
898 struct VLockFile;
899 extern void VLockFileInit(struct VLockFile *lf, const char *path);
900 extern void VLockFileReinit(struct VLockFile *lf);
901 extern int VLockFileLock(struct VLockFile *lf, afs_uint32 offset,
902                          int locktype, int nonblock);
903 extern void VLockFileUnlock(struct VLockFile *lf, afs_uint32 offset);
904
905 #ifdef AFS_DEMAND_ATTACH_FS
906 extern Volume *VPreAttachVolumeByName(Error * ec, char *partition, char *name);
907 extern Volume *VPreAttachVolumeByName_r(Error * ec, char *partition, char *name);
908 extern Volume *VPreAttachVolumeById_r(Error * ec, char * partition,
909                                       VolId volumeId);
910 extern Volume *VPreAttachVolumeByVp_r(Error * ec, struct DiskPartition64 * partp,
911                                       Volume * vp, VolId volume_id);
912 extern Volume *VGetVolumeByVp_r(Error * ec, Volume * vp);
913 extern int VShutdownByPartition_r(struct DiskPartition64 * dp);
914 extern int VShutdownVolume_r(Volume * vp);
915 extern int VConnectSALV(void);
916 extern int VConnectSALV_r(void);
917 extern int VReconnectSALV(void);
918 extern int VReconnectSALV_r(void);
919 extern int VDisconnectSALV(void);
920 extern int VDisconnectSALV_r(void);
921 extern void VPrintExtendedCacheStats(int flags);
922 extern void VPrintExtendedCacheStats_r(int flags);
923 extern void VLRU_SetOptions(int option, afs_uint32 val);
924 extern int VSetVolHashSize(int logsize);
925 extern int VRequestSalvage_r(Error * ec, Volume * vp, int reason, int flags);
926 extern int VUpdateSalvagePriority_r(Volume * vp);
927 extern int VRegisterVolOp_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
928 extern int VDeregisterVolOp_r(Volume * vp);
929 extern void VCancelReservation_r(Volume * vp);
930 extern int VChildProcReconnectFS_r(void);
931 extern void VOfflineForVolOp_r(Error *ec, Volume *vp, char *message);
932
933 struct VDiskLock;
934 extern void VDiskLockInit(struct VDiskLock *dl, struct VLockFile *lf,
935                           afs_uint32 offset);
936 extern int VGetDiskLock(struct VDiskLock *dl, int locktype, int nonblock);
937 extern void VReleaseDiskLock(struct VDiskLock *dl, int locktype);
938 #endif /* AFS_DEMAND_ATTACH_FS */
939 extern int VVolOpLeaveOnline_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
940 extern int VVolOpLeaveOnlineNoHeader_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
941 extern int VVolOpSetVBusy_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
942
943 extern void VPurgeVolume(Error * ec, Volume * vp);
944
945 extern afs_int32 VCanScheduleSalvage(void);
946 extern afs_int32 VCanUseFSSYNC(void);
947 extern afs_int32 VCanUseSALVSYNC(void);
948 extern afs_int32 VCanUnsafeAttach(void);
949 extern afs_int32 VReadVolumeDiskHeader(VolumeId volid,
950                                        struct DiskPartition64 * dp,
951                                        VolumeDiskHeader_t * hdr);
952 extern afs_int32 VWriteVolumeDiskHeader(VolumeDiskHeader_t * hdr,
953                                         struct DiskPartition64 * dp);
954 extern afs_int32 VCreateVolumeDiskHeader(VolumeDiskHeader_t * hdr,
955                                          struct DiskPartition64 * dp);
956 extern afs_int32 VDestroyVolumeDiskHeader(struct DiskPartition64 * dp,
957                                           VolumeId volid, VolumeId parent);
958
959 /**
960  * VWalkVolumeHeaders header callback.
961  *
962  * @param[in] dp   disk partition
963  * @param[in] name full path to the .vol header file
964  * @param[in] hdr  the header data that was read from the .vol header
965  * @param[in] last 1 if this is the last attempt to read the vol header, 0
966  *                 otherwise. DAFS VWalkVolumeHeaders will retry reading the
967  *                 header once, if a non-fatal error occurs when reading the
968  *                 header, or if this function returns a positive error code.
969  *                 So, if there is a problem, this function will be called
970  *                 first with last=0, then with last=1, then the error function
971  *                 callback will be called. For non-DAFS, this is always 1.
972  * @param[in] rock the rock passed to VWalkVolumeHeaders
973  *
974  * @return operation status
975  *  @retval 0 success
976  *  @retval negative a fatal error that should stop the walk immediately
977  *  @retval positive an error with the volume header was encountered; the walk
978  *          should continue, but the error function should be called on this
979  *          header
980  *
981  * @see VWalkVolumeHeaders
982  */
983 typedef int (*VWalkVolFunc)(struct DiskPartition64 *dp, const char *name,
984                             struct VolumeDiskHeader *hdr, int last,
985                             void *rock);
986 /**
987  * VWalkVolumeHeaders error callback.
988  *
989  * This is called from VWalkVolumeHeaders when an invalid or otherwise
990  * problematic volume header is encountered. It is typically implemented as a
991  * wrapper to unlink the .vol file.
992  *
993  * @param[in] dp   disk partition
994  * @param[in] name full path to the .vol header file
995  * @param[in] hdr  header read in from the .vol file, or NULL if it could not
996  *                 be read
997  * @param[in] rock rock passed to VWalkVolumeHeaders
998  *
999  * @see VWalkVolumeHeaders
1000  */
1001 typedef void (*VWalkErrFunc)(struct DiskPartition64 *dp, const char *name,
1002                              struct VolumeDiskHeader *hdr, void *rock);
1003 extern int VWalkVolumeHeaders(struct DiskPartition64 *dp, const char *partpath,
1004                               VWalkVolFunc volfunc, VWalkErrFunc errfunc,
1005                               void *rock);
1006
1007 /* Naive formula relating number of file size to number of 1K blocks in file */
1008 /* Note:  we charge 1 block for 0 length files so the user can't store
1009    an inifite number of them; for most files, we give him the inode, vnode,
1010    and indirect block overhead, for FREE! */
1011 #define nBlocks(bytes) ((afs_sfsize_t)((bytes) == 0? 1: (((afs_sfsize_t)(bytes))+1023)/1024))
1012
1013 /* Client process id -- file server sends a Check volumes signal back to the client at this pid */
1014 #define CLIENTPID       "/vice/vol/clientpid"
1015
1016 /* Modes of attachment, for VAttachVolume[ByName] to convey to the file server */
1017 #define V_READONLY 1            /* Absolutely no updates will be done to the volume */
1018 #define V_CLONE    2            /* Cloning the volume:  if it is read/write, then directory
1019                                  * version numbers will change.  Header will be updated.  If
1020                                  * the volume is read-only, the file server may continue to
1021                                  * server it; it may also continue to server it in read/write
1022                                  * mode if the writes are deferred */
1023 #define V_VOLUPD   3            /* General update or volume purge is possible.  Volume must
1024                                  * go offline */
1025 #define V_DUMP     4            /* A dump of the volume is requested; the volume can be served
1026                                  * read-only during this time */
1027 #define V_SECRETLY 5            /* Secret attach of the volume.  This is used to attach a volume
1028                                  * which the file server doesn't know about--and which it shouldn't
1029                                  * know about yet, since the volume has just been created and
1030                                  * is somewhat bogus.  Required to make sure that a file server
1031                                  * never knows about more than one copy of the same volume--when
1032                                  * a volume is moved from one partition to another on a single
1033                                  * server */
1034 #define V_PEEK     6            /* "Peek" at the volume without telling the fileserver.  This is
1035                                  * similar to V_SECRETLY, but read-only.  It is used in cases where
1036                                  * not impacting fileserver performance is more important than
1037                                  * getting the most recent data. */
1038
1039
1040
1041 /* VUpdateVolume_r flags */
1042 #define VOL_UPDATE_WAIT          0x1  /* for demand attach, wait for other exclusive ops to end */
1043 #define VOL_UPDATE_NOFORCEOFF    0x2  /* don't force offline on failure. this is to prevent
1044                                        * infinite recursion between vupdate and vforceoff */
1045
1046 /* VForceOffline_r flags */
1047 #define VOL_FORCEOFF_NOUPDATE    0x1  /* don't force update on forceoff. this is to prevent
1048                                        * infinite recursion between vupdate and vforceoff */
1049
1050 /* VSyncVolume_r flags */
1051 #define VOL_SYNC_WAIT            0x1  /* for demand attach, wait for other exclusive ops to end */
1052
1053 /* VAllocBitmapEntry_r flags */
1054 #define VOL_ALLOC_BITMAP_WAIT    0x1  /* for demand attach, wait for other exclusive ops to end */
1055
1056 /* VRequestSalvage_r flags */
1057 #define VOL_SALVAGE_INVALIDATE_HEADER 0x1 /* for demand attach fs, invalidate volume header cache */
1058 #define VOL_SALVAGE_NO_OFFLINE        0x2 /* we do not need to wait to offline the volume; it has
1059                                            * not been fully attached */
1060
1061
1062 #if     defined(NEARINODE_HINT)
1063 #define V_pref(vp,nearInode)  nearInodeHash(V_id(vp),(nearInode)); (nearInode) %= V_partition(vp)->f_files
1064 #else
1065 #define V_pref(vp,nearInode)   nearInode = 0
1066 #endif /* NEARINODE_HINT */
1067
1068 hdr_static_inline(unsigned int)
1069 afs_printable_VolumeId_u(VolumeId d) { return (unsigned int) d; }
1070
1071 hdr_static_inline(unsigned int)
1072 afs_printable_VnodeId_u(VnodeId d) { return (unsigned int) d; }
1073
1074 #endif /* __volume_h */