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
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <sys/types.h>
24 #include <netinet/in.h>
41 #include <afs/afsint.h>
43 #ifdef AFS_PTHREAD_ENV
45 #else /* AFS_PTHREAD_ENV */
46 #include <afs/assert.h>
47 #endif /* AFS_PTHREAD_ENV */
48 #include <afs/prs_fs.h>
52 #include <afs/cellconfig.h>
55 #include <afs/ihandle.h>
57 #include <afs/ntops.h>
59 #include <afs/vnode.h>
60 #include <afs/volume.h>
61 #include <afs/partition.h>
63 #include <afs/daemon_com.h>
64 #include <afs/fssync.h>
66 #include "afs/audit.h"
72 #include "volser_prototypes.h"
75 extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
76 extern struct afsconf_dir *tdir;
78 /* Needed by Irix. Leave, or include a header */
79 extern char *volutil_PartitionName();
81 extern void LogError(afs_int32 errcode);
83 /* Forward declarations */
84 static int GetPartName(afs_int32 partid, char *pname);
86 #define OneDay (24*60*60)
92 afs_int32 localTid = 1;
93 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
94 VolDeleteVolume(), VolClone();
95 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
96 VolForward(), VolDump();
97 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
98 VolSetInfo(), VolGetName();
99 afs_int32 VolListPartitions(), VolListOneVolume(),
100 VolXListOneVolume(), VolXListVolumes();
101 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
102 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
104 /* this call unlocks all of the partition locks we've set */
108 register struct DiskPartition *tp;
109 for (tp = DiskPartitionList; tp; tp = tp->next) {
110 if (tp->lock_fd != -1) {
111 close(tp->lock_fd); /* releases flock held on this partition */
118 /* get partition id from a name */
120 PartitionID(char *aname)
123 register int code = 0;
128 return -1; /* unknown */
130 /* otherwise check for vicepa or /vicepa, or just plain "a" */
132 if (!strncmp(aname, "/vicep", 6)) {
133 strncpy(ascii, aname + 6, 2);
135 return -1; /* bad partition name */
136 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
137 * from 0. Do the appropriate conversion */
139 /* one char name, 0..25 */
140 if (ascii[0] < 'a' || ascii[0] > 'z')
141 return -1; /* wrongo */
142 return ascii[0] - 'a';
144 /* two char name, 26 .. <whatever> */
145 if (ascii[0] < 'a' || ascii[0] > 'z')
146 return -1; /* wrongo */
147 if (ascii[1] < 'a' || ascii[1] > 'z')
148 return -1; /* just as bad */
149 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
150 if (code > VOLMAXPARTS)
157 ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
161 /* It's better using the Generic VFORMAT since otherwise we have to make changes to too many places... The 14 char limitation in names hits us again in AIX; print in field of 9 digits (still 10 for the rest), right justified with 0 padding */
162 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
167 ConvertPartition(int apartno, char *aname, int asize)
173 strcpy(aname, "/vicep");
175 aname[6] = 'a' + apartno;
179 aname[6] = 'a' + (apartno / 26);
180 aname[7] = 'a' + (apartno % 26);
186 /* the only attach function that takes a partition is "...ByName", so we use it */
188 XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
190 char pbuf[30], vbuf[20];
191 register struct Volume *tv;
193 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
197 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
201 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
205 /* Adapted from the file server; create a root directory for this volume */
207 ViceCreateRoot(Volume *vp)
210 struct acl_accessList *ACL;
212 Inode inodeNumber, nearInode;
213 char buf[SIZEOF_LARGEDISKVNODE];
214 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
215 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
221 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
223 V_pref(vp, nearInode);
225 IH_CREATE(V_linkHandle(vp), V_device(vp),
226 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
228 assert(VALID_INO(inodeNumber));
230 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
231 did.Volume = V_id(vp);
232 did.Vnode = (VnodeId) 1;
235 assert(!(MakeDir(&dir, &did, &did)));
236 DFlush(); /* flush all modified dir buffers out */
237 DZap(&dir); /* Remove all buffers for this dir */
238 length = Length(&dir); /* Remember size of this directory */
240 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
242 /* build a single entry ACL that gives all rights to system:administrators */
243 /* this section of code assumes that access list format is not going to
246 ACL = VVnodeDiskACL(vnode);
247 ACL->size = sizeof(struct acl_accessList);
248 ACL->version = ACL_ACLVERSION;
252 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
253 ACL->entries[0].rights =
254 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
255 | PRSFS_LOCK | PRSFS_ADMINISTER;
257 vnode->type = vDirectory;
259 vnode->modeBits = 0777;
260 vnode->linkCount = 2;
261 VNDISK_SET_LEN(vnode, length);
262 vnode->uniquifier = 1;
263 V_uniquifier(vp) = vnode->uniquifier + 1;
264 vnode->dataVersion = 1;
265 VNDISK_SET_INO(vnode, inodeNumber);
266 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
270 vnode->vnodeMagic = vcp->magic;
272 IH_INIT(h, vp->device, V_parentId(vp),
273 vp->vnodeIndex[vLarge].handle->ih_ino);
276 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
278 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
279 assert(code == SIZEOF_LARGEDISKVNODE);
280 FDH_REALLYCLOSE(fdP);
282 VNDISK_GET_LEN(length, vnode);
283 V_diskused(vp) = nBlocks(length);
289 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
294 code = VolPartitionInfo(acid, pname, partition);
295 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
300 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
303 register struct DiskPartition *dp;
306 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
309 dp = VGetPartition(pname, 0);
311 strncpy(partition->name, dp->name, 32);
312 strncpy(partition->devName, dp->devName, 32);
313 partition->lock_fd = dp->lock_fd;
314 partition->free = dp->free;
315 partition->minFree = dp->totalUsable;
318 return VOLSERILLEGAL_PARTITION;
321 /* obliterate a volume completely, and slowly. */
323 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
327 code = VolNukeVolume(acid, apartID, avolID);
328 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
333 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
338 register afs_int32 code;
340 char caller[MAXKTCNAMELEN];
342 /* check for access */
343 if (!afsconf_SuperUser(tdir, acid, caller))
344 return VOLSERBAD_ACCESS;
346 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
348 tp = volutil_PartitionName(apartID);
351 strcpy(partName, tp); /* remember it for later */
352 /* we first try to attach the volume in update mode, so that the file
353 * server doesn't try to use it (and abort) while (or after) we delete it.
354 * If we don't get the volume, that's fine, too. We just won't put it back.
356 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
357 code = nuke(partName, avolID);
359 VDetachVolume(&error, tvp);
363 /* create a new volume, with name aname, on the specified partition (1..n)
364 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
365 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
366 * for the volume id (useful for things like volume restore).
367 * Return the new volume id in *avolid.
370 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
371 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
377 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
378 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
379 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
385 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
386 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
391 afs_int32 junk; /* discardable error code */
392 register afs_int32 volumeID, doCreateRoot = 1;
393 register struct volser_trans *tt;
395 char caller[MAXKTCNAMELEN];
397 if (strlen(aname) > 31)
398 return VOLSERBADNAME;
399 if (!afsconf_SuperUser(tdir, acid, caller))
400 return VOLSERBAD_ACCESS;
402 Log("%s is executing CreateVolume '%s'\n", caller, aname);
403 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
404 return error; /*a standard unix error */
405 if (atype != readwriteVolume && atype != readonlyVolume
406 && atype != backupVolume)
408 if ((volumeID = *avolid) == 0) {
410 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
414 if ((aparent == volumeID) && (atype == readwriteVolume)) {
419 tt = NewTrans(volumeID, apart);
421 Log("1 createvolume: failed to create trans\n");
422 return VOLSERVOLBUSY; /* volume already busy! */
424 vp = VCreateVolume(&error, ppath, volumeID, aparent);
426 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
431 V_uniquifier(vp) = 1;
432 V_creationDate(vp) = V_copyDate(vp);
433 V_inService(vp) = V_blessed(vp) = 1;
435 AssignVolumeName(&V_disk(vp), aname, 0);
438 V_destroyMe(vp) = DESTROY_ME;
440 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
441 VUpdateVolume(&error, vp);
443 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
446 VDetachVolume(&junk, vp); /* rather return the real error code */
451 strcpy(tt->lastProcName, "CreateVolume");
452 tt->rxCallPtr = acid;
453 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
454 tt->rxCallPtr = (struct rx_call *)0;
456 return VOLSERTRELE_ERROR;
460 /* delete the volume associated with this transaction */
462 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
466 code = VolDeleteVolume(acid, atrans);
467 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
472 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
474 register struct volser_trans *tt;
476 char caller[MAXKTCNAMELEN];
478 if (!afsconf_SuperUser(tdir, acid, caller))
479 return VOLSERBAD_ACCESS;
480 tt = FindTrans(atrans);
483 if (tt->vflags & VTDeleted) {
484 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
489 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
490 strcpy(tt->lastProcName, "DeleteVolume");
491 tt->rxCallPtr = acid;
492 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
493 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
494 tt->rxCallPtr = (struct rx_call *)0;
496 return VOLSERTRELE_ERROR;
498 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
499 return 0; /* vpurgevolume doesn't set an error code */
502 /* make a clone of the volume associated with atrans, possibly giving it a new
503 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
504 * for the clone's id). The new clone is given the name newName. Finally, due to
505 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
506 * the clone operation. This may be useful when making new backup volumes, for instance
507 * since the net result of a clone and a purge generally leaves many inode ref counts
508 * the same, while doing them separately would result in far more iincs and idecs being
509 * peformed (and they are slow operations).
511 /* for efficiency reasons, sometimes faster to piggyback a purge here */
513 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
514 afs_int32 newType, char *newName, afs_int32 *newNumber)
518 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
519 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
520 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
526 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
527 afs_int32 newType, char *newName, afs_int32 *newNumber)
530 register struct Volume *originalvp, *purgevp, *newvp;
532 register struct volser_trans *tt, *ttc;
533 char caller[MAXKTCNAMELEN];
535 if (strlen(newName) > 31)
536 return VOLSERBADNAME;
537 if (!afsconf_SuperUser(tdir, acid, caller))
538 return VOLSERBAD_ACCESS; /*not a super user */
540 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
542 originalvp = (Volume *) 0;
543 purgevp = (Volume *) 0;
544 newvp = (Volume *) 0;
545 tt = ttc = (struct volser_trans *)0;
547 if (!newNumber || !*newNumber) {
548 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
553 if (newType != readonlyVolume && newType != backupVolume)
555 tt = FindTrans(atrans);
558 if (tt->vflags & VTDeleted) {
559 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
563 ttc = NewTrans(newId, tt->partition);
564 if (!ttc) { /* someone is messing with the clone already */
568 strcpy(tt->lastProcName, "Clone");
569 tt->rxCallPtr = acid;
573 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
575 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
581 originalvp = tt->volume;
582 if ((V_type(originalvp) == backupVolume)
583 || (V_type(originalvp) == readonlyVolume)) {
584 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
588 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
589 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
595 if (originalvp->device != purgevp->device) {
596 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
600 if (V_type(purgevp) != readonlyVolume) {
601 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
605 if (V_type(originalvp) == readonlyVolume
606 && V_parentId(originalvp) != V_parentId(purgevp)) {
607 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
611 if (V_type(originalvp) == readwriteVolume
612 && tt->volid != V_parentId(purgevp)) {
613 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
622 VCreateVolume(&error, originalvp->partition->name, newId,
623 V_parentId(originalvp));
625 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
626 newvp = (Volume *) 0;
629 if (newType == readonlyVolume)
630 V_cloneId(originalvp) = newId;
631 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
634 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
635 CloneVolume(&error, originalvp, newvp, purgevp);
636 purgevp = NULL; /* clone releases it, maybe even if error */
638 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
642 if (newType == readonlyVolume) {
643 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
644 V_type(newvp) = readonlyVolume;
645 } else if (newType == backupVolume) {
646 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
647 V_type(newvp) = backupVolume;
648 V_backupId(originalvp) = newId;
650 strcpy(newvp->header->diskstuff.name, newName);
651 V_creationDate(newvp) = V_copyDate(newvp);
652 ClearVolumeStats(&V_disk(newvp));
653 V_destroyMe(newvp) = DESTROY_ME;
654 V_inService(newvp) = 0;
655 if (newType == backupVolume) {
656 V_backupDate(originalvp) = V_copyDate(newvp);
657 V_backupDate(newvp) = V_copyDate(newvp);
660 VUpdateVolume(&error, newvp);
662 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
666 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
668 VUpdateVolume(&error, originalvp);
670 Log("1 Volser: Clone: original update %u\n", error);
674 tt->rxCallPtr = (struct rx_call *)0;
676 tt = (struct volser_trans *)0;
677 error = VOLSERTRELE_ERROR;
685 VDetachVolume(&code, purgevp);
687 VDetachVolume(&code, newvp);
689 tt->rxCallPtr = (struct rx_call *)0;
697 /* reclone this volume into the specified id */
699 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
703 code = VolReClone(acid, atrans, cloneId);
704 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
710 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
712 register struct Volume *originalvp, *clonevp;
715 register struct volser_trans *tt, *ttc;
716 char caller[MAXKTCNAMELEN];
718 /*not a super user */
719 if (!afsconf_SuperUser(tdir, acid, caller))
720 return VOLSERBAD_ACCESS;
722 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
724 clonevp = originalvp = (Volume *) 0;
725 tt = (struct volser_trans *)0;
727 tt = FindTrans(atrans);
730 if (tt->vflags & VTDeleted) {
731 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
735 ttc = NewTrans(cloneId, tt->partition);
736 if (!ttc) { /* someone is messing with the clone already */
740 strcpy(tt->lastProcName, "ReClone");
741 tt->rxCallPtr = acid;
743 originalvp = tt->volume;
744 if ((V_type(originalvp) == backupVolume)
745 || (V_type(originalvp) == readonlyVolume)) {
746 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
750 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
751 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
757 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
759 Log("1 Volser: can't attach clone %d\n", cloneId);
763 newType = V_type(clonevp); /* type of the new volume */
765 if (originalvp->device != clonevp->device) {
766 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
771 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
772 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
776 if (V_type(originalvp) == readonlyVolume
777 && V_parentId(originalvp) != V_parentId(clonevp)) {
778 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
782 if (V_type(originalvp) == readwriteVolume
783 && tt->volid != V_parentId(clonevp)) {
784 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
790 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
792 CloneVolume(&error, originalvp, clonevp, clonevp);
794 Log("1 Volser: Clone: reclone operation failed with code %d\n",
800 /* fix up volume name and type, CloneVolume just propagated RW's */
801 if (newType == readonlyVolume) {
802 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
803 V_type(clonevp) = readonlyVolume;
804 } else if (newType == backupVolume) {
805 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
806 V_type(clonevp) = backupVolume;
807 V_backupId(originalvp) = cloneId;
809 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
811 /* pretend recloned volume is a totally new instance */
812 V_copyDate(clonevp) = time(0);
813 V_creationDate(clonevp) = V_copyDate(clonevp);
814 ClearVolumeStats(&V_disk(clonevp));
815 V_destroyMe(clonevp) = 0;
816 V_inService(clonevp) = 0;
817 if (newType == backupVolume) {
818 V_backupDate(originalvp) = V_copyDate(clonevp);
819 V_backupDate(clonevp) = V_copyDate(clonevp);
821 V_inUse(clonevp) = 0;
822 VUpdateVolume(&error, clonevp);
824 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
828 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
830 VUpdateVolume(&error, originalvp);
832 Log("1 Volser: Clone: original update %u\n", error);
836 tt->rxCallPtr = (struct rx_call *)0;
838 tt = (struct volser_trans *)0;
839 error = VOLSERTRELE_ERROR;
846 struct DiskPartition *tpartp = originalvp->partition;
847 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
853 VDetachVolume(&code, clonevp);
855 tt->rxCallPtr = (struct rx_call *)0;
863 /* create a new transaction, associated with volume and partition. Type of
864 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
865 * See volser.h for definition of iflags (the constants are named IT*).
868 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
869 afs_int32 iflags, afs_int32 *ttid)
873 code = VolTransCreate(acid, volume, partition, iflags, ttid);
874 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
880 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
881 afs_int32 iflags, afs_int32 *ttid)
883 register struct volser_trans *tt;
885 afs_int32 error, code;
887 char caller[MAXKTCNAMELEN];
889 if (!afsconf_SuperUser(tdir, acid, caller))
890 return VOLSERBAD_ACCESS; /*not a super user */
891 if (iflags & ITCreate)
893 else if (iflags & ITBusy)
895 else if (iflags & ITReadOnly)
897 else if (iflags & ITOffline)
900 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
905 tt = NewTrans(volume, partition);
907 /* can't create a transaction? put the volume back */
908 Log("1 transcreate: can't create transaction\n");
909 return VOLSERVOLBUSY;
911 tv = XAttachVolume(&error, volume, partition, mode);
915 VDetachVolume(&code, tv);
923 strcpy(tt->lastProcName, "TransCreate");
925 return VOLSERTRELE_ERROR;
930 /* using aindex as a 0-based index, return the aindex'th volume on this server
931 * Both the volume number and partition number (one-based) are returned.
934 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
939 code = VolGetNthVolume(acid, aindex, avolume, apart);
940 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
945 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
948 Log("1 Volser: GetNthVolume: Not yet implemented\n");
952 /* return the volume flags (VT* constants in volser.h) associated with this
956 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
960 code = VolGetFlags(acid, atid, aflags);
961 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
966 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
968 register struct volser_trans *tt;
970 tt = FindTrans(atid);
973 if (tt->vflags & VTDeleted) {
974 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
979 strcpy(tt->lastProcName, "GetFlags");
980 tt->rxCallPtr = acid;
981 *aflags = tt->vflags;
982 tt->rxCallPtr = (struct rx_call *)0;
984 return VOLSERTRELE_ERROR;
989 /* Change the volume flags (VT* constants in volser.h) associated with this
990 * transaction. Effects take place immediately on volume, although volume
991 * remains attached as usual by the transaction.
994 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
998 code = VolSetFlags(acid, atid, aflags);
999 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1005 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1007 register struct volser_trans *tt;
1008 register struct Volume *vp;
1010 char caller[MAXKTCNAMELEN];
1012 if (!afsconf_SuperUser(tdir, acid, caller))
1013 return VOLSERBAD_ACCESS; /*not a super user */
1014 /* find the trans */
1015 tt = FindTrans(atid);
1018 if (tt->vflags & VTDeleted) {
1019 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1024 strcpy(tt->lastProcName, "SetFlags");
1025 tt->rxCallPtr = acid;
1026 vp = tt->volume; /* pull volume out of transaction */
1028 /* check if we're allowed to make any updates */
1029 if (tt->iflags & ITReadOnly) {
1034 /* handle delete-on-salvage flag */
1035 if (aflags & VTDeleteOnSalvage) {
1036 V_destroyMe(tt->volume) = DESTROY_ME;
1038 V_destroyMe(tt->volume) = 0;
1041 if (aflags & VTOutOfService) {
1042 V_inService(vp) = 0;
1044 V_inService(vp) = 1;
1046 VUpdateVolume(&error, vp);
1047 tt->vflags = aflags;
1048 tt->rxCallPtr = (struct rx_call *)0;
1049 if (TRELE(tt) && !error)
1050 return VOLSERTRELE_ERROR;
1055 /* dumpS the volume associated with a particular transaction from a particular
1056 * date. Send the dump to a different transaction (destTrans) on the server
1057 * specified by the destServer structure.
1060 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1061 struct destServer *destination, afs_int32 destTrans,
1062 struct restoreCookie *cookie)
1067 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1068 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1069 destination->destHost, AUD_LONG, destTrans, AUD_END);
1074 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1075 struct destServer *destination, afs_int32 destTrans,
1076 struct restoreCookie *cookie)
1078 register struct volser_trans *tt;
1079 register afs_int32 code;
1080 register struct rx_connection *tcon;
1081 struct rx_call *tcall;
1082 register struct Volume *vp;
1083 struct rx_securityClass *securityObject;
1084 afs_int32 securityIndex;
1085 char caller[MAXKTCNAMELEN];
1087 if (!afsconf_SuperUser(tdir, acid, caller))
1088 return VOLSERBAD_ACCESS; /*not a super user */
1089 /* initialize things */
1090 tcon = (struct rx_connection *)0;
1091 tt = (struct volser_trans *)0;
1093 /* find the local transaction */
1094 tt = FindTrans(fromTrans);
1097 if (tt->vflags & VTDeleted) {
1098 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1103 strcpy(tt->lastProcName, "Forward");
1105 /* get auth info for the this connection (uses afs from ticket file) */
1106 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1112 /* make an rpc connection to the other server */
1114 rx_NewConnection(htonl(destination->destHost),
1115 htons(destination->destPort), VOLSERVICE_ID,
1116 securityObject, securityIndex);
1118 tt->rxCallPtr = (struct rx_call *)0;
1122 tcall = rx_NewCall(tcon);
1123 tt->rxCallPtr = tcall;
1124 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1125 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1130 /* these next calls implictly call rx_Write when writing out data */
1131 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1134 EndAFSVolRestore(tcall); /* probably doesn't do much */
1135 tt->rxCallPtr = (struct rx_call *)0;
1136 code = rx_EndCall(tcall, 0);
1137 rx_DestroyConnection(tcon); /* done with the connection */
1142 return VOLSERTRELE_ERROR;
1148 (void)rx_EndCall(tcall, 0);
1149 rx_DestroyConnection(tcon);
1152 tt->rxCallPtr = (struct rx_call *)0;
1158 /* Start a dump and send it to multiple places simultaneously.
1159 * If this returns an error (eg, return ENOENT), it means that
1160 * none of the releases worked. If this returns 0, that means
1161 * that one or more of the releases worked, and the caller has
1162 * to examine the results array to see which one(s).
1163 * This will only do EITHER incremental or full, not both, so it's
1164 * the caller's responsibility to be sure that all the destinations
1165 * need just an incremental (and from the same time), if that's
1169 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1170 fromDate, manyDests *destinations, afs_int32 spare,
1171 struct restoreCookie *cookie, manyResults *results)
1173 afs_int32 securityIndex;
1174 struct rx_securityClass *securityObject;
1175 char caller[MAXKTCNAMELEN];
1176 struct volser_trans *tt;
1177 afs_int32 ec, code, *codes;
1178 struct rx_connection **tcons;
1179 struct rx_call **tcalls;
1181 int i, is_incremental;
1184 memset(results, 0, sizeof(manyResults));
1186 if (!afsconf_SuperUser(tdir, acid, caller))
1187 return VOLSERBAD_ACCESS; /*not a super user */
1188 tt = FindTrans(fromTrans);
1191 if (tt->vflags & VTDeleted) {
1192 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1197 strcpy(tt->lastProcName, "ForwardMulti");
1199 /* (fromDate == 0) ==> full dump */
1200 is_incremental = (fromDate ? 1 : 0);
1202 i = results->manyResults_len = destinations->manyDests_len;
1203 results->manyResults_val = codes =
1204 (afs_int32 *) malloc(i * sizeof(afs_int32));
1206 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1207 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1209 /* get auth info for this connection (uses afs from ticket file) */
1210 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1212 goto fail; /* in order to audit each failure */
1215 /* make connections to all the other servers */
1216 for (i = 0; i < destinations->manyDests_len; i++) {
1217 struct replica *dest = &(destinations->manyDests_val[i]);
1219 rx_NewConnection(htonl(dest->server.destHost),
1220 htons(dest->server.destPort), VOLSERVICE_ID,
1221 securityObject, securityIndex);
1223 codes[i] = ENOTCONN;
1225 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1226 codes[i] = ENOTCONN;
1229 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1232 (void)rx_EndCall(tcalls[i], 0);
1234 rx_DestroyConnection(tcons[i]);
1241 /* these next calls implictly call rx_Write when writing out data */
1242 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1246 for (i--; i >= 0; i--) {
1247 struct replica *dest = &(destinations->manyDests_val[i]);
1249 if (!code && tcalls[i] && !codes[i]) {
1250 EndAFSVolRestore(tcalls[i]);
1253 ec = rx_EndCall(tcalls[i], 0);
1258 rx_DestroyConnection(tcons[i]); /* done with the connection */
1261 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1262 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1263 dest->trans, AUD_END);
1269 tt->rxCallPtr = (struct rx_call *)0;
1270 if (TRELE(tt) && !code) /* return the first code if it's set */
1271 return VOLSERTRELE_ERROR;
1278 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1282 code = VolDump(acid, fromTrans, fromDate, 0);
1283 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1288 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1292 code = VolDump(acid, fromTrans, fromDate, flags);
1293 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1298 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1301 register struct volser_trans *tt;
1302 char caller[MAXKTCNAMELEN];
1304 if (!afsconf_SuperUser(tdir, acid, caller))
1305 return VOLSERBAD_ACCESS; /*not a super user */
1306 tt = FindTrans(fromTrans);
1309 if (tt->vflags & VTDeleted) {
1310 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1314 strcpy(tt->lastProcName, "Dump");
1315 tt->rxCallPtr = acid;
1316 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1317 ? 0 : 1); /* squirt out the volume's data, too */
1319 tt->rxCallPtr = (struct rx_call *)0;
1323 tt->rxCallPtr = (struct rx_call *)0;
1326 return VOLSERTRELE_ERROR;
1332 * Ha! No more helper process!
1335 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1336 struct restoreCookie *cookie)
1340 code = VolRestore(acid, atrans, aflags, cookie);
1341 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1346 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1347 struct restoreCookie *cookie)
1349 register struct volser_trans *tt;
1350 register afs_int32 code, tcode;
1351 char caller[MAXKTCNAMELEN];
1353 if (!afsconf_SuperUser(tdir, acid, caller))
1354 return VOLSERBAD_ACCESS; /*not a super user */
1355 tt = FindTrans(atrans);
1358 if (tt->vflags & VTDeleted) {
1359 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1363 strcpy(tt->lastProcName, "Restore");
1364 tt->rxCallPtr = acid;
1366 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1368 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1369 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1370 tt->rxCallPtr = (struct rx_call *)0;
1373 return (code ? code : tcode);
1376 /* end a transaction, returning the transaction's final error code in rcode */
1378 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1382 code = VolEndTrans(acid, destTrans, rcode);
1383 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1388 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1390 register struct volser_trans *tt;
1391 char caller[MAXKTCNAMELEN];
1393 if (!afsconf_SuperUser(tdir, acid, caller))
1394 return VOLSERBAD_ACCESS; /*not a super user */
1395 tt = FindTrans(destTrans);
1399 *rcode = tt->returnCode;
1400 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1406 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1410 code = VolSetForwarding(acid, atid, anewsite);
1411 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1417 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1419 register struct volser_trans *tt;
1420 char caller[MAXKTCNAMELEN];
1422 if (!afsconf_SuperUser(tdir, acid, caller))
1423 return VOLSERBAD_ACCESS; /*not a super user */
1424 tt = FindTrans(atid);
1427 if (tt->vflags & VTDeleted) {
1428 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1433 strcpy(tt->lastProcName, "SetForwarding");
1434 tt->rxCallPtr = acid;
1435 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
1436 tt->rxCallPtr = (struct rx_call *)0;
1438 return VOLSERTRELE_ERROR;
1444 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1445 register struct volser_status *astatus)
1449 code = VolGetStatus(acid, atrans, astatus);
1450 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1455 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1456 register struct volser_status *astatus)
1458 register struct Volume *tv;
1459 register struct VolumeDiskData *td;
1460 struct volser_trans *tt;
1463 tt = FindTrans(atrans);
1466 if (tt->vflags & VTDeleted) {
1467 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1472 strcpy(tt->lastProcName, "GetStatus");
1473 tt->rxCallPtr = acid;
1476 tt->rxCallPtr = (struct rx_call *)0;
1481 td = &tv->header->diskstuff;
1482 astatus->volID = td->id;
1483 astatus->nextUnique = td->uniquifier;
1484 astatus->type = td->type;
1485 astatus->parentID = td->parentId;
1486 astatus->cloneID = td->cloneId;
1487 astatus->backupID = td->backupId;
1488 astatus->restoredFromID = td->restoredFromId;
1489 astatus->maxQuota = td->maxquota;
1490 astatus->minQuota = td->minquota;
1491 astatus->owner = td->owner;
1492 astatus->creationDate = td->creationDate;
1493 astatus->accessDate = td->accessDate;
1494 astatus->updateDate = td->updateDate;
1495 astatus->expirationDate = td->expirationDate;
1496 astatus->backupDate = td->backupDate;
1497 astatus->copyDate = td->copyDate;
1498 tt->rxCallPtr = (struct rx_call *)0;
1500 return VOLSERTRELE_ERROR;
1506 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1507 register struct volintInfo *astatus)
1511 code = VolSetInfo(acid, atrans, astatus);
1512 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1517 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1518 register struct volintInfo *astatus)
1520 register struct Volume *tv;
1521 register struct VolumeDiskData *td;
1522 struct volser_trans *tt;
1523 char caller[MAXKTCNAMELEN];
1526 if (!afsconf_SuperUser(tdir, acid, caller))
1527 return VOLSERBAD_ACCESS; /*not a super user */
1528 tt = FindTrans(atrans);
1531 if (tt->vflags & VTDeleted) {
1532 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1536 strcpy(tt->lastProcName, "SetStatus");
1537 tt->rxCallPtr = acid;
1540 tt->rxCallPtr = (struct rx_call *)0;
1545 td = &tv->header->diskstuff;
1547 * Add more fields as necessary
1549 if (astatus->maxquota != -1)
1550 td->maxquota = astatus->maxquota;
1551 if (astatus->dayUse != -1)
1552 td->dayUse = astatus->dayUse;
1553 if (astatus->creationDate != -1)
1554 td->creationDate = astatus->creationDate;
1555 if (astatus->updateDate != -1)
1556 td->updateDate = astatus->updateDate;
1557 if (astatus->spare2 != -1)
1558 td->volUpdateCounter = (unsigned int)astatus->spare2;
1559 VUpdateVolume(&error, tv);
1560 tt->rxCallPtr = (struct rx_call *)0;
1562 return VOLSERTRELE_ERROR;
1568 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1572 code = VolGetName(acid, atrans, aname);
1573 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1578 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1580 register struct Volume *tv;
1581 register struct VolumeDiskData *td;
1582 struct volser_trans *tt;
1586 tt = FindTrans(atrans);
1589 if (tt->vflags & VTDeleted) {
1590 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1594 strcpy(tt->lastProcName, "GetName");
1595 tt->rxCallPtr = acid;
1598 tt->rxCallPtr = (struct rx_call *)0;
1603 td = &tv->header->diskstuff;
1604 len = strlen(td->name) + 1; /* don't forget the null */
1606 tt->rxCallPtr = (struct rx_call *)0;
1610 *aname = (char *)malloc(len);
1611 strcpy(*aname, td->name);
1612 tt->rxCallPtr = (struct rx_call *)0;
1614 return VOLSERTRELE_ERROR;
1619 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1622 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1623 afs_int32 parentId, afs_int32 cloneId)
1629 /*return a list of all partitions on the server. The non mounted
1630 *partitions are returned as -1 in the corresponding slot in partIds*/
1632 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1636 code = VolListPartitions(acid, partIds);
1637 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1642 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1647 strcpy(namehead, "/vicep"); /*7 including null terminator */
1649 /* Just return attached partitions. */
1651 for (i = 0; i < 26; i++) {
1652 namehead[6] = i + 'a';
1653 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1659 /*return a list of all partitions on the server. The non mounted
1660 *partitions are returned as -1 in the corresponding slot in partIds*/
1662 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1666 code = XVolListPartitions(acid, pEntries);
1667 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1672 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1674 struct stat rbuf, pbuf;
1676 struct partList partList;
1677 struct DiskPartition *dp;
1680 strcpy(namehead, "/vicep"); /*7 including null terminator */
1682 /* Only report attached partitions */
1683 for (i = 0; i < VOLMAXPARTS; i++) {
1684 #ifdef AFS_DEMAND_ATTACH_FS
1685 dp = VGetPartitionById(i, 0);
1688 namehead[6] = i + 'a';
1692 namehead[6] = 'a' + (k / 26);
1693 namehead[7] = 'a' + (k % 26);
1696 dp = VGetPartition(namehead, 0);
1699 partList.partId[j++] = i;
1701 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1702 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1704 pEntries->partEntries_len = j;
1709 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1711 ExtractVolId(char vname[])
1714 char name[VOLSER_MAXVOLNAME + 1];
1716 strcpy(name, vname);
1718 while (name[i] == 'V' || name[i] == '0')
1721 name[11] = '\0'; /* smash the "." */
1722 return (atol(&name[i]));
1725 /*return the name of the next volume header in the directory associated with dirp and dp.
1726 *the volume id is returned in volid, and volume header name is returned in volname*/
1728 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1732 dp = readdir(dirp); /*read next entry in the directory */
1734 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1735 *volid = ExtractVolId(dp->d_name);
1736 strcpy(volname, dp->d_name);
1737 return 0; /*return the name of the file representing a volume */
1739 strcpy(volname, "");
1740 return 0; /*volname doesnot represent a volume */
1743 strcpy(volname, "EOD");
1744 return 0; /*end of directory */
1749 /*return the header information about the <volid> */
1751 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1752 volumeId, volEntries *volumeInfo)
1756 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
1757 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1762 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1763 volumeId, volEntries *volumeInfo)
1766 register struct Volume *tv;
1767 struct DiskPartition *partP;
1768 struct volser_trans *ttc;
1769 char pname[9], volname[20];
1770 afs_int32 error = 0;
1776 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
1777 pntr = volumeInfo->volEntries_val;
1778 volumeInfo->volEntries_len = 1;
1779 if (GetPartName(partid, pname))
1780 return VOLSERILLEGAL_PARTITION;
1781 if (!(partP = VGetPartition(pname, 0)))
1782 return VOLSERILLEGAL_PARTITION;
1783 dirp = opendir(VPartitionPath(partP));
1785 return VOLSERILLEGAL_PARTITION;
1786 strcpy(volname, "");
1787 ttc = (struct volser_trans *)0;
1788 tv = (Volume *) 0; /* volume not attached */
1790 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
1792 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
1793 GetNextVol(dirp, volname, &volid);
1794 continue; /*back to while loop */
1797 if (volid == volumeId) { /*copy other things too */
1799 #ifndef AFS_PTHREAD_ENV
1800 IOMGR_Poll(); /*make sure that the client doesnot time out */
1802 ttc = NewTrans(volid, partid);
1804 pntr->status = VBUSY;
1805 pntr->volid = volid;
1808 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
1810 pntr->status = 0; /*things are messed up */
1811 strcpy(pntr->name, volname);
1812 pntr->volid = volid;
1813 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
1816 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1817 /*this volume will be salvaged */
1819 strcpy(pntr->name, volname);
1820 pntr->volid = volid;
1821 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
1825 if (tv->header->diskstuff.needsSalvaged) {
1826 /*this volume will be salvaged */
1828 strcpy(pntr->name, volname);
1829 pntr->volid = volid;
1830 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
1834 /*read in the relevant info */
1835 pntr->status = VOK; /*its ok */
1836 pntr->volid = tv->header->diskstuff.id;
1837 strcpy(pntr->name, tv->header->diskstuff.name);
1838 pntr->type = tv->header->diskstuff.type; /*if ro volume */
1839 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
1840 pntr->backupID = tv->header->diskstuff.backupId;
1841 pntr->parentID = tv->header->diskstuff.parentId;
1842 pntr->copyDate = tv->header->diskstuff.copyDate;
1843 pntr->inUse = tv->header->diskstuff.inUse;
1844 pntr->size = tv->header->diskstuff.diskused;
1845 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1846 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1847 pntr->maxquota = tv->header->diskstuff.maxquota;
1848 pntr->filecount = tv->header->diskstuff.filecount;
1849 now = FT_ApproxTime();
1850 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1853 pntr->dayUse = tv->header->diskstuff.dayUse;
1854 pntr->creationDate = tv->header->diskstuff.creationDate;
1855 pntr->accessDate = tv->header->diskstuff.accessDate;
1856 pntr->updateDate = tv->header->diskstuff.updateDate;
1857 pntr->backupDate = tv->header->diskstuff.backupDate;
1858 pntr->spare0 = tv->header->diskstuff.minquota;
1860 (long)tv->header->diskstuff.weekUse[0] +
1861 (long)tv->header->diskstuff.weekUse[1] +
1862 (long)tv->header->diskstuff.weekUse[2] +
1863 (long)tv->header->diskstuff.weekUse[3] +
1864 (long)tv->header->diskstuff.weekUse[4] +
1865 (long)tv->header->diskstuff.weekUse[5] +
1866 (long)tv->header->diskstuff.weekUse[6];
1867 pntr->spare2 = V_volUpCounter(tv);
1868 pntr->flags = pntr->spare3 = (long)0;
1869 VDetachVolume(&error, tv); /*free the volume */
1872 pntr->status = 0; /*things are messed up */
1873 strcpy(pntr->name, volname);
1874 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
1879 GetNextVol(dirp, volname, &volid);
1883 VDetachVolume(&error, tv);
1887 DeleteTrans(ttc, 1);
1888 ttc = (struct volser_trans *)0;
1898 /*------------------------------------------------------------------------
1899 * EXPORTED SAFSVolXListOneVolume
1902 * Returns extended info on volume a_volID on partition a_partID.
1905 * a_rxCidP : Pointer to the Rx call we're performing.
1906 * a_partID : Partition for which we want the extended list.
1907 * a_volID : Volume ID we wish to know about.
1908 * a_volumeXInfoP : Ptr to the extended info blob.
1911 * 0 Successful operation
1912 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1915 * Nothing interesting.
1919 *------------------------------------------------------------------------*/
1922 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1923 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1927 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1928 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1933 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1934 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1935 { /*SAFSVolXListOneVolume */
1937 volintXInfo *xInfoP; /*Ptr to the extended vol info */
1938 register struct Volume *tv; /*Volume ptr */
1939 struct volser_trans *ttc; /*Volume transaction ptr */
1940 struct DiskPartition *partP; /*Ptr to partition */
1941 char pname[9], volname[20]; /*Partition, volume names */
1942 afs_int32 error; /*Error code */
1943 afs_int32 code; /*Return code */
1944 DIR *dirp; /*Partition directory ptr */
1945 afs_int32 currVolID; /*Current volume ID */
1946 int found = 0; /*Did we find the volume we need? */
1947 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
1948 int numStatBytes; /*Num stat bytes to copy per volume */
1952 * Set up our pointers for action, marking our structure to hold exactly
1953 * one entry. Also, assume we'll fail in our quest.
1955 a_volumeXInfoP->volXEntries_val =
1956 (volintXInfo *) malloc(sizeof(volintXInfo));
1957 xInfoP = a_volumeXInfoP->volXEntries_val;
1958 a_volumeXInfoP->volXEntries_len = 1;
1962 * If the partition name we've been given is bad, bogue out.
1964 if (GetPartName(a_partID, pname))
1965 return (VOLSERILLEGAL_PARTITION);
1968 * Open the directory representing the given AFS parttion. If we can't
1971 if (!(partP = VGetPartition(pname, 0)))
1972 return VOLSERILLEGAL_PARTITION;
1973 dirp = opendir(VPartitionPath(partP));
1975 return (VOLSERILLEGAL_PARTITION);
1978 * Sweep through the partition directory, looking for the desired entry.
1979 * First, of course, figure out how many stat bytes to copy out of each
1983 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1984 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1985 strcpy(volname, "");
1986 ttc = (struct volser_trans *)0; /*No transaction yet */
1987 tv = (Volume *) 0; /*Volume not yet attached */
1989 while (strcmp(volname, "EOD") && !found) {
1991 * If this is not a volume, move on to the next entry in the
1992 * partition's directory.
1994 if (!strcmp(volname, "")) {
1995 GetNextVol(dirp, volname, &currVolID);
1999 if (currVolID == a_volID) {
2001 * We found the volume entry we're interested. Pull out the
2002 * extended information, remembering to poll (so that the client
2003 * doesn't time out) and to set up a transaction on the volume.
2006 #ifndef AFS_PTHREAD_ENV
2009 ttc = NewTrans(currVolID, a_partID);
2012 * Couldn't get a transaction on this volume; let our caller
2015 xInfoP->status = VBUSY;
2016 xInfoP->volid = currVolID;
2021 * Attach the volume, give up on the volume if we can't.
2023 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2025 xInfoP->status = 0; /*things are messed up */
2026 strcpy(xInfoP->name, volname);
2027 xInfoP->volid = currVolID;
2028 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
2034 * Also bag out on this volume if it's been marked as needing a
2035 * salvage or to-be-destroyed.
2037 volDiskDataP = &(tv->header->diskstuff);
2038 if (volDiskDataP->destroyMe == DESTROY_ME) {
2040 strcpy(xInfoP->name, volname);
2041 xInfoP->volid = currVolID;
2042 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2046 if (volDiskDataP->needsSalvaged) {
2048 strcpy(xInfoP->name, volname);
2049 xInfoP->volid = currVolID;
2050 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
2055 * Pull out the desired info and stuff it into the area we'll be
2056 * returning to our caller.
2058 strcpy(xInfoP->name, volDiskDataP->name);
2059 xInfoP->volid = volDiskDataP->id;
2060 xInfoP->type = volDiskDataP->type;
2061 xInfoP->backupID = volDiskDataP->backupId;
2062 xInfoP->parentID = volDiskDataP->parentId;
2063 xInfoP->cloneID = volDiskDataP->cloneId;
2064 xInfoP->status = VOK;
2065 xInfoP->copyDate = volDiskDataP->copyDate;
2066 xInfoP->inUse = volDiskDataP->inUse;
2067 xInfoP->creationDate = volDiskDataP->creationDate;
2068 xInfoP->accessDate = volDiskDataP->accessDate;
2069 xInfoP->updateDate = volDiskDataP->updateDate;
2070 xInfoP->backupDate = volDiskDataP->backupDate;
2071 xInfoP->filecount = volDiskDataP->filecount;
2072 xInfoP->maxquota = volDiskDataP->maxquota;
2073 xInfoP->size = volDiskDataP->diskused;
2076 * Copy out the stat fields in a single operation.
2078 now = FT_ApproxTime();
2079 if (now - volDiskDataP->dayUseDate > OneDay) {
2081 memset((char *)&(xInfoP->stat_reads[0]), 0, numStatBytes);
2083 xInfoP->dayUse = volDiskDataP->dayUse;
2084 memcpy((char *)&(xInfoP->stat_reads[0]),
2085 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2089 * We're done copying. Detach the volume and iterate (at this
2090 * point, since we found our volume, we'll then drop out of the
2093 VDetachVolume(&error, tv);
2097 strcpy(xInfoP->name, volname);
2098 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2104 * At this point, we're golden.
2107 } /*Found desired volume */
2108 GetNextVol(dirp, volname, &currVolID);
2112 * Drop the transaction we have for this volume.
2116 VDetachVolume(&error, tv);
2120 DeleteTrans(ttc, 1);
2121 ttc = (struct volser_trans *)0;
2125 * Clean up before going to dinner: close the partition directory,
2126 * return the proper value.
2131 } /*SAFSVolXListOneVolume */
2133 /*returns all the volumes on partition partid. If flags = 1 then all the
2134 * relevant info about the volumes is also returned */
2136 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2137 volEntries *volumeInfo)
2141 code = VolListVolumes(acid, partid, flags, volumeInfo);
2142 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2147 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2148 volEntries *volumeInfo)
2151 register struct Volume *tv;
2152 struct DiskPartition *partP;
2153 struct volser_trans *ttc;
2154 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2155 char pname[9], volname[20];
2156 afs_int32 error = 0;
2161 volumeInfo->volEntries_val =
2162 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2163 pntr = volumeInfo->volEntries_val;
2164 volumeInfo->volEntries_len = 0;
2165 if (GetPartName(partid, pname))
2166 return VOLSERILLEGAL_PARTITION;
2167 if (!(partP = VGetPartition(pname, 0)))
2168 return VOLSERILLEGAL_PARTITION;
2169 dirp = opendir(VPartitionPath(partP));
2171 return VOLSERILLEGAL_PARTITION;
2172 strcpy(volname, "");
2173 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2174 ttc = (struct volser_trans *)0; /* new one for each pass */
2175 tv = (Volume *) 0; /* volume not attached */
2177 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2178 GetNextVol(dirp, volname, &volid);
2179 continue; /*back to while loop */
2182 if (flags) { /*copy other things too */
2183 #ifndef AFS_PTHREAD_ENV
2184 IOMGR_Poll(); /*make sure that the client doesnot time out */
2186 ttc = NewTrans(volid, partid);
2188 pntr->status = VBUSY;
2189 pntr->volid = volid;
2192 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2194 pntr->status = 0; /*things are messed up */
2195 strcpy(pntr->name, volname);
2196 pntr->volid = volid;
2197 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
2200 if (tv->header->diskstuff.needsSalvaged) {
2201 /*this volume will be salvaged */
2203 strcpy(pntr->name, volname);
2204 pntr->volid = volid;
2205 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
2209 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2210 /*this volume will be salvaged */
2213 /*read in the relevant info */
2214 pntr->status = VOK; /*its ok */
2215 pntr->volid = tv->header->diskstuff.id;
2216 strcpy(pntr->name, tv->header->diskstuff.name);
2217 pntr->type = tv->header->diskstuff.type; /*if ro volume */
2218 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
2219 pntr->backupID = tv->header->diskstuff.backupId;
2220 pntr->parentID = tv->header->diskstuff.parentId;
2221 pntr->copyDate = tv->header->diskstuff.copyDate;
2222 pntr->inUse = tv->header->diskstuff.inUse;
2223 pntr->size = tv->header->diskstuff.diskused;
2224 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2225 pntr->maxquota = tv->header->diskstuff.maxquota;
2226 pntr->filecount = tv->header->diskstuff.filecount;
2227 now = FT_ApproxTime();
2228 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2231 pntr->dayUse = tv->header->diskstuff.dayUse;
2232 pntr->creationDate = tv->header->diskstuff.creationDate;
2233 pntr->accessDate = tv->header->diskstuff.accessDate;
2234 pntr->updateDate = tv->header->diskstuff.updateDate;
2235 pntr->backupDate = tv->header->diskstuff.backupDate;
2236 pntr->spare0 = tv->header->diskstuff.minquota;
2238 (long)tv->header->diskstuff.weekUse[0] +
2239 (long)tv->header->diskstuff.weekUse[1] +
2240 (long)tv->header->diskstuff.weekUse[2] +
2241 (long)tv->header->diskstuff.weekUse[3] +
2242 (long)tv->header->diskstuff.weekUse[4] +
2243 (long)tv->header->diskstuff.weekUse[5] +
2244 (long)tv->header->diskstuff.weekUse[6];
2245 pntr->spare2 = V_volUpCounter(tv);
2246 pntr->flags = pntr->spare3 = (long)0;
2247 VDetachVolume(&error, tv); /*free the volume */
2250 pntr->status = 0; /*things are messed up */
2251 strcpy(pntr->name, volname);
2252 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2257 pntr->volid = volid;
2258 /*just volids are needed */
2263 DeleteTrans(ttc, 1);
2264 ttc = (struct volser_trans *)0;
2267 volumeInfo->volEntries_len += 1;
2268 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2269 /*running out of space, allocate more space */
2270 allocSize = (allocSize * 3) / 2;
2272 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2273 allocSize * sizeof(volintInfo));
2276 VDetachVolume(&error, tv);
2280 DeleteTrans(ttc, 1);
2281 ttc = (struct volser_trans *)0;
2284 return VOLSERNO_MEMORY;
2286 volumeInfo->volEntries_val = pntr; /* point to new block */
2287 /* set pntr to the right position */
2288 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2294 VDetachVolume(&error, tv);
2298 DeleteTrans(ttc, 1);
2299 ttc = (struct volser_trans *)0;
2301 GetNextVol(dirp, volname, &volid);
2306 DeleteTrans(ttc, 1);
2311 /*------------------------------------------------------------------------
2312 * EXPORTED SAFSVolXListVolumes
2315 * Returns all the volumes on partition a_partID. If a_flags
2316 * is set to 1, then all the relevant extended volume information
2320 * a_rxCidP : Pointer to the Rx call we're performing.
2321 * a_partID : Partition for which we want the extended list.
2322 * a_flags : Various flags.
2323 * a_volumeXInfoP : Ptr to the extended info blob.
2326 * 0 Successful operation
2327 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2328 * VOLSERNO_MEMORY if we ran out of memory allocating
2332 * Nothing interesting.
2336 *------------------------------------------------------------------------*/
2339 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2340 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2344 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2345 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2350 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2351 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2352 { /*SAFSVolXListVolumes */
2354 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2355 register struct Volume *tv; /*Volume ptr */
2356 struct DiskPartition *partP; /*Ptr to partition */
2357 struct volser_trans *ttc; /*Volume transaction ptr */
2358 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2359 char pname[9], volname[20]; /*Partition, volume names */
2360 afs_int32 error = 0; /*Return code */
2361 DIR *dirp; /*Partition directory ptr */
2362 afs_int32 volid; /*Current volume ID */
2363 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2364 int numStatBytes; /*Num stat bytes to copy per volume */
2368 * Allocate a large array of extended volume info structures, then
2369 * set it up for action.
2371 a_volumeXInfoP->volXEntries_val =
2372 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2373 xInfoP = a_volumeXInfoP->volXEntries_val;
2374 a_volumeXInfoP->volXEntries_len = 0;
2377 * If the partition name we've been given is bad, bogue out.
2379 if (GetPartName(a_partID, pname))
2380 return (VOLSERILLEGAL_PARTITION);
2383 * Open the directory representing the given AFS parttion. If we can't
2386 if (!(partP = VGetPartition(pname, 0)))
2387 return VOLSERILLEGAL_PARTITION;
2388 dirp = opendir(VPartitionPath(partP));
2390 return (VOLSERILLEGAL_PARTITION);
2393 * Sweep through the partition directory, acting on each entry. First,
2394 * of course, figure out how many stat bytes to copy out of each volume.
2397 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2398 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2399 strcpy(volname, "");
2400 while (strcmp(volname, "EOD")) {
2401 ttc = (struct volser_trans *)0; /*New one for each pass */
2402 tv = (Volume *) 0; /*Volume not yet attached */
2405 * If this is not a volume, move on to the next entry in the
2406 * partition's directory.
2408 if (!strcmp(volname, "")) {
2409 GetNextVol(dirp, volname, &volid);
2415 * Full info about the volume desired. Poll to make sure the
2416 * client doesn't time out, then start up a new transaction.
2418 #ifndef AFS_PTHREAD_ENV
2421 ttc = NewTrans(volid, a_partID);
2424 * Couldn't get a transaction on this volume; let our caller
2427 xInfoP->status = VBUSY;
2428 xInfoP->volid = volid;
2433 * Attach the volume, give up on this volume if we can't.
2435 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2437 xInfoP->status = 0; /*things are messed up */
2438 strcpy(xInfoP->name, volname);
2439 xInfoP->volid = volid;
2440 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2446 * Also bag out on this volume if it's been marked as needing a
2447 * salvage or to-be-destroyed.
2449 volDiskDataP = &(tv->header->diskstuff);
2450 if (volDiskDataP->needsSalvaged) {
2452 strcpy(xInfoP->name, volname);
2453 xInfoP->volid = volid;
2454 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
2458 if (volDiskDataP->destroyMe == DESTROY_ME)
2462 * Pull out the desired info and stuff it into the area we'll be
2463 * returning to our caller.
2465 strcpy(xInfoP->name, volDiskDataP->name);
2466 xInfoP->volid = volDiskDataP->id;
2467 xInfoP->type = volDiskDataP->type;
2468 xInfoP->backupID = volDiskDataP->backupId;
2469 xInfoP->parentID = volDiskDataP->parentId;
2470 xInfoP->cloneID = volDiskDataP->cloneId;
2471 xInfoP->status = VOK;
2472 xInfoP->copyDate = volDiskDataP->copyDate;
2473 xInfoP->inUse = volDiskDataP->inUse;
2474 xInfoP->creationDate = volDiskDataP->creationDate;
2475 xInfoP->accessDate = volDiskDataP->accessDate;
2476 xInfoP->updateDate = volDiskDataP->updateDate;
2477 xInfoP->backupDate = volDiskDataP->backupDate;
2478 now = FT_ApproxTime();
2479 if (now - volDiskDataP->dayUseDate > OneDay)
2482 xInfoP->dayUse = volDiskDataP->dayUse;
2483 xInfoP->filecount = volDiskDataP->filecount;
2484 xInfoP->maxquota = volDiskDataP->maxquota;
2485 xInfoP->size = volDiskDataP->diskused;
2488 * Copy out the stat fields in a single operation.
2490 memcpy((char *)&(xInfoP->stat_reads[0]),
2491 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2494 * We're done copying. Detach the volume and iterate.
2496 VDetachVolume(&error, tv);
2500 strcpy(xInfoP->name, volname);
2501 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2505 } /*Full contents desired */
2508 * Just volume IDs are needed.
2510 xInfoP->volid = volid;
2514 * Drop the transaction we have for this volume.
2517 DeleteTrans(ttc, 1);
2518 ttc = (struct volser_trans *)0;
2522 * Bump the pointer in the data area we're building, along with
2523 * the count of the number of entries it contains.
2526 (a_volumeXInfoP->volXEntries_len)++;
2527 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2529 * We're running out of space in the area we've built. Grow it.
2531 allocSize = (allocSize * 3) / 2;
2532 xInfoP = (volintXInfo *)
2533 realloc((char *)a_volumeXInfoP->volXEntries_val,
2534 (allocSize * sizeof(volintXInfo)));
2535 if (xInfoP == NULL) {
2537 * Bummer, no memory. Bag it, tell our caller what went wrong.
2540 VDetachVolume(&error, tv);
2544 DeleteTrans(ttc, 1);
2545 ttc = (struct volser_trans *)0;
2548 return (VOLSERNO_MEMORY);
2552 * Memory reallocation worked. Correct our pointers so they
2553 * now point to the new block and the current open position within
2556 a_volumeXInfoP->volXEntries_val = xInfoP;
2558 a_volumeXInfoP->volXEntries_val +
2559 a_volumeXInfoP->volXEntries_len;
2561 /*Need more space */
2564 * Detach our current volume and the transaction on it, then move on
2565 * to the next volume in the partition directory.
2568 VDetachVolume(&error, tv);
2572 DeleteTrans(ttc, 1);
2573 ttc = (struct volser_trans *)0;
2575 GetNextVol(dirp, volname, &volid);
2576 } /*Sweep through the partition directory */
2579 * We've examined all entries in the partition directory. Close it,
2580 * delete our transaction (if any), and go home happy.
2584 DeleteTrans(ttc, 1);
2587 } /*SAFSVolXListVolumes */
2589 /*this call is used to monitor the status of volser for debugging purposes.
2590 *information about all the active transactions is returned in transInfo*/
2592 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2596 code = VolMonitor(acid, transInfo);
2597 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2602 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2604 transDebugInfo *pntr;
2605 afs_int32 allocSize = 50;
2606 struct volser_trans *tt, *allTrans;
2608 transInfo->transDebugEntries_val =
2609 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2610 pntr = transInfo->transDebugEntries_val;
2611 transInfo->transDebugEntries_len = 0;
2612 allTrans = TransList();
2613 if (allTrans == (struct volser_trans *)0)
2614 return 0; /*no active transactions */
2615 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2616 pntr->tid = tt->tid;
2617 pntr->time = tt->time;
2618 pntr->creationTime = tt->creationTime;
2619 pntr->returnCode = tt->returnCode;
2620 pntr->volid = tt->volid;
2621 pntr->partition = tt->partition;
2622 pntr->iflags = tt->iflags;
2623 pntr->vflags = tt->vflags;
2624 pntr->tflags = tt->tflags;
2625 strcpy(pntr->lastProcName, tt->lastProcName);
2626 pntr->callValid = 0;
2627 if (tt->rxCallPtr) { /*record call related info */
2628 pntr->callValid = 1;
2629 pntr->readNext = tt->rxCallPtr->rnext;
2630 pntr->transmitNext = tt->rxCallPtr->tnext;
2631 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2632 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2635 transInfo->transDebugEntries_len += 1;
2636 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2637 allocSize = (allocSize * 3) / 2;
2639 (transDebugInfo *) realloc((char *)transInfo->
2640 transDebugEntries_val,
2642 sizeof(transDebugInfo));
2643 transInfo->transDebugEntries_val = pntr;
2645 transInfo->transDebugEntries_val +
2646 transInfo->transDebugEntries_len;
2647 /*set pntr to right position */
2656 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2660 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2661 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2662 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2668 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2671 afs_int32 error = 0;
2672 register struct volser_trans *tt;
2673 char caller[MAXKTCNAMELEN];
2675 if (strlen(name) > 31)
2676 return VOLSERBADNAME;
2677 if (!afsconf_SuperUser(tdir, acid, caller))
2678 return VOLSERBAD_ACCESS; /*not a super user */
2679 /* find the trans */
2680 tt = FindTrans(atid);
2683 if (tt->vflags & VTDeleted) {
2684 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2688 strcpy(tt->lastProcName, "SetIdsTypes");
2689 tt->rxCallPtr = acid;
2693 V_backupId(tv) = backupId;
2694 V_cloneId(tv) = cloneId;
2695 V_parentId(tv) = pId;
2696 strcpy((&V_disk(tv))->name, name);
2697 VUpdateVolume(&error, tv);
2699 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2703 tt->rxCallPtr = (struct rx_call *)0;
2704 if (TRELE(tt) && !error)
2705 return VOLSERTRELE_ERROR;
2709 tt->rxCallPtr = (struct rx_call *)0;
2710 if (TRELE(tt) && !error)
2711 return VOLSERTRELE_ERROR;
2716 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2720 code = VolSetDate(acid, atid, cdate);
2721 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2727 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2730 afs_int32 error = 0;
2731 register struct volser_trans *tt;
2732 char caller[MAXKTCNAMELEN];
2734 if (!afsconf_SuperUser(tdir, acid, caller))
2735 return VOLSERBAD_ACCESS; /*not a super user */
2736 /* find the trans */
2737 tt = FindTrans(atid);
2740 if (tt->vflags & VTDeleted) {
2741 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2745 strcpy(tt->lastProcName, "SetDate");
2746 tt->rxCallPtr = acid;
2749 V_creationDate(tv) = cdate;
2750 VUpdateVolume(&error, tv);
2752 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2756 tt->rxCallPtr = (struct rx_call *)0;
2757 if (TRELE(tt) && !error)
2758 return VOLSERTRELE_ERROR;
2762 tt->rxCallPtr = (struct rx_call *)0;
2763 if (TRELE(tt) && !error)
2764 return VOLSERTRELE_ERROR;
2768 #ifdef AFS_NAMEI_ENV
2770 * Inode number format (from namei_ops.c):
2771 * low 26 bits - vnode number - all 1's if volume special file.
2773 * next 3 bits spare (0's)
2774 * high 32 bits - uniquifier (regular) or type if spare
2776 #define NAMEI_VNODEMASK 0x003ffffff
2777 #define NAMEI_TAGMASK 0x7
2778 #define NAMEI_TAGSHIFT 26
2779 #define NAMEI_UNIQMASK 0xffffffff
2780 #define NAMEI_UNIQSHIFT 32
2781 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2782 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2783 #endif /* AFS_NAMEI_ENV */
2786 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2789 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2793 afs_int32 error = 0;
2796 char caller[MAXKTCNAMELEN];
2797 char headername[16];
2800 struct VolumeDiskHeader h;
2804 struct DiskPartition *dp;
2806 if (!afsconf_SuperUser(tdir, acid, caller))
2807 return VOLSERBAD_ACCESS; /*not a super user */
2808 if (GetPartName(partId, pname))
2809 return VOLSERILLEGAL_PARTITION;
2810 dirp = opendir(pname);
2812 return VOLSERILLEGAL_PARTITION;
2813 strcpy(volname, "");
2815 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2816 GetNextVol(dirp, volname, &volid);
2817 if (strcmp(volname, "")) { /* its a volume */
2818 if (volid == volumeId)
2824 (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
2825 (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
2826 fd = open(opath, O_RDONLY);
2828 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2831 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2832 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2837 FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
2839 for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
2842 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2845 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
2846 IH_INIT(ih, dp->device, h.parent, ino);
2848 error = namei_ConvertROtoRWvolume(ih, volumeId);
2852 h.volumeInfo_hi = h.id;
2853 h.smallVnodeIndex_hi = h.id;
2854 h.largeVnodeIndex_hi = h.id;
2855 h.linkTable_hi = h.id;
2856 (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
2857 (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
2858 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
2860 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
2863 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
2864 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
2869 if (unlink(opath) < 0) {
2870 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
2872 FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
2873 FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
2875 #else /* AFS_NAMEI_ENV */
2877 #endif /* AFS_NAMEI_ENV */
2881 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2882 register struct volintSize *size)
2885 register struct volser_trans *tt;
2886 char caller[MAXKTCNAMELEN];
2888 if (!afsconf_SuperUser(tdir, acid, caller))
2889 return VOLSERBAD_ACCESS; /*not a super user */
2890 tt = FindTrans(fromTrans);
2893 if (tt->vflags & VTDeleted) {
2897 strcpy(tt->lastProcName, "GetSize");
2898 tt->rxCallPtr = acid;
2899 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2900 tt->rxCallPtr = (struct rx_call *)0;
2902 return VOLSERTRELE_ERROR;
2904 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2908 /* GetPartName - map partid (a decimal number) into pname (a string)
2909 * Since for NT we actually want to return the drive name, we map through the
2913 GetPartName(afs_int32 partid, char *pname)
2918 strcpy(pname, "/vicep");
2919 pname[6] = 'a' + partid;
2922 } else if (partid < VOLMAXPARTS) {
2923 strcpy(pname, "/vicep");
2925 pname[6] = 'a' + (partid / 26);
2926 pname[7] = 'a' + (partid % 26);