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