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>
53 #include <afs/cellconfig.h>
56 #include <afs/ihandle.h>
58 #include <afs/ntops.h>
60 #include <afs/vnode.h>
61 #include <afs/volume.h>
62 #include <afs/partition.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;
77 extern char *volutil_PartitionName();
79 extern void LogError(afs_int32 errcode);
81 /* Forward declarations */
82 static int GetPartName(afs_int32 partid, char *pname);
84 #define OneDay (24*60*60)
90 afs_int32 localTid = 1;
91 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
92 VolDeleteVolume(), VolClone();
93 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
94 VolForward(), VolDump();
95 afs_int32 VolForwardMultiple();
96 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
97 VolSetInfo(), VolGetName();
98 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(),
99 VolXListOneVolume(), VolXListVolumes();
100 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
101 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
103 /* this call unlocks all of the partition locks we've set */
106 register struct DiskPartition *tp;
107 for (tp = DiskPartitionList; tp; tp = tp->next) {
108 if (tp->lock_fd != -1) {
109 close(tp->lock_fd); /* releases flock held on this partition */
116 /* get partition id from a name */
122 register int code = 0;
127 return -1; /* unknown */
129 /* otherwise check for vicepa or /vicepa, or just plain "a" */
131 if (!strncmp(aname, "/vicep", 6)) {
132 strncpy(ascii, aname + 6, 2);
134 return -1; /* bad partition name */
135 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
136 * from 0. Do the appropriate conversion */
138 /* one char name, 0..25 */
139 if (ascii[0] < 'a' || ascii[0] > 'z')
140 return -1; /* wrongo */
141 return ascii[0] - 'a';
143 /* two char name, 26 .. <whatever> */
144 if (ascii[0] < 'a' || ascii[0] > 'z')
145 return -1; /* wrongo */
146 if (ascii[1] < 'a' || ascii[1] > 'z')
147 return -1; /* just as bad */
148 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
149 if (code > VOLMAXPARTS)
156 ConvertVolume(avol, aname, asize)
163 /* 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 */
164 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
169 ConvertPartition(apartno, aname, asize)
178 strcpy(aname, "/vicep");
180 aname[6] = 'a' + apartno;
184 aname[6] = 'a' + (apartno / 26);
185 aname[7] = 'a' + (apartno % 26);
191 /* the only attach function that takes a partition is "...ByName", so we use it */
193 XAttachVolume(error, avolid, apartid, amode)
199 char pbuf[30], vbuf[20];
200 register struct Volume *tv;
202 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
206 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
210 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
214 /* Adapted from the file server; create a root directory for this volume */
220 struct acl_accessList *ACL;
222 Inode inodeNumber, nearInode;
223 char buf[SIZEOF_LARGEDISKVNODE];
224 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
225 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
231 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
233 V_pref(vp, nearInode);
235 IH_CREATE(V_linkHandle(vp), V_device(vp),
236 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
238 assert(VALID_INO(inodeNumber));
240 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
241 did.Volume = V_id(vp);
242 did.Vnode = (VnodeId) 1;
245 assert(!(MakeDir(&dir, &did, &did)));
246 DFlush(); /* flush all modified dir buffers out */
247 DZap(&dir); /* Remove all buffers for this dir */
248 length = Length(&dir); /* Remember size of this directory */
250 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
252 /* build a single entry ACL that gives all rights to system:administrators */
253 /* this section of code assumes that access list format is not going to
256 ACL = VVnodeDiskACL(vnode);
257 ACL->size = sizeof(struct acl_accessList);
258 ACL->version = ACL_ACLVERSION;
262 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
263 ACL->entries[0].rights =
264 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
265 | PRSFS_LOCK | PRSFS_ADMINISTER;
267 vnode->type = vDirectory;
269 vnode->modeBits = 0777;
270 vnode->linkCount = 2;
271 VNDISK_SET_LEN(vnode, length);
272 vnode->uniquifier = 1;
273 V_uniquifier(vp) = vnode->uniquifier + 1;
274 vnode->dataVersion = 1;
275 VNDISK_SET_INO(vnode, inodeNumber);
276 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
280 vnode->vnodeMagic = vcp->magic;
282 IH_INIT(h, vp->device, V_parentId(vp),
283 vp->vnodeIndex[vLarge].handle->ih_ino);
286 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
288 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
289 assert(code == SIZEOF_LARGEDISKVNODE);
290 FDH_REALLYCLOSE(fdP);
292 VNDISK_GET_LEN(length, vnode);
293 V_diskused(vp) = nBlocks(length);
299 SAFSVolPartitionInfo(acid, pname, partition)
300 struct rx_call *acid;
302 struct diskPartition *partition;
306 code = VolPartitionInfo(acid, pname, partition);
307 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
312 VolPartitionInfo(acid, pname, partition)
313 struct rx_call *acid;
315 struct diskPartition *partition;
317 register struct DiskPartition *dp;
320 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
323 dp = VGetPartition(pname, 0);
325 strncpy(partition->name, dp->name, 32);
326 strncpy(partition->devName, dp->devName, 32);
327 partition->lock_fd = dp->lock_fd;
328 partition->free = dp->free;
329 partition->minFree = dp->totalUsable;
332 return VOLSERILLEGAL_PARTITION;
335 /* obliterate a volume completely, and slowly. */
337 SAFSVolNukeVolume(acid, apartID, avolID)
338 struct rx_call *acid;
339 afs_int32 apartID, avolID;
343 code = VolNukeVolume(acid, apartID, avolID);
344 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
349 VolNukeVolume(acid, apartID, avolID)
350 struct rx_call *acid;
351 afs_int32 apartID, avolID;
356 register afs_int32 code;
358 char caller[MAXKTCNAMELEN];
360 /* check for access */
361 if (!afsconf_SuperUser(tdir, acid, caller))
362 return VOLSERBAD_ACCESS;
364 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
366 tp = volutil_PartitionName(apartID);
369 strcpy(partName, tp); /* remember it for later */
370 /* we first try to attach the volume in update mode, so that the file
371 * server doesn't try to use it (and abort) while (or after) we delete it.
372 * If we don't get the volume, that's fine, too. We just won't put it back.
374 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
375 code = nuke(partName, avolID);
377 VDetachVolume(&error, tvp);
381 /* create a new volume, with name aname, on the specified partition (1..n)
382 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
383 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
384 * for the volume id (useful for things like volume restore).
385 * Return the new volume id in *avolid.
388 SAFSVolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans)
389 struct rx_call *acid;
400 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
401 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
402 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
408 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans)
409 struct rx_call *acid;
419 afs_int32 junk; /* discardable error code */
420 register afs_int32 volumeID, doCreateRoot = 1;
421 register struct volser_trans *tt;
423 char caller[MAXKTCNAMELEN];
425 if (strlen(aname) > 31)
426 return VOLSERBADNAME;
427 if (!afsconf_SuperUser(tdir, acid, caller))
428 return VOLSERBAD_ACCESS;
430 Log("%s is executing CreateVolume '%s'\n", caller, aname);
431 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
432 return error; /*a standard unix error */
433 if (atype != readwriteVolume && atype != readonlyVolume
434 && atype != backupVolume)
436 if ((volumeID = *avolid) == 0) {
438 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
442 if ((aparent == volumeID) && (atype == readwriteVolume)) {
447 tt = NewTrans(volumeID, apart);
449 Log("1 createvolume: failed to create trans\n");
450 return VOLSERVOLBUSY; /* volume already busy! */
452 vp = VCreateVolume(&error, ppath, volumeID, aparent);
454 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
459 V_uniquifier(vp) = 1;
460 V_creationDate(vp) = V_copyDate(vp);
461 V_inService(vp) = V_blessed(vp) = 1;
463 AssignVolumeName(&V_disk(vp), aname, 0);
466 V_destroyMe(vp) = DESTROY_ME;
468 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
469 VUpdateVolume(&error, vp);
471 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
474 VDetachVolume(&junk, vp); /* rather return the real error code */
479 strcpy(tt->lastProcName, "CreateVolume");
480 tt->rxCallPtr = acid;
481 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
482 tt->rxCallPtr = (struct rx_call *)0;
484 return VOLSERTRELE_ERROR;
488 /* delete the volume associated with this transaction */
490 SAFSVolDeleteVolume(acid, atrans)
492 struct rx_call *acid;
496 code = VolDeleteVolume(acid, atrans);
497 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
502 VolDeleteVolume(acid, atrans)
504 struct rx_call *acid;
506 register struct volser_trans *tt;
508 char caller[MAXKTCNAMELEN];
510 if (!afsconf_SuperUser(tdir, acid, caller))
511 return VOLSERBAD_ACCESS;
512 tt = FindTrans(atrans);
515 if (tt->vflags & VTDeleted) {
516 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
521 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
522 strcpy(tt->lastProcName, "DeleteVolume");
523 tt->rxCallPtr = acid;
524 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
525 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
526 tt->rxCallPtr = (struct rx_call *)0;
528 return VOLSERTRELE_ERROR;
530 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
531 return 0; /* vpurgevolume doesn't set an error code */
534 /* make a clone of the volume associated with atrans, possibly giving it a new
535 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
536 * for the clone's id). The new clone is given the name newName. Finally, due to
537 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
538 * the clone operation. This may be useful when making new backup volumes, for instance
539 * since the net result of a clone and a purge generally leaves many inode ref counts
540 * the same, while doing them separately would result in far more iincs and idecs being
541 * peformed (and they are slow operations).
544 SAFSVolClone(acid, atrans, purgeId, newType, newName, newNumber)
545 struct rx_call *acid;
548 afs_int32 *newNumber;
549 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
554 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
555 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
556 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
562 VolClone(acid, atrans, purgeId, newType, newName, newNumber)
563 struct rx_call *acid;
566 afs_int32 *newNumber;
567 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
571 register struct Volume *originalvp, *purgevp, *newvp;
573 register struct volser_trans *tt, *ttc;
574 char caller[MAXKTCNAMELEN];
576 if (strlen(newName) > 31)
577 return VOLSERBADNAME;
578 if (!afsconf_SuperUser(tdir, acid, caller))
579 return VOLSERBAD_ACCESS; /*not a super user */
581 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
583 originalvp = (Volume *) 0;
584 purgevp = (Volume *) 0;
585 newvp = (Volume *) 0;
586 tt = ttc = (struct volser_trans *)0;
588 if (!newNumber || !*newNumber) {
589 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
594 if (newType != readonlyVolume && newType != backupVolume)
596 tt = FindTrans(atrans);
599 if (tt->vflags & VTDeleted) {
600 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
604 ttc = NewTrans(newId, tt->partition);
605 if (!ttc) { /* someone is messing with the clone already */
609 strcpy(tt->lastProcName, "Clone");
610 tt->rxCallPtr = acid;
614 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
616 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
622 originalvp = tt->volume;
623 if ((V_type(originalvp) == backupVolume)
624 || (V_type(originalvp) == readonlyVolume)) {
625 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
629 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
630 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
636 if (originalvp->device != purgevp->device) {
637 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
641 if (V_type(purgevp) != readonlyVolume) {
642 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
646 if (V_type(originalvp) == readonlyVolume
647 && V_parentId(originalvp) != V_parentId(purgevp)) {
648 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
652 if (V_type(originalvp) == readwriteVolume
653 && tt->volid != V_parentId(purgevp)) {
654 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
663 VCreateVolume(&error, originalvp->partition->name, newId,
664 V_parentId(originalvp));
666 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
667 newvp = (Volume *) 0;
670 if (newType == readonlyVolume)
671 V_cloneId(originalvp) = newId;
672 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
675 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
676 CloneVolume(&error, originalvp, newvp, purgevp);
677 purgevp = NULL; /* clone releases it, maybe even if error */
679 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
683 if (newType == readonlyVolume) {
684 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
685 V_type(newvp) = readonlyVolume;
686 } else if (newType == backupVolume) {
687 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
688 V_type(newvp) = backupVolume;
689 V_backupId(originalvp) = newId;
691 strcpy(newvp->header->diskstuff.name, newName);
692 V_creationDate(newvp) = V_copyDate(newvp);
693 ClearVolumeStats(&V_disk(newvp));
694 V_destroyMe(newvp) = DESTROY_ME;
695 V_inService(newvp) = 0;
696 if (newType == backupVolume) {
697 V_backupDate(originalvp) = V_copyDate(newvp);
698 V_backupDate(newvp) = V_copyDate(newvp);
701 VUpdateVolume(&error, newvp);
703 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
707 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
709 VUpdateVolume(&error, originalvp);
711 Log("1 Volser: Clone: original update %u\n", error);
715 tt->rxCallPtr = (struct rx_call *)0;
717 tt = (struct volser_trans *)0;
718 error = VOLSERTRELE_ERROR;
726 VDetachVolume(&code, purgevp);
728 VDetachVolume(&code, newvp);
730 tt->rxCallPtr = (struct rx_call *)0;
738 /* reclone this volume into the specified id */
740 SAFSVolReClone(acid, atrans, cloneId)
741 struct rx_call *acid;
747 code = VolReClone(acid, atrans, cloneId);
748 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
754 VolReClone(acid, atrans, cloneId)
755 struct rx_call *acid;
759 register struct Volume *originalvp, *clonevp;
762 register struct volser_trans *tt, *ttc;
763 char caller[MAXKTCNAMELEN];
765 /*not a super user */
766 if (!afsconf_SuperUser(tdir, acid, caller))
767 return VOLSERBAD_ACCESS;
769 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
771 clonevp = originalvp = (Volume *) 0;
772 tt = (struct volser_trans *)0;
774 tt = FindTrans(atrans);
777 if (tt->vflags & VTDeleted) {
778 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
782 ttc = NewTrans(cloneId, tt->partition);
783 if (!ttc) { /* someone is messing with the clone already */
787 strcpy(tt->lastProcName, "ReClone");
788 tt->rxCallPtr = acid;
790 originalvp = tt->volume;
791 if ((V_type(originalvp) == backupVolume)
792 || (V_type(originalvp) == readonlyVolume)) {
793 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
797 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
798 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
804 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
806 Log("1 Volser: can't attach clone %d\n", cloneId);
810 newType = V_type(clonevp); /* type of the new volume */
812 if (originalvp->device != clonevp->device) {
813 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
818 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
819 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
823 if (V_type(originalvp) == readonlyVolume
824 && V_parentId(originalvp) != V_parentId(clonevp)) {
825 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
829 if (V_type(originalvp) == readwriteVolume
830 && tt->volid != V_parentId(clonevp)) {
831 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
837 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
839 CloneVolume(&error, originalvp, clonevp, clonevp);
841 Log("1 Volser: Clone: reclone operation failed with code %d\n",
847 /* fix up volume name and type, CloneVolume just propagated RW's */
848 if (newType == readonlyVolume) {
849 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
850 V_type(clonevp) = readonlyVolume;
851 } else if (newType == backupVolume) {
852 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
853 V_type(clonevp) = backupVolume;
854 V_backupId(originalvp) = cloneId;
856 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
858 /* pretend recloned volume is a totally new instance */
859 V_copyDate(clonevp) = time(0);
860 V_creationDate(clonevp) = V_copyDate(clonevp);
861 ClearVolumeStats(&V_disk(clonevp));
862 V_destroyMe(clonevp) = 0;
863 V_inService(clonevp) = 0;
864 if (newType == backupVolume) {
865 V_backupDate(originalvp) = V_copyDate(clonevp);
866 V_backupDate(clonevp) = V_copyDate(clonevp);
868 V_inUse(clonevp) = 0;
869 VUpdateVolume(&error, clonevp);
871 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
875 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
877 VUpdateVolume(&error, originalvp);
879 Log("1 Volser: Clone: original update %u\n", error);
883 tt->rxCallPtr = (struct rx_call *)0;
885 tt = (struct volser_trans *)0;
886 error = VOLSERTRELE_ERROR;
893 struct DiskPartition *tpartp = originalvp->partition;
894 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
900 VDetachVolume(&code, clonevp);
902 tt->rxCallPtr = (struct rx_call *)0;
910 /* create a new transaction, associated with volume and partition. Type of
911 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
912 * See volser.h for definition of iflags (the constants are named IT*).
915 SAFSVolTransCreate(acid, volume, partition, iflags, ttid)
916 struct rx_call *acid;
924 code = VolTransCreate(acid, volume, partition, iflags, ttid);
925 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
931 VolTransCreate(acid, volume, partition, iflags, ttid)
932 struct rx_call *acid;
938 register struct volser_trans *tt;
940 afs_int32 error, code;
942 char caller[MAXKTCNAMELEN];
944 if (!afsconf_SuperUser(tdir, acid, caller))
945 return VOLSERBAD_ACCESS; /*not a super user */
946 if (iflags & ITCreate)
948 else if (iflags & ITBusy)
950 else if (iflags & ITReadOnly)
952 else if (iflags & ITOffline)
955 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
960 tt = NewTrans(volume, partition);
962 /* can't create a transaction? put the volume back */
963 Log("1 transcreate: can't create transaction\n");
964 return VOLSERVOLBUSY;
966 tv = XAttachVolume(&error, volume, partition, mode);
970 VDetachVolume(&code, tv);
978 strcpy(tt->lastProcName, "TransCreate");
980 return VOLSERTRELE_ERROR;
985 /* using aindex as a 0-based index, return the aindex'th volume on this server
986 * Both the volume number and partition number (one-based) are returned.
989 SAFSVolGetNthVolume(acid, aindex, avolume, apart)
990 struct rx_call *acid;
997 code = VolGetNthVolume(acid, aindex, avolume, apart);
998 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
1003 VolGetNthVolume(acid, aindex, avolume, apart)
1004 struct rx_call *acid;
1009 Log("1 Volser: GetNthVolume: Not yet implemented\n");
1013 /* return the volume flags (VT* constants in volser.h) associated with this
1017 SAFSVolGetFlags(acid, atid, aflags)
1018 struct rx_call *acid;
1024 code = VolGetFlags(acid, atid, aflags);
1025 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
1030 VolGetFlags(acid, atid, aflags)
1031 struct rx_call *acid;
1035 register struct volser_trans *tt;
1037 tt = FindTrans(atid);
1040 if (tt->vflags & VTDeleted) {
1041 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
1046 strcpy(tt->lastProcName, "GetFlags");
1047 tt->rxCallPtr = acid;
1048 *aflags = tt->vflags;
1049 tt->rxCallPtr = (struct rx_call *)0;
1051 return VOLSERTRELE_ERROR;
1056 /* Change the volume flags (VT* constants in volser.h) associated with this
1057 * transaction. Effects take place immediately on volume, although volume
1058 * remains attached as usual by the transaction.
1061 SAFSVolSetFlags(acid, atid, aflags)
1062 struct rx_call *acid;
1068 code = VolSetFlags(acid, atid, aflags);
1069 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1075 VolSetFlags(acid, atid, aflags)
1076 struct rx_call *acid;
1080 register struct volser_trans *tt;
1081 register struct Volume *vp;
1083 char caller[MAXKTCNAMELEN];
1085 if (!afsconf_SuperUser(tdir, acid, caller))
1086 return VOLSERBAD_ACCESS; /*not a super user */
1087 /* find the trans */
1088 tt = FindTrans(atid);
1091 if (tt->vflags & VTDeleted) {
1092 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1097 strcpy(tt->lastProcName, "SetFlags");
1098 tt->rxCallPtr = acid;
1099 vp = tt->volume; /* pull volume out of transaction */
1101 /* check if we're allowed to make any updates */
1102 if (tt->iflags & ITReadOnly) {
1107 /* handle delete-on-salvage flag */
1108 if (aflags & VTDeleteOnSalvage) {
1109 V_destroyMe(tt->volume) = DESTROY_ME;
1111 V_destroyMe(tt->volume) = 0;
1114 if (aflags & VTOutOfService) {
1115 V_inService(vp) = 0;
1117 V_inService(vp) = 1;
1119 VUpdateVolume(&error, vp);
1120 tt->vflags = aflags;
1121 tt->rxCallPtr = (struct rx_call *)0;
1122 if (TRELE(tt) && !error)
1123 return VOLSERTRELE_ERROR;
1128 /* dumpS the volume associated with a particular transaction from a particular
1129 * date. Send the dump to a different transaction (destTrans) on the server
1130 * specified by the destServer structure.
1133 SAFSVolForward(acid, fromTrans, fromDate, destination, destTrans, cookie)
1134 struct rx_call *acid;
1135 afs_int32 fromTrans;
1137 struct destServer *destination;
1138 struct restoreCookie *cookie;
1139 afs_int32 destTrans;
1144 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1145 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1146 destination->destHost, AUD_LONG, destTrans, AUD_END);
1151 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie)
1152 struct rx_call *acid;
1153 afs_int32 fromTrans;
1155 struct destServer *destination;
1156 struct restoreCookie *cookie;
1157 afs_int32 destTrans;
1159 register struct volser_trans *tt;
1160 register afs_int32 code;
1161 register struct rx_connection *tcon;
1162 struct rx_call *tcall;
1163 register struct Volume *vp;
1164 struct rx_securityClass *securityObject;
1165 afs_int32 securityIndex;
1166 char caller[MAXKTCNAMELEN];
1168 if (!afsconf_SuperUser(tdir, acid, caller))
1169 return VOLSERBAD_ACCESS; /*not a super user */
1170 /* initialize things */
1171 tcon = (struct rx_connection *)0;
1172 tt = (struct volser_trans *)0;
1174 /* find the local transaction */
1175 tt = FindTrans(fromTrans);
1178 if (tt->vflags & VTDeleted) {
1179 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1184 strcpy(tt->lastProcName, "Forward");
1186 /* get auth info for the this connection (uses afs from ticket file) */
1187 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1193 /* make an rpc connection to the other server */
1195 rx_NewConnection(htonl(destination->destHost),
1196 htons(destination->destPort), VOLSERVICE_ID,
1197 securityObject, securityIndex);
1199 tt->rxCallPtr = (struct rx_call *)0;
1203 tcall = rx_NewCall(tcon);
1204 tt->rxCallPtr = tcall;
1205 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1206 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1211 /* these next calls implictly call rx_Write when writing out data */
1212 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1215 EndAFSVolRestore(tcall); /* probably doesn't do much */
1216 tt->rxCallPtr = (struct rx_call *)0;
1217 code = rx_EndCall(tcall, 0);
1218 rx_DestroyConnection(tcon); /* done with the connection */
1223 return VOLSERTRELE_ERROR;
1229 (void)rx_EndCall(tcall, 0);
1230 rx_DestroyConnection(tcon);
1233 tt->rxCallPtr = (struct rx_call *)0;
1239 /* Start a dump and send it to multiple places simultaneously.
1240 * If this returns an error (eg, return ENOENT), it means that
1241 * none of the releases worked. If this returns 0, that means
1242 * that one or more of the releases worked, and the caller has
1243 * to examine the results array to see which one(s).
1244 * This will only do EITHER incremental or full, not both, so it's
1245 * the caller's responsibility to be sure that all the destinations
1246 * need just an incremental (and from the same time), if that's
1250 SAFSVolForwardMultiple(acid, fromTrans, fromDate, destinations, spare, cookie,
1252 struct rx_call *acid;
1253 afs_int32 fromTrans;
1256 manyDests *destinations;
1257 struct restoreCookie *cookie;
1258 manyResults *results;
1260 afs_int32 securityIndex;
1261 struct rx_securityClass *securityObject;
1262 char caller[MAXKTCNAMELEN];
1263 struct volser_trans *tt;
1264 afs_int32 ec, code, *codes;
1265 struct rx_connection **tcons;
1266 struct rx_call **tcalls;
1268 int i, nconns, is_incremental;
1271 memset(results, 0, sizeof(manyResults));
1273 if (!afsconf_SuperUser(tdir, acid, caller))
1274 return VOLSERBAD_ACCESS; /*not a super user */
1275 tt = FindTrans(fromTrans);
1278 if (tt->vflags & VTDeleted) {
1279 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1284 strcpy(tt->lastProcName, "ForwardMulti");
1286 /* (fromDate == 0) ==> incremental dump */
1287 is_incremental = (fromDate ? 1 : 0);
1289 i = results->manyResults_len = destinations->manyDests_len;
1290 results->manyResults_val = codes =
1291 (afs_int32 *) malloc(i * sizeof(afs_int32));
1293 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1294 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1296 /* get auth info for this connection (uses afs from ticket file) */
1297 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1299 goto fail; /* in order to audit each failure */
1302 /* make connections to all the other servers */
1303 for (i = 0; i < destinations->manyDests_len; i++) {
1304 struct replica *dest = &(destinations->manyDests_val[i]);
1306 rx_NewConnection(htonl(dest->server.destHost),
1307 htons(dest->server.destPort), VOLSERVICE_ID,
1308 securityObject, securityIndex);
1310 codes[i] = ENOTCONN;
1312 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1313 codes[i] = ENOTCONN;
1316 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1319 (void)rx_EndCall(tcalls[i], 0);
1321 rx_DestroyConnection(tcons[i]);
1328 /* these next calls implictly call rx_Write when writing out data */
1329 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1333 for (i--; i >= 0; i--) {
1334 struct replica *dest = &(destinations->manyDests_val[i]);
1336 if (!code && tcalls[i] && !codes[i]) {
1337 EndAFSVolRestore(tcalls[i]);
1340 ec = rx_EndCall(tcalls[i], 0);
1345 rx_DestroyConnection(tcons[i]); /* done with the connection */
1348 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1349 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1350 dest->trans, AUD_END);
1356 tt->rxCallPtr = (struct rx_call *)0;
1357 if (TRELE(tt) && !code) /* return the first code if it's set */
1358 return VOLSERTRELE_ERROR;
1365 SAFSVolDump(acid, fromTrans, fromDate)
1366 struct rx_call *acid;
1367 afs_int32 fromTrans;
1372 code = VolDump(acid, fromTrans, fromDate);
1373 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1378 VolDump(acid, fromTrans, fromDate)
1379 struct rx_call *acid;
1380 afs_int32 fromTrans;
1384 register struct volser_trans *tt;
1385 char caller[MAXKTCNAMELEN];
1387 if (!afsconf_SuperUser(tdir, acid, caller))
1388 return VOLSERBAD_ACCESS; /*not a super user */
1389 tt = FindTrans(fromTrans);
1392 if (tt->vflags & VTDeleted) {
1393 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1397 strcpy(tt->lastProcName, "Dump");
1398 tt->rxCallPtr = acid;
1399 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1401 tt->rxCallPtr = (struct rx_call *)0;
1405 tt->rxCallPtr = (struct rx_call *)0;
1408 return VOLSERTRELE_ERROR;
1414 * Ha! No more helper process!
1417 SAFSVolRestore(acid, atrans, aflags, cookie)
1418 struct rx_call *acid;
1421 struct restoreCookie *cookie;
1425 code = VolRestore(acid, atrans, aflags, cookie);
1426 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1431 VolRestore(acid, atrans, aflags, cookie)
1432 struct rx_call *acid;
1435 struct restoreCookie *cookie;
1437 register struct volser_trans *tt;
1438 register afs_int32 code, tcode;
1439 char caller[MAXKTCNAMELEN];
1441 if (!afsconf_SuperUser(tdir, acid, caller))
1442 return VOLSERBAD_ACCESS; /*not a super user */
1443 tt = FindTrans(atrans);
1446 if (tt->vflags & VTDeleted) {
1447 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1451 strcpy(tt->lastProcName, "Restore");
1452 tt->rxCallPtr = acid;
1454 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1456 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1457 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l); /*break call backs on the
1458 * restored volume */
1459 tt->rxCallPtr = (struct rx_call *)0;
1462 return (code ? code : tcode);
1465 /* end a transaction, returning the transaction's final error code in rcode */
1467 SAFSVolEndTrans(acid, destTrans, rcode)
1468 struct rx_call *acid;
1469 afs_int32 destTrans;
1474 code = VolEndTrans(acid, destTrans, rcode);
1475 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1480 VolEndTrans(acid, destTrans, rcode)
1481 struct rx_call *acid;
1482 afs_int32 destTrans;
1485 register struct volser_trans *tt;
1486 char caller[MAXKTCNAMELEN];
1488 if (!afsconf_SuperUser(tdir, acid, caller))
1489 return VOLSERBAD_ACCESS; /*not a super user */
1490 tt = FindTrans(destTrans);
1494 *rcode = tt->returnCode;
1495 DeleteTrans(tt); /* this does an implicit TRELE */
1501 SAFSVolSetForwarding(acid, atid, anewsite)
1502 struct rx_call *acid;
1508 code = VolSetForwarding(acid, atid, anewsite);
1509 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1515 VolSetForwarding(acid, atid, anewsite)
1516 struct rx_call *acid;
1521 register struct volser_trans *tt;
1522 char caller[MAXKTCNAMELEN];
1524 if (!afsconf_SuperUser(tdir, acid, caller))
1525 return VOLSERBAD_ACCESS; /*not a super user */
1526 tt = FindTrans(atid);
1529 if (tt->vflags & VTDeleted) {
1530 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1535 strcpy(tt->lastProcName, "SetForwarding");
1536 tt->rxCallPtr = acid;
1537 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1538 tt->rxCallPtr = (struct rx_call *)0;
1540 return VOLSERTRELE_ERROR;
1546 SAFSVolGetStatus(acid, atrans, astatus)
1547 struct rx_call *acid;
1549 register struct volser_status *astatus;
1553 code = VolGetStatus(acid, atrans, astatus);
1554 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1559 VolGetStatus(acid, atrans, astatus)
1560 struct rx_call *acid;
1562 register struct volser_status *astatus;
1564 register struct Volume *tv;
1565 register struct VolumeDiskData *td;
1566 struct volser_trans *tt;
1569 tt = FindTrans(atrans);
1572 if (tt->vflags & VTDeleted) {
1573 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1578 strcpy(tt->lastProcName, "GetStatus");
1579 tt->rxCallPtr = acid;
1582 tt->rxCallPtr = (struct rx_call *)0;
1587 td = &tv->header->diskstuff;
1588 astatus->volID = td->id;
1589 astatus->nextUnique = td->uniquifier;
1590 astatus->type = td->type;
1591 astatus->parentID = td->parentId;
1592 astatus->cloneID = td->cloneId;
1593 astatus->backupID = td->backupId;
1594 astatus->restoredFromID = td->restoredFromId;
1595 astatus->maxQuota = td->maxquota;
1596 astatus->minQuota = td->minquota;
1597 astatus->owner = td->owner;
1598 astatus->creationDate = td->creationDate;
1599 astatus->accessDate = td->accessDate;
1600 astatus->updateDate = td->updateDate;
1601 astatus->expirationDate = td->expirationDate;
1602 astatus->backupDate = td->backupDate;
1603 astatus->copyDate = td->copyDate;
1604 tt->rxCallPtr = (struct rx_call *)0;
1606 return VOLSERTRELE_ERROR;
1612 SAFSVolSetInfo(acid, atrans, astatus)
1613 struct rx_call *acid;
1615 register struct volintInfo *astatus;
1619 code = VolSetInfo(acid, atrans, astatus);
1620 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1625 VolSetInfo(acid, atrans, astatus)
1626 struct rx_call *acid;
1628 register struct volintInfo *astatus;
1630 register struct Volume *tv;
1631 register struct VolumeDiskData *td;
1632 struct volser_trans *tt;
1633 char caller[MAXKTCNAMELEN];
1636 if (!afsconf_SuperUser(tdir, acid, caller))
1637 return VOLSERBAD_ACCESS; /*not a super user */
1638 tt = FindTrans(atrans);
1641 if (tt->vflags & VTDeleted) {
1642 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1646 strcpy(tt->lastProcName, "SetStatus");
1647 tt->rxCallPtr = acid;
1650 tt->rxCallPtr = (struct rx_call *)0;
1655 td = &tv->header->diskstuff;
1657 * Add more fields as necessary
1659 if (astatus->maxquota != -1)
1660 td->maxquota = astatus->maxquota;
1661 if (astatus->dayUse != -1)
1662 td->dayUse = astatus->dayUse;
1663 VUpdateVolume(&error, tv);
1664 tt->rxCallPtr = (struct rx_call *)0;
1666 return VOLSERTRELE_ERROR;
1672 SAFSVolGetName(acid, atrans, aname)
1673 struct rx_call *acid;
1679 code = VolGetName(acid, atrans, aname);
1680 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1685 VolGetName(acid, atrans, aname)
1686 struct rx_call *acid;
1690 register struct Volume *tv;
1691 register struct VolumeDiskData *td;
1692 struct volser_trans *tt;
1696 tt = FindTrans(atrans);
1699 if (tt->vflags & VTDeleted) {
1700 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1704 strcpy(tt->lastProcName, "GetName");
1705 tt->rxCallPtr = acid;
1708 tt->rxCallPtr = (struct rx_call *)0;
1713 td = &tv->header->diskstuff;
1714 len = strlen(td->name) + 1; /* don't forget the null */
1716 tt->rxCallPtr = (struct rx_call *)0;
1720 *aname = (char *)malloc(len);
1721 strcpy(*aname, td->name);
1722 tt->rxCallPtr = (struct rx_call *)0;
1724 return VOLSERTRELE_ERROR;
1729 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1732 SAFSVolSignalRestore(acid, volname, volType, parentId, cloneId)
1733 struct rx_call *acid;
1735 afs_int32 parentId, cloneId;
1742 /*return a list of all partitions on the server. The non mounted
1743 *partitions are returned as -1 in the corresponding slot in partIds*/
1745 SAFSVolListPartitions(acid, partIds)
1746 struct rx_call *acid;
1747 struct pIDs *partIds;
1751 code = VolListPartitions(acid, partIds);
1752 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1757 VolListPartitions(acid, partIds)
1758 struct rx_call *acid;
1759 struct pIDs *partIds;
1765 strcpy(namehead, "/vicep"); /*7 including null terminator */
1767 /* Just return attached partitions. */
1769 for (i = 0; i < 26; i++) {
1770 namehead[6] = i + 'a';
1771 if (VGetPartition(namehead, 0))
1772 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1778 /*return a list of all partitions on the server. The non mounted
1779 *partitions are returned as -1 in the corresponding slot in partIds*/
1781 SAFSVolXListPartitions(acid, pEntries)
1782 struct rx_call *acid;
1783 struct partEntries *pEntries;
1787 code = XVolListPartitions(acid, pEntries);
1788 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1793 XVolListPartitions(acid, pEntries)
1794 struct rx_call *acid;
1795 struct partEntries *pEntries;
1797 struct stat rbuf, pbuf;
1799 struct partList partList;
1800 struct DiskPartition *dp;
1803 strcpy(namehead, "/vicep"); /*7 including null terminator */
1805 /* Only report attached partitions */
1806 for (i = 0; i < VOLMAXPARTS; i++) {
1808 namehead[6] = i + 'a';
1812 namehead[6] = 'a' + (k / 26);
1813 namehead[7] = 'a' + (k % 26);
1816 dp = VGetPartition(namehead, 0);
1818 partList.partId[j++] = i;
1820 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1821 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1823 pEntries->partEntries_len = j;
1828 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1834 char name[VOLSER_MAXVOLNAME + 1];
1836 strcpy(name, vname);
1838 while (name[i] == 'V' || name[i] == '0')
1841 name[11] = '\0'; /* smash the "." */
1842 return (atol(&name[i]));
1845 /*return the name of the next volume header in the directory associated with dirp and dp.
1846 *the volume id is returned in volid, and volume header name is returned in volname*/
1847 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1851 dp = readdir(dirp); /*read next entry in the directory */
1854 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1855 *volid = ExtractVolId(dp->d_name);
1856 strcpy(volname, dp->d_name);
1857 return 0; /*return the name of the file representing a volume */
1859 strcpy(volname, "");
1860 return 0; /*volname doesnot represent a volume */
1863 strcpy(volname, "EOD");
1864 return 0; /*end of directory */
1869 /*return the header information about the <volid> */
1871 SAFSVolListOneVolume(acid, partid, volumeId, volumeInfo)
1872 struct rx_call *acid;
1873 afs_int32 volumeId, partid;
1874 volEntries *volumeInfo;
1878 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
1879 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1884 VolListOneVolume(acid, partid, volumeId, volumeInfo)
1885 struct rx_call *acid;
1886 afs_int32 volumeId, partid;
1887 volEntries *volumeInfo;
1890 register struct Volume *tv;
1891 struct DiskPartition *partP;
1892 struct volser_trans *ttc;
1893 char pname[9], volname[20];
1894 afs_int32 error = 0;
1900 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
1901 pntr = volumeInfo->volEntries_val;
1902 volumeInfo->volEntries_len = 1;
1903 if (GetPartName(partid, pname))
1904 return VOLSERILLEGAL_PARTITION;
1905 if (!(partP = VGetPartition(pname, 0)))
1906 return VOLSERILLEGAL_PARTITION;
1907 dirp = opendir(VPartitionPath(partP));
1909 return VOLSERILLEGAL_PARTITION;
1910 strcpy(volname, "");
1911 ttc = (struct volser_trans *)0;
1912 tv = (Volume *) 0; /* volume not attached */
1914 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
1916 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
1917 GetNextVol(dirp, volname, &volid);
1918 continue; /*back to while loop */
1921 if (volid == volumeId) { /*copy other things too */
1923 #ifndef AFS_PTHREAD_ENV
1924 IOMGR_Poll(); /*make sure that the client doesnot time out */
1926 ttc = NewTrans(volid, partid);
1928 pntr->status = VBUSY;
1929 pntr->volid = volid;
1932 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1934 pntr->status = 0; /*things are messed up */
1935 strcpy(pntr->name, volname);
1936 pntr->volid = volid;
1937 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
1940 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1941 /*this volume will be salvaged */
1943 strcpy(pntr->name, volname);
1944 pntr->volid = volid;
1945 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
1949 if (tv->header->diskstuff.needsSalvaged) {
1950 /*this volume will be salvaged */
1952 strcpy(pntr->name, volname);
1953 pntr->volid = volid;
1954 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
1958 /*read in the relevant info */
1959 pntr->status = VOK; /*its ok */
1960 pntr->volid = tv->header->diskstuff.id;
1961 strcpy(pntr->name, tv->header->diskstuff.name);
1962 pntr->type = tv->header->diskstuff.type; /*if ro volume */
1963 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
1964 pntr->backupID = tv->header->diskstuff.backupId;
1965 pntr->parentID = tv->header->diskstuff.parentId;
1966 pntr->copyDate = tv->header->diskstuff.copyDate;
1967 pntr->inUse = tv->header->diskstuff.inUse;
1968 pntr->size = tv->header->diskstuff.diskused;
1969 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1970 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1971 pntr->maxquota = tv->header->diskstuff.maxquota;
1972 pntr->filecount = tv->header->diskstuff.filecount;
1973 now = FT_ApproxTime();
1974 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1977 pntr->dayUse = tv->header->diskstuff.dayUse;
1978 pntr->creationDate = tv->header->diskstuff.creationDate;
1979 pntr->accessDate = tv->header->diskstuff.accessDate;
1980 pntr->updateDate = tv->header->diskstuff.updateDate;
1981 pntr->backupDate = tv->header->diskstuff.backupDate;
1982 pntr->spare0 = tv->header->diskstuff.minquota;
1984 (long)tv->header->diskstuff.weekUse[0] +
1985 (long)tv->header->diskstuff.weekUse[1] +
1986 (long)tv->header->diskstuff.weekUse[2] +
1987 (long)tv->header->diskstuff.weekUse[3] +
1988 (long)tv->header->diskstuff.weekUse[4] +
1989 (long)tv->header->diskstuff.weekUse[5] +
1990 (long)tv->header->diskstuff.weekUse[6];
1991 pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
1992 VDetachVolume(&error, tv); /*free the volume */
1995 pntr->status = 0; /*things are messed up */
1996 strcpy(pntr->name, volname);
1997 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2002 GetNextVol(dirp, volname, &volid);
2006 VDetachVolume(&error, tv);
2011 ttc = (struct volser_trans *)0;
2021 /*------------------------------------------------------------------------
2022 * EXPORTED SAFSVolXListOneVolume
2025 * Returns extended info on volume a_volID on partition a_partID.
2028 * a_rxCidP : Pointer to the Rx call we're performing.
2029 * a_partID : Partition for which we want the extended list.
2030 * a_volID : Volume ID we wish to know about.
2031 * a_volumeXInfoP : Ptr to the extended info blob.
2034 * 0 Successful operation
2035 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2038 * Nothing interesting.
2042 *------------------------------------------------------------------------*/
2045 SAFSVolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
2046 struct rx_call *a_rxCidP;
2049 volXEntries *a_volumeXInfoP;
2053 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2054 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2059 VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
2060 struct rx_call *a_rxCidP;
2063 volXEntries *a_volumeXInfoP;
2065 { /*SAFSVolXListOneVolume */
2067 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2068 register struct Volume *tv; /*Volume ptr */
2069 struct volser_trans *ttc; /*Volume transaction ptr */
2070 struct DiskPartition *partP; /*Ptr to partition */
2071 char pname[9], volname[20]; /*Partition, volume names */
2072 afs_int32 error; /*Error code */
2073 afs_int32 code; /*Return code */
2074 DIR *dirp; /*Partition directory ptr */
2075 afs_int32 currVolID; /*Current volume ID */
2076 int found = 0; /*Did we find the volume we need? */
2077 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2078 int numStatBytes; /*Num stat bytes to copy per volume */
2082 * Set up our pointers for action, marking our structure to hold exactly
2083 * one entry. Also, assume we'll fail in our quest.
2085 a_volumeXInfoP->volXEntries_val =
2086 (volintXInfo *) malloc(sizeof(volintXInfo));
2087 xInfoP = a_volumeXInfoP->volXEntries_val;
2088 a_volumeXInfoP->volXEntries_len = 1;
2092 * If the partition name we've been given is bad, bogue out.
2094 if (GetPartName(a_partID, pname))
2095 return (VOLSERILLEGAL_PARTITION);
2098 * Open the directory representing the given AFS parttion. If we can't
2101 if (!(partP = VGetPartition(pname, 0)))
2102 return VOLSERILLEGAL_PARTITION;
2103 dirp = opendir(VPartitionPath(partP));
2105 return (VOLSERILLEGAL_PARTITION);
2108 * Sweep through the partition directory, looking for the desired entry.
2109 * First, of course, figure out how many stat bytes to copy out of each
2113 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2114 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2115 strcpy(volname, "");
2116 ttc = (struct volser_trans *)0; /*No transaction yet */
2117 tv = (Volume *) 0; /*Volume not yet attached */
2119 while (strcmp(volname, "EOD") && !found) {
2121 * If this is not a volume, move on to the next entry in the
2122 * partition's directory.
2124 if (!strcmp(volname, "")) {
2125 GetNextVol(dirp, volname, &currVolID);
2129 if (currVolID == a_volID) {
2131 * We found the volume entry we're interested. Pull out the
2132 * extended information, remembering to poll (so that the client
2133 * doesn't time out) and to set up a transaction on the volume.
2136 #ifndef AFS_PTHREAD_ENV
2139 ttc = NewTrans(currVolID, a_partID);
2142 * Couldn't get a transaction on this volume; let our caller
2145 xInfoP->status = VBUSY;
2146 xInfoP->volid = currVolID;
2151 * Attach the volume, give up on the volume if we can't.
2153 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2155 xInfoP->status = 0; /*things are messed up */
2156 strcpy(xInfoP->name, volname);
2157 xInfoP->volid = currVolID;
2158 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
2164 * Also bag out on this volume if it's been marked as needing a
2165 * salvage or to-be-destroyed.
2167 volDiskDataP = &(tv->header->diskstuff);
2168 if (volDiskDataP->destroyMe == DESTROY_ME) {
2170 strcpy(xInfoP->name, volname);
2171 xInfoP->volid = currVolID;
2172 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2176 if (volDiskDataP->needsSalvaged) {
2178 strcpy(xInfoP->name, volname);
2179 xInfoP->volid = currVolID;
2180 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
2185 * Pull out the desired info and stuff it into the area we'll be
2186 * returning to our caller.
2188 strcpy(xInfoP->name, volDiskDataP->name);
2189 xInfoP->volid = volDiskDataP->id;
2190 xInfoP->type = volDiskDataP->type;
2191 xInfoP->backupID = volDiskDataP->backupId;
2192 xInfoP->parentID = volDiskDataP->parentId;
2193 xInfoP->cloneID = volDiskDataP->cloneId;
2194 xInfoP->status = VOK;
2195 xInfoP->copyDate = volDiskDataP->copyDate;
2196 xInfoP->inUse = volDiskDataP->inUse;
2197 xInfoP->creationDate = volDiskDataP->creationDate;
2198 xInfoP->accessDate = volDiskDataP->accessDate;
2199 xInfoP->updateDate = volDiskDataP->updateDate;
2200 xInfoP->backupDate = volDiskDataP->backupDate;
2201 now = FT_ApproxTime();
2202 if (now - volDiskDataP->dayUseDate > OneDay)
2205 xInfoP->dayUse = volDiskDataP->dayUse;
2206 xInfoP->filecount = volDiskDataP->filecount;
2207 xInfoP->maxquota = volDiskDataP->maxquota;
2208 xInfoP->size = volDiskDataP->diskused;
2211 * Copy out the stat fields in a single operation.
2213 memcpy((char *)&(xInfoP->stat_reads[0]),
2214 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2217 * We're done copying. Detach the volume and iterate (at this
2218 * point, since we found our volume, we'll then drop out of the
2221 VDetachVolume(&error, tv);
2225 strcpy(xInfoP->name, volname);
2226 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2232 * At this point, we're golden.
2235 } /*Found desired volume */
2236 GetNextVol(dirp, volname, &currVolID);
2240 * Drop the transaction we have for this volume.
2244 VDetachVolume(&error, tv);
2249 ttc = (struct volser_trans *)0;
2253 * Clean up before going to dinner: close the partition directory,
2254 * return the proper value.
2259 } /*SAFSVolXListOneVolume */
2261 /*returns all the volumes on partition partid. If flags = 1 then all the
2262 * relevant info about the volumes is also returned */
2264 SAFSVolListVolumes(acid, partid, flags, volumeInfo)
2265 struct rx_call *acid;
2266 afs_int32 flags, partid;
2267 volEntries *volumeInfo;
2271 code = VolListVolumes(acid, partid, flags, volumeInfo);
2272 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2277 VolListVolumes(acid, partid, flags, volumeInfo)
2278 struct rx_call *acid;
2279 afs_int32 flags, partid;
2280 volEntries *volumeInfo;
2283 register struct Volume *tv;
2284 struct DiskPartition *partP;
2285 struct volser_trans *ttc;
2286 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2287 char pname[9], volname[20];
2288 afs_int32 error = 0;
2293 volumeInfo->volEntries_val =
2294 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2295 pntr = volumeInfo->volEntries_val;
2296 volumeInfo->volEntries_len = 0;
2297 if (GetPartName(partid, pname))
2298 return VOLSERILLEGAL_PARTITION;
2299 if (!(partP = VGetPartition(pname, 0)))
2300 return VOLSERILLEGAL_PARTITION;
2301 dirp = opendir(VPartitionPath(partP));
2303 return VOLSERILLEGAL_PARTITION;
2304 strcpy(volname, "");
2305 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2306 ttc = (struct volser_trans *)0; /* new one for each pass */
2307 tv = (Volume *) 0; /* volume not attached */
2309 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2310 GetNextVol(dirp, volname, &volid);
2311 continue; /*back to while loop */
2314 if (flags) { /*copy other things too */
2315 #ifndef AFS_PTHREAD_ENV
2316 IOMGR_Poll(); /*make sure that the client doesnot time out */
2318 ttc = NewTrans(volid, partid);
2320 pntr->status = VBUSY;
2321 pntr->volid = volid;
2324 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2326 pntr->status = 0; /*things are messed up */
2327 strcpy(pntr->name, volname);
2328 pntr->volid = volid;
2329 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
2332 if (tv->header->diskstuff.needsSalvaged) {
2333 /*this volume will be salvaged */
2335 strcpy(pntr->name, volname);
2336 pntr->volid = volid;
2337 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
2341 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2342 /*this volume will be salvaged */
2345 /*read in the relevant info */
2346 pntr->status = VOK; /*its ok */
2347 pntr->volid = tv->header->diskstuff.id;
2348 strcpy(pntr->name, tv->header->diskstuff.name);
2349 pntr->type = tv->header->diskstuff.type; /*if ro volume */
2350 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
2351 pntr->backupID = tv->header->diskstuff.backupId;
2352 pntr->parentID = tv->header->diskstuff.parentId;
2353 pntr->copyDate = tv->header->diskstuff.copyDate;
2354 pntr->inUse = tv->header->diskstuff.inUse;
2355 pntr->size = tv->header->diskstuff.diskused;
2356 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2357 pntr->maxquota = tv->header->diskstuff.maxquota;
2358 pntr->filecount = tv->header->diskstuff.filecount;
2359 now = FT_ApproxTime();
2360 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2363 pntr->dayUse = tv->header->diskstuff.dayUse;
2364 pntr->creationDate = tv->header->diskstuff.creationDate;
2365 pntr->accessDate = tv->header->diskstuff.accessDate;
2366 pntr->updateDate = tv->header->diskstuff.updateDate;
2367 pntr->backupDate = tv->header->diskstuff.backupDate;
2368 pntr->spare0 = tv->header->diskstuff.minquota;
2370 (long)tv->header->diskstuff.weekUse[0] +
2371 (long)tv->header->diskstuff.weekUse[1] +
2372 (long)tv->header->diskstuff.weekUse[2] +
2373 (long)tv->header->diskstuff.weekUse[3] +
2374 (long)tv->header->diskstuff.weekUse[4] +
2375 (long)tv->header->diskstuff.weekUse[5] +
2376 (long)tv->header->diskstuff.weekUse[6];
2377 pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
2378 VDetachVolume(&error, tv); /*free the volume */
2381 pntr->status = 0; /*things are messed up */
2382 strcpy(pntr->name, volname);
2383 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2388 pntr->volid = volid;
2389 /*just volids are needed */
2395 ttc = (struct volser_trans *)0;
2398 volumeInfo->volEntries_len += 1;
2399 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2400 /*running out of space, allocate more space */
2401 allocSize = (allocSize * 3) / 2;
2403 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2404 allocSize * sizeof(volintInfo));
2407 VDetachVolume(&error, tv);
2412 ttc = (struct volser_trans *)0;
2415 return VOLSERNO_MEMORY;
2417 volumeInfo->volEntries_val = pntr; /* point to new block */
2418 /* set pntr to the right position */
2419 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2425 VDetachVolume(&error, tv);
2430 ttc = (struct volser_trans *)0;
2432 GetNextVol(dirp, volname, &volid);
2442 /*------------------------------------------------------------------------
2443 * EXPORTED SAFSVolXListVolumes
2446 * Returns all the volumes on partition a_partID. If a_flags
2447 * is set to 1, then all the relevant extended volume information
2451 * a_rxCidP : Pointer to the Rx call we're performing.
2452 * a_partID : Partition for which we want the extended list.
2453 * a_flags : Various flags.
2454 * a_volumeXInfoP : Ptr to the extended info blob.
2457 * 0 Successful operation
2458 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2459 * VOLSERNO_MEMORY if we ran out of memory allocating
2463 * Nothing interesting.
2467 *------------------------------------------------------------------------*/
2470 SAFSVolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2471 struct rx_call *a_rxCidP;
2474 volXEntries *a_volumeXInfoP;
2478 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2479 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2484 VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2485 struct rx_call *a_rxCidP;
2488 volXEntries *a_volumeXInfoP;
2490 { /*SAFSVolXListVolumes */
2492 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2493 register struct Volume *tv; /*Volume ptr */
2494 struct DiskPartition *partP; /*Ptr to partition */
2495 struct volser_trans *ttc; /*Volume transaction ptr */
2496 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2497 char pname[9], volname[20]; /*Partition, volume names */
2498 afs_int32 error = 0; /*Return code */
2499 DIR *dirp; /*Partition directory ptr */
2500 afs_int32 volid; /*Current volume ID */
2501 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2502 int numStatBytes; /*Num stat bytes to copy per volume */
2506 * Allocate a large array of extended volume info structures, then
2507 * set it up for action.
2509 a_volumeXInfoP->volXEntries_val =
2510 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2511 xInfoP = a_volumeXInfoP->volXEntries_val;
2512 a_volumeXInfoP->volXEntries_len = 0;
2515 * If the partition name we've been given is bad, bogue out.
2517 if (GetPartName(a_partID, pname))
2518 return (VOLSERILLEGAL_PARTITION);
2521 * Open the directory representing the given AFS parttion. If we can't
2524 if (!(partP = VGetPartition(pname, 0)))
2525 return VOLSERILLEGAL_PARTITION;
2526 dirp = opendir(VPartitionPath(partP));
2528 return (VOLSERILLEGAL_PARTITION);
2531 * Sweep through the partition directory, acting on each entry. First,
2532 * of course, figure out how many stat bytes to copy out of each volume.
2535 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2536 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2537 strcpy(volname, "");
2538 while (strcmp(volname, "EOD")) {
2539 ttc = (struct volser_trans *)0; /*New one for each pass */
2540 tv = (Volume *) 0; /*Volume not yet attached */
2543 * If this is not a volume, move on to the next entry in the
2544 * partition's directory.
2546 if (!strcmp(volname, "")) {
2547 GetNextVol(dirp, volname, &volid);
2553 * Full info about the volume desired. Poll to make sure the
2554 * client doesn't time out, then start up a new transaction.
2556 #ifndef AFS_PTHREAD_ENV
2559 ttc = NewTrans(volid, a_partID);
2562 * Couldn't get a transaction on this volume; let our caller
2565 xInfoP->status = VBUSY;
2566 xInfoP->volid = volid;
2571 * Attach the volume, give up on this volume if we can't.
2573 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2575 xInfoP->status = 0; /*things are messed up */
2576 strcpy(xInfoP->name, volname);
2577 xInfoP->volid = volid;
2578 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2584 * Also bag out on this volume if it's been marked as needing a
2585 * salvage or to-be-destroyed.
2587 volDiskDataP = &(tv->header->diskstuff);
2588 if (volDiskDataP->needsSalvaged) {
2590 strcpy(xInfoP->name, volname);
2591 xInfoP->volid = volid;
2592 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
2596 if (volDiskDataP->destroyMe == DESTROY_ME)
2600 * Pull out the desired info and stuff it into the area we'll be
2601 * returning to our caller.
2603 strcpy(xInfoP->name, volDiskDataP->name);
2604 xInfoP->volid = volDiskDataP->id;
2605 xInfoP->type = volDiskDataP->type;
2606 xInfoP->backupID = volDiskDataP->backupId;
2607 xInfoP->parentID = volDiskDataP->parentId;
2608 xInfoP->cloneID = volDiskDataP->cloneId;
2609 xInfoP->status = VOK;
2610 xInfoP->copyDate = volDiskDataP->copyDate;
2611 xInfoP->inUse = volDiskDataP->inUse;
2612 xInfoP->creationDate = volDiskDataP->creationDate;
2613 xInfoP->accessDate = volDiskDataP->accessDate;
2614 xInfoP->updateDate = volDiskDataP->updateDate;
2615 xInfoP->backupDate = volDiskDataP->backupDate;
2616 now = FT_ApproxTime();
2617 if (now - volDiskDataP->dayUseDate > OneDay)
2620 xInfoP->dayUse = volDiskDataP->dayUse;
2621 xInfoP->filecount = volDiskDataP->filecount;
2622 xInfoP->maxquota = volDiskDataP->maxquota;
2623 xInfoP->size = volDiskDataP->diskused;
2626 * Copy out the stat fields in a single operation.
2628 memcpy((char *)&(xInfoP->stat_reads[0]),
2629 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2632 * We're done copying. Detach the volume and iterate.
2634 VDetachVolume(&error, tv);
2638 strcpy(xInfoP->name, volname);
2639 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2643 } /*Full contents desired */
2646 * Just volume IDs are needed.
2648 xInfoP->volid = volid;
2652 * Drop the transaction we have for this volume.
2656 ttc = (struct volser_trans *)0;
2660 * Bump the pointer in the data area we're building, along with
2661 * the count of the number of entries it contains.
2664 (a_volumeXInfoP->volXEntries_len)++;
2665 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2667 * We're running out of space in the area we've built. Grow it.
2669 allocSize = (allocSize * 3) / 2;
2670 xInfoP = (volintXInfo *)
2671 realloc((char *)a_volumeXInfoP->volXEntries_val,
2672 (allocSize * sizeof(volintXInfo)));
2673 if (xInfoP == NULL) {
2675 * Bummer, no memory. Bag it, tell our caller what went wrong.
2678 VDetachVolume(&error, tv);
2683 ttc = (struct volser_trans *)0;
2686 return (VOLSERNO_MEMORY);
2690 * Memory reallocation worked. Correct our pointers so they
2691 * now point to the new block and the current open position within
2694 a_volumeXInfoP->volXEntries_val = xInfoP;
2696 a_volumeXInfoP->volXEntries_val +
2697 a_volumeXInfoP->volXEntries_len;
2699 /*Need more space */
2702 * Detach our current volume and the transaction on it, then move on
2703 * to the next volume in the partition directory.
2706 VDetachVolume(&error, tv);
2711 ttc = (struct volser_trans *)0;
2713 GetNextVol(dirp, volname, &volid);
2714 } /*Sweep through the partition directory */
2717 * We've examined all entries in the partition directory. Close it,
2718 * delete our transaction (if any), and go home happy.
2725 } /*SAFSVolXListVolumes */
2727 /*this call is used to monitor the status of volser for debugging purposes.
2728 *information about all the active transactions is returned in transInfo*/
2730 SAFSVolMonitor(acid, transInfo)
2731 struct rx_call *acid;
2732 transDebugEntries *transInfo;
2736 code = VolMonitor(acid, transInfo);
2737 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2742 VolMonitor(acid, transInfo)
2743 struct rx_call *acid;
2744 transDebugEntries *transInfo;
2746 transDebugInfo *pntr;
2747 afs_int32 allocSize = 50;
2748 struct volser_trans *tt, *allTrans;
2750 transInfo->transDebugEntries_val =
2751 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2752 pntr = transInfo->transDebugEntries_val;
2753 transInfo->transDebugEntries_len = 0;
2754 allTrans = TransList();
2755 if (allTrans == (struct volser_trans *)0)
2756 return 0; /*no active transactions */
2757 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2758 pntr->tid = tt->tid;
2759 pntr->time = tt->time;
2760 pntr->creationTime = tt->creationTime;
2761 pntr->returnCode = tt->returnCode;
2762 pntr->volid = tt->volid;
2763 pntr->partition = tt->partition;
2764 pntr->iflags = tt->iflags;
2765 pntr->vflags = tt->vflags;
2766 pntr->tflags = tt->tflags;
2767 strcpy(pntr->lastProcName, tt->lastProcName);
2768 pntr->callValid = 0;
2769 if (tt->rxCallPtr) { /*record call related info */
2770 pntr->callValid = 1;
2771 pntr->readNext = tt->rxCallPtr->rnext;
2772 pntr->transmitNext = tt->rxCallPtr->tnext;
2773 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2774 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2777 transInfo->transDebugEntries_len += 1;
2778 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2779 allocSize = (allocSize * 3) / 2;
2781 (transDebugInfo *) realloc((char *)transInfo->
2782 transDebugEntries_val,
2784 sizeof(transDebugInfo));
2785 transInfo->transDebugEntries_val = pntr;
2787 transInfo->transDebugEntries_val +
2788 transInfo->transDebugEntries_len;
2789 /*set pntr to right position */
2798 SAFSVolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId)
2799 struct rx_call *acid;
2800 afs_int32 type, pId, cloneId, backupId, atid;
2805 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2806 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2807 AUD_STR, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2813 VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId)
2814 struct rx_call *acid;
2815 afs_int32 type, pId, cloneId, backupId, atid;
2819 afs_int32 error = 0;
2820 register struct volser_trans *tt;
2821 char caller[MAXKTCNAMELEN];
2823 if (strlen(name) > 31)
2824 return VOLSERBADNAME;
2825 if (!afsconf_SuperUser(tdir, acid, caller))
2826 return VOLSERBAD_ACCESS; /*not a super user */
2827 /* find the trans */
2828 tt = FindTrans(atid);
2831 if (tt->vflags & VTDeleted) {
2832 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2836 strcpy(tt->lastProcName, "SetIdsTypes");
2837 tt->rxCallPtr = acid;
2841 V_backupId(tv) = backupId;
2842 V_cloneId(tv) = cloneId;
2843 V_parentId(tv) = pId;
2844 strcpy((&V_disk(tv))->name, name);
2845 VUpdateVolume(&error, tv);
2847 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2851 tt->rxCallPtr = (struct rx_call *)0;
2852 if (TRELE(tt) && !error)
2853 return VOLSERTRELE_ERROR;
2857 tt->rxCallPtr = (struct rx_call *)0;
2858 if (TRELE(tt) && !error)
2859 return VOLSERTRELE_ERROR;
2864 SAFSVolSetDate(acid, atid, cdate)
2865 struct rx_call *acid;
2866 afs_int32 atid, cdate;
2870 code = VolSetDate(acid, atid, cdate);
2871 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2877 VolSetDate(acid, atid, cdate)
2878 struct rx_call *acid;
2879 afs_int32 atid, cdate;
2882 afs_int32 error = 0;
2883 register struct volser_trans *tt;
2884 char caller[MAXKTCNAMELEN];
2886 if (!afsconf_SuperUser(tdir, acid, caller))
2887 return VOLSERBAD_ACCESS; /*not a super user */
2888 /* find the trans */
2889 tt = FindTrans(atid);
2892 if (tt->vflags & VTDeleted) {
2893 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2897 strcpy(tt->lastProcName, "SetDate");
2898 tt->rxCallPtr = acid;
2901 V_creationDate(tv) = cdate;
2902 VUpdateVolume(&error, tv);
2904 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2908 tt->rxCallPtr = (struct rx_call *)0;
2909 if (TRELE(tt) && !error)
2910 return VOLSERTRELE_ERROR;
2914 tt->rxCallPtr = (struct rx_call *)0;
2915 if (TRELE(tt) && !error)
2916 return VOLSERTRELE_ERROR;
2920 #ifdef AFS_NAMEI_ENV
2922 * Inode number format (from namei_ops.c):
2923 * low 26 bits - vnode number - all 1's if volume special file.
2925 * next 3 bits spare (0's)
2926 * high 32 bits - uniquifier (regular) or type if spare
2928 #define NAMEI_VNODEMASK 0x003ffffff
2929 #define NAMEI_TAGMASK 0x7
2930 #define NAMEI_TAGSHIFT 26
2931 #define NAMEI_UNIQMASK 0xffffffff
2932 #define NAMEI_UNIQSHIFT 32
2933 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2934 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2935 #endif /* AFS_NAMEI_ENV */
2938 SAFSVolConvertROtoRWvolume(acid, partId, volumeId)
2939 struct rx_call *acid;
2943 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2947 afs_int32 error = 0;
2950 char caller[MAXKTCNAMELEN];
2951 char headername[16];
2954 struct VolumeDiskHeader h;
2958 struct DiskPartition *dp;
2960 if (!afsconf_SuperUser(tdir, acid, caller))
2961 return VOLSERBAD_ACCESS; /*not a super user */
2962 if (GetPartName(partId, pname))
2963 return VOLSERILLEGAL_PARTITION;
2964 dirp = opendir(pname);
2966 return VOLSERILLEGAL_PARTITION;
2967 strcpy(volname, "");
2969 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2970 GetNextVol(dirp, volname, &volid);
2971 if (strcmp(volname, "")) { /* its a volume */
2972 if (volid == volumeId)
2978 (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
2979 (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
2980 fd = open(opath, O_RDONLY);
2982 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2985 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2986 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2991 FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
2993 for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
2996 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2999 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
3000 IH_INIT(ih, dp->device, h.parent, ino);
3002 error = namei_ConvertROtoRWvolume(ih, volumeId);
3006 h.volumeInfo_hi = h.id;
3007 h.smallVnodeIndex_hi = h.id;
3008 h.largeVnodeIndex_hi = h.id;
3009 h.linkTable_hi = h.id;
3010 (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
3011 (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
3012 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
3014 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
3017 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
3018 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
3023 if (unlink(opath) < 0) {
3024 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
3026 FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
3027 FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
3029 #else /* AFS_NAMEI_ENV */
3031 #endif /* AFS_NAMEI_ENV */
3035 SAFSVolGetSize(acid, fromTrans, fromDate, size)
3036 struct rx_call *acid;
3037 afs_int32 fromTrans;
3039 register struct volintSize *size;
3042 register struct volser_trans *tt;
3043 char caller[MAXKTCNAMELEN];
3045 if (!afsconf_SuperUser(tdir, acid, caller))
3046 return VOLSERBAD_ACCESS; /*not a super user */
3047 tt = FindTrans(fromTrans);
3050 if (tt->vflags & VTDeleted) {
3054 strcpy(tt->lastProcName, "GetSize");
3055 tt->rxCallPtr = acid;
3056 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
3057 tt->rxCallPtr = (struct rx_call *)0;
3059 return VOLSERTRELE_ERROR;
3061 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
3065 /* GetPartName - map partid (a decimal number) into pname (a string)
3066 * Since for NT we actually want to return the drive name, we map through the
3070 GetPartName(afs_int32 partid, char *pname)
3075 strcpy(pname, "/vicep");
3076 pname[6] = 'a' + partid;
3079 } else if (partid < VOLMAXPARTS) {
3080 strcpy(pname, "/vicep");
3082 pname[6] = 'a' + (partid / 26);
3083 pname[7] = 'a' + (partid % 26);