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