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