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>
25 #include <netinet/in.h>
34 #include <afs/afsint.h>
36 #ifdef AFS_PTHREAD_ENV
38 #else /* AFS_PTHREAD_ENV */
39 #include <afs/assert.h>
40 #endif /* AFS_PTHREAD_ENV */
41 #include <afs/prs_fs.h>
45 #include <afs/cellconfig.h>
48 #include <afs/ihandle.h>
50 #include <afs/ntops.h>
52 #include <afs/vnode.h>
53 #include <afs/volume.h>
54 #include <afs/partition.h>
56 #include <afs/daemon_com.h>
57 #include <afs/fssync.h>
59 #include "afs/audit.h"
65 #include "volser_prototypes.h"
68 extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
69 extern struct afsconf_dir *tdir;
71 /* Needed by Irix. Leave, or include a header */
72 extern char *volutil_PartitionName();
74 extern void LogError(afs_int32 errcode);
76 /* Forward declarations */
77 static int GetPartName(afs_int32 partid, char *pname);
79 #define OneDay (24*60*60)
85 afs_int32 localTid = 1;
86 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
87 VolDeleteVolume(), VolClone();
88 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
89 VolForward(), VolDump();
90 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
91 VolSetInfo(), VolGetName();
92 afs_int32 VolListPartitions(), VolListOneVolume(),
93 VolXListOneVolume(), VolXListVolumes();
94 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
95 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
97 /* this call unlocks all of the partition locks we've set */
101 register struct DiskPartition *tp;
102 for (tp = DiskPartitionList; tp; tp = tp->next) {
103 if (tp->lock_fd != -1) {
104 close(tp->lock_fd); /* releases flock held on this partition */
111 /* get partition id from a name */
113 PartitionID(char *aname)
116 register int code = 0;
121 return -1; /* unknown */
123 /* otherwise check for vicepa or /vicepa, or just plain "a" */
125 if (!strncmp(aname, "/vicep", 6)) {
126 strncpy(ascii, aname + 6, 2);
128 return -1; /* bad partition name */
129 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
130 * from 0. Do the appropriate conversion */
132 /* one char name, 0..25 */
133 if (ascii[0] < 'a' || ascii[0] > 'z')
134 return -1; /* wrongo */
135 return ascii[0] - 'a';
137 /* two char name, 26 .. <whatever> */
138 if (ascii[0] < 'a' || ascii[0] > 'z')
139 return -1; /* wrongo */
140 if (ascii[1] < 'a' || ascii[1] > 'z')
141 return -1; /* just as bad */
142 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
143 if (code > VOLMAXPARTS)
150 ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
154 /* 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 */
155 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
160 ConvertPartition(int apartno, char *aname, int asize)
166 strcpy(aname, "/vicep");
168 aname[6] = 'a' + apartno;
172 aname[6] = 'a' + (apartno / 26);
173 aname[7] = 'a' + (apartno % 26);
179 /* the only attach function that takes a partition is "...ByName", so we use it */
181 XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
183 char pbuf[30], vbuf[20];
184 register struct Volume *tv;
186 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
190 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
194 tv = VAttachVolumeByName((Error *)error, pbuf, vbuf, amode);
198 /* Adapted from the file server; create a root directory for this volume */
200 ViceCreateRoot(Volume *vp)
203 struct acl_accessList *ACL;
205 Inode inodeNumber, nearInode;
206 char buf[SIZEOF_LARGEDISKVNODE];
207 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
208 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
214 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
216 V_pref(vp, nearInode);
218 IH_CREATE(V_linkHandle(vp), V_device(vp),
219 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
221 assert(VALID_INO(inodeNumber));
223 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
224 did.Volume = V_id(vp);
225 did.Vnode = (VnodeId) 1;
228 assert(!(MakeDir(&dir, &did, &did)));
229 DFlush(); /* flush all modified dir buffers out */
230 DZap(&dir); /* Remove all buffers for this dir */
231 length = Length(&dir); /* Remember size of this directory */
233 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
235 /* build a single entry ACL that gives all rights to system:administrators */
236 /* this section of code assumes that access list format is not going to
239 ACL = VVnodeDiskACL(vnode);
240 ACL->size = sizeof(struct acl_accessList);
241 ACL->version = ACL_ACLVERSION;
245 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
246 ACL->entries[0].rights =
247 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
248 | PRSFS_LOCK | PRSFS_ADMINISTER;
250 vnode->type = vDirectory;
252 vnode->modeBits = 0777;
253 vnode->linkCount = 2;
254 VNDISK_SET_LEN(vnode, length);
255 vnode->uniquifier = 1;
256 V_uniquifier(vp) = vnode->uniquifier + 1;
257 vnode->dataVersion = 1;
258 VNDISK_SET_INO(vnode, inodeNumber);
259 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
263 vnode->vnodeMagic = vcp->magic;
265 IH_INIT(h, vp->device, V_parentId(vp),
266 vp->vnodeIndex[vLarge].handle->ih_ino);
269 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
271 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
272 assert(code == SIZEOF_LARGEDISKVNODE);
273 FDH_REALLYCLOSE(fdP);
275 VNDISK_GET_LEN(length, vnode);
276 V_diskused(vp) = nBlocks(length);
282 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
287 code = VolPartitionInfo(acid, pname, partition);
288 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
293 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
296 register struct DiskPartition *dp;
299 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
302 dp = VGetPartition(pname, 0);
304 strncpy(partition->name, dp->name, 32);
305 strncpy(partition->devName, dp->devName, 32);
306 partition->lock_fd = dp->lock_fd;
307 partition->free = dp->free;
308 partition->minFree = dp->totalUsable;
311 return VOLSERILLEGAL_PARTITION;
314 /* obliterate a volume completely, and slowly. */
316 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
320 code = VolNukeVolume(acid, apartID, avolID);
321 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
326 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
331 register afs_int32 code;
333 char caller[MAXKTCNAMELEN];
335 /* check for access */
336 if (!afsconf_SuperUser(tdir, acid, caller))
337 return VOLSERBAD_ACCESS;
339 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
341 tp = volutil_PartitionName(apartID);
344 strcpy(partName, tp); /* remember it for later */
345 /* we first try to attach the volume in update mode, so that the file
346 * server doesn't try to use it (and abort) while (or after) we delete it.
347 * If we don't get the volume, that's fine, too. We just won't put it back.
349 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
350 code = nuke(partName, avolID);
352 VDetachVolume(&error, tvp);
356 /* create a new volume, with name aname, on the specified partition (1..n)
357 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
358 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
359 * for the volume id (useful for things like volume restore).
360 * Return the new volume id in *avolid.
363 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
364 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
370 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
371 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
372 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
378 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
379 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
384 afs_int32 junk; /* discardable error code */
385 register afs_int32 volumeID, doCreateRoot = 1;
386 register struct volser_trans *tt;
388 char caller[MAXKTCNAMELEN];
390 if (strlen(aname) > 31)
391 return VOLSERBADNAME;
392 if (!afsconf_SuperUser(tdir, acid, caller))
393 return VOLSERBAD_ACCESS;
395 Log("%s is executing CreateVolume '%s'\n", caller, aname);
396 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
397 return error; /*a standard unix error */
398 if (atype != readwriteVolume && atype != readonlyVolume
399 && atype != backupVolume)
401 if ((volumeID = *avolid) == 0) {
403 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
407 if ((aparent == volumeID) && (atype == readwriteVolume)) {
412 tt = NewTrans(volumeID, apart);
414 Log("1 createvolume: failed to create trans\n");
415 return VOLSERVOLBUSY; /* volume already busy! */
417 vp = VCreateVolume(&error, ppath, volumeID, aparent);
419 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
424 V_uniquifier(vp) = 1;
425 V_creationDate(vp) = V_copyDate(vp);
426 V_inService(vp) = V_blessed(vp) = 1;
428 AssignVolumeName(&V_disk(vp), aname, 0);
431 V_destroyMe(vp) = DESTROY_ME;
433 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
434 VUpdateVolume(&error, vp);
436 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
439 VDetachVolume(&junk, vp); /* rather return the real error code */
444 strcpy(tt->lastProcName, "CreateVolume");
445 tt->rxCallPtr = acid;
446 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
447 tt->rxCallPtr = (struct rx_call *)0;
449 return VOLSERTRELE_ERROR;
453 /* delete the volume associated with this transaction */
455 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
459 code = VolDeleteVolume(acid, atrans);
460 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
465 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
467 register struct volser_trans *tt;
469 char caller[MAXKTCNAMELEN];
471 if (!afsconf_SuperUser(tdir, acid, caller))
472 return VOLSERBAD_ACCESS;
473 tt = FindTrans(atrans);
476 if (tt->vflags & VTDeleted) {
477 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
482 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
483 strcpy(tt->lastProcName, "DeleteVolume");
484 tt->rxCallPtr = acid;
485 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
486 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
487 tt->rxCallPtr = (struct rx_call *)0;
489 return VOLSERTRELE_ERROR;
491 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
492 return 0; /* vpurgevolume doesn't set an error code */
495 /* make a clone of the volume associated with atrans, possibly giving it a new
496 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
497 * for the clone's id). The new clone is given the name newName. Finally, due to
498 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
499 * the clone operation. This may be useful when making new backup volumes, for instance
500 * since the net result of a clone and a purge generally leaves many inode ref counts
501 * the same, while doing them separately would result in far more iincs and idecs being
502 * peformed (and they are slow operations).
504 /* for efficiency reasons, sometimes faster to piggyback a purge here */
506 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
507 afs_int32 newType, char *newName, afs_int32 *newNumber)
511 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
512 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
513 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
519 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
520 afs_int32 newType, char *newName, afs_int32 *newNumber)
523 register struct Volume *originalvp, *purgevp, *newvp;
525 register struct volser_trans *tt, *ttc;
526 char caller[MAXKTCNAMELEN];
528 if (strlen(newName) > 31)
529 return VOLSERBADNAME;
530 if (!afsconf_SuperUser(tdir, acid, caller))
531 return VOLSERBAD_ACCESS; /*not a super user */
533 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
535 originalvp = (Volume *) 0;
536 purgevp = (Volume *) 0;
537 newvp = (Volume *) 0;
538 tt = ttc = (struct volser_trans *)0;
540 if (!newNumber || !*newNumber) {
541 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
546 if (newType != readonlyVolume && newType != backupVolume)
548 tt = FindTrans(atrans);
551 if (tt->vflags & VTDeleted) {
552 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
556 ttc = NewTrans(newId, tt->partition);
557 if (!ttc) { /* someone is messing with the clone already */
561 strcpy(tt->lastProcName, "Clone");
562 tt->rxCallPtr = acid;
566 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
568 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
574 originalvp = tt->volume;
575 if ((V_type(originalvp) == backupVolume)
576 || (V_type(originalvp) == readonlyVolume)) {
577 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
581 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
582 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
588 if (originalvp->device != purgevp->device) {
589 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
593 if (V_type(purgevp) != readonlyVolume) {
594 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
598 if (V_type(originalvp) == readonlyVolume
599 && V_parentId(originalvp) != V_parentId(purgevp)) {
600 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
604 if (V_type(originalvp) == readwriteVolume
605 && tt->volid != V_parentId(purgevp)) {
606 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
615 VCreateVolume(&error, originalvp->partition->name, newId,
616 V_parentId(originalvp));
618 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
619 newvp = (Volume *) 0;
622 if (newType == readonlyVolume)
623 V_cloneId(originalvp) = newId;
624 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
627 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
628 CloneVolume(&error, originalvp, newvp, purgevp);
629 purgevp = NULL; /* clone releases it, maybe even if error */
631 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
635 if (newType == readonlyVolume) {
636 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
637 V_type(newvp) = readonlyVolume;
638 } else if (newType == backupVolume) {
639 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
640 V_type(newvp) = backupVolume;
641 V_backupId(originalvp) = newId;
643 strcpy(newvp->header->diskstuff.name, newName);
644 V_creationDate(newvp) = V_copyDate(newvp);
645 ClearVolumeStats(&V_disk(newvp));
646 V_destroyMe(newvp) = DESTROY_ME;
647 V_inService(newvp) = 0;
648 if (newType == backupVolume) {
649 V_backupDate(originalvp) = V_copyDate(newvp);
650 V_backupDate(newvp) = V_copyDate(newvp);
653 VUpdateVolume(&error, newvp);
655 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
659 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
661 VUpdateVolume(&error, originalvp);
663 Log("1 Volser: Clone: original update %u\n", error);
667 tt->rxCallPtr = (struct rx_call *)0;
669 tt = (struct volser_trans *)0;
670 error = VOLSERTRELE_ERROR;
678 VDetachVolume(&code, purgevp);
680 VDetachVolume(&code, newvp);
682 tt->rxCallPtr = (struct rx_call *)0;
690 /* reclone this volume into the specified id */
692 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
696 code = VolReClone(acid, atrans, cloneId);
697 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
703 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
705 register struct Volume *originalvp, *clonevp;
708 register struct volser_trans *tt, *ttc;
709 char caller[MAXKTCNAMELEN];
711 /*not a super user */
712 if (!afsconf_SuperUser(tdir, acid, caller))
713 return VOLSERBAD_ACCESS;
715 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
717 clonevp = originalvp = (Volume *) 0;
718 tt = (struct volser_trans *)0;
720 tt = FindTrans(atrans);
723 if (tt->vflags & VTDeleted) {
724 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
728 ttc = NewTrans(cloneId, tt->partition);
729 if (!ttc) { /* someone is messing with the clone already */
733 strcpy(tt->lastProcName, "ReClone");
734 tt->rxCallPtr = acid;
736 originalvp = tt->volume;
737 if ((V_type(originalvp) == backupVolume)
738 || (V_type(originalvp) == readonlyVolume)) {
739 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
743 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
744 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
750 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
752 Log("1 Volser: can't attach clone %d\n", cloneId);
756 newType = V_type(clonevp); /* type of the new volume */
758 if (originalvp->device != clonevp->device) {
759 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
764 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
765 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
769 if (V_type(originalvp) == readonlyVolume
770 && V_parentId(originalvp) != V_parentId(clonevp)) {
771 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
775 if (V_type(originalvp) == readwriteVolume
776 && tt->volid != V_parentId(clonevp)) {
777 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
783 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
785 CloneVolume(&error, originalvp, clonevp, clonevp);
787 Log("1 Volser: Clone: reclone operation failed with code %d\n",
793 /* fix up volume name and type, CloneVolume just propagated RW's */
794 if (newType == readonlyVolume) {
795 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
796 V_type(clonevp) = readonlyVolume;
797 } else if (newType == backupVolume) {
798 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
799 V_type(clonevp) = backupVolume;
800 V_backupId(originalvp) = cloneId;
802 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
804 /* pretend recloned volume is a totally new instance */
805 V_copyDate(clonevp) = time(0);
806 V_creationDate(clonevp) = V_copyDate(clonevp);
807 ClearVolumeStats(&V_disk(clonevp));
808 V_destroyMe(clonevp) = 0;
809 V_inService(clonevp) = 0;
810 if (newType == backupVolume) {
811 V_backupDate(originalvp) = V_copyDate(clonevp);
812 V_backupDate(clonevp) = V_copyDate(clonevp);
814 V_inUse(clonevp) = 0;
815 VUpdateVolume(&error, clonevp);
817 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
821 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
823 VUpdateVolume(&error, originalvp);
825 Log("1 Volser: Clone: original update %u\n", error);
829 tt->rxCallPtr = (struct rx_call *)0;
831 tt = (struct volser_trans *)0;
832 error = VOLSERTRELE_ERROR;
839 struct DiskPartition *tpartp = originalvp->partition;
840 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
846 VDetachVolume(&code, clonevp);
848 tt->rxCallPtr = (struct rx_call *)0;
856 /* create a new transaction, associated with volume and partition. Type of
857 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
858 * See volser.h for definition of iflags (the constants are named IT*).
861 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
862 afs_int32 iflags, afs_int32 *ttid)
866 code = VolTransCreate(acid, volume, partition, iflags, ttid);
867 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
873 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
874 afs_int32 iflags, afs_int32 *ttid)
876 register struct volser_trans *tt;
878 afs_int32 error, code;
880 char caller[MAXKTCNAMELEN];
882 if (!afsconf_SuperUser(tdir, acid, caller))
883 return VOLSERBAD_ACCESS; /*not a super user */
884 if (iflags & ITCreate)
886 else if (iflags & ITBusy)
888 else if (iflags & ITReadOnly)
890 else if (iflags & ITOffline)
893 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
898 tt = NewTrans(volume, partition);
900 /* can't create a transaction? put the volume back */
901 Log("1 transcreate: can't create transaction\n");
902 return VOLSERVOLBUSY;
904 tv = XAttachVolume(&error, volume, partition, mode);
908 VDetachVolume(&code, tv);
916 strcpy(tt->lastProcName, "TransCreate");
918 return VOLSERTRELE_ERROR;
923 /* using aindex as a 0-based index, return the aindex'th volume on this server
924 * Both the volume number and partition number (one-based) are returned.
927 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
932 code = VolGetNthVolume(acid, aindex, avolume, apart);
933 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
938 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
941 Log("1 Volser: GetNthVolume: Not yet implemented\n");
945 /* return the volume flags (VT* constants in volser.h) associated with this
949 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
953 code = VolGetFlags(acid, atid, aflags);
954 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
959 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
961 register struct volser_trans *tt;
963 tt = FindTrans(atid);
966 if (tt->vflags & VTDeleted) {
967 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
972 strcpy(tt->lastProcName, "GetFlags");
973 tt->rxCallPtr = acid;
974 *aflags = tt->vflags;
975 tt->rxCallPtr = (struct rx_call *)0;
977 return VOLSERTRELE_ERROR;
982 /* Change the volume flags (VT* constants in volser.h) associated with this
983 * transaction. Effects take place immediately on volume, although volume
984 * remains attached as usual by the transaction.
987 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
991 code = VolSetFlags(acid, atid, aflags);
992 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
998 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1000 register struct volser_trans *tt;
1001 register struct Volume *vp;
1003 char caller[MAXKTCNAMELEN];
1005 if (!afsconf_SuperUser(tdir, acid, caller))
1006 return VOLSERBAD_ACCESS; /*not a super user */
1007 /* find the trans */
1008 tt = FindTrans(atid);
1011 if (tt->vflags & VTDeleted) {
1012 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1017 strcpy(tt->lastProcName, "SetFlags");
1018 tt->rxCallPtr = acid;
1019 vp = tt->volume; /* pull volume out of transaction */
1021 /* check if we're allowed to make any updates */
1022 if (tt->iflags & ITReadOnly) {
1027 /* handle delete-on-salvage flag */
1028 if (aflags & VTDeleteOnSalvage) {
1029 V_destroyMe(tt->volume) = DESTROY_ME;
1031 V_destroyMe(tt->volume) = 0;
1034 if (aflags & VTOutOfService) {
1035 V_inService(vp) = 0;
1037 V_inService(vp) = 1;
1039 VUpdateVolume(&error, vp);
1040 tt->vflags = aflags;
1041 tt->rxCallPtr = (struct rx_call *)0;
1042 if (TRELE(tt) && !error)
1043 return VOLSERTRELE_ERROR;
1048 /* dumpS the volume associated with a particular transaction from a particular
1049 * date. Send the dump to a different transaction (destTrans) on the server
1050 * specified by the destServer structure.
1053 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1054 struct destServer *destination, afs_int32 destTrans,
1055 struct restoreCookie *cookie)
1060 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1061 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1062 destination->destHost, AUD_LONG, destTrans, AUD_END);
1067 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1068 struct destServer *destination, afs_int32 destTrans,
1069 struct restoreCookie *cookie)
1071 register struct volser_trans *tt;
1072 register afs_int32 code;
1073 register struct rx_connection *tcon;
1074 struct rx_call *tcall;
1075 register struct Volume *vp;
1076 struct rx_securityClass *securityObject;
1077 afs_int32 securityIndex;
1078 char caller[MAXKTCNAMELEN];
1080 if (!afsconf_SuperUser(tdir, acid, caller))
1081 return VOLSERBAD_ACCESS; /*not a super user */
1082 /* initialize things */
1083 tcon = (struct rx_connection *)0;
1084 tt = (struct volser_trans *)0;
1086 /* find the local transaction */
1087 tt = FindTrans(fromTrans);
1090 if (tt->vflags & VTDeleted) {
1091 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1096 strcpy(tt->lastProcName, "Forward");
1098 /* get auth info for the this connection (uses afs from ticket file) */
1099 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1105 /* make an rpc connection to the other server */
1107 rx_NewConnection(htonl(destination->destHost),
1108 htons(destination->destPort), VOLSERVICE_ID,
1109 securityObject, securityIndex);
1111 tt->rxCallPtr = (struct rx_call *)0;
1115 tcall = rx_NewCall(tcon);
1116 tt->rxCallPtr = tcall;
1117 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1118 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1123 /* these next calls implictly call rx_Write when writing out data */
1124 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1127 EndAFSVolRestore(tcall); /* probably doesn't do much */
1128 tt->rxCallPtr = (struct rx_call *)0;
1129 code = rx_EndCall(tcall, 0);
1130 rx_DestroyConnection(tcon); /* done with the connection */
1135 return VOLSERTRELE_ERROR;
1141 (void)rx_EndCall(tcall, 0);
1142 rx_DestroyConnection(tcon);
1145 tt->rxCallPtr = (struct rx_call *)0;
1151 /* Start a dump and send it to multiple places simultaneously.
1152 * If this returns an error (eg, return ENOENT), it means that
1153 * none of the releases worked. If this returns 0, that means
1154 * that one or more of the releases worked, and the caller has
1155 * to examine the results array to see which one(s).
1156 * This will only do EITHER incremental or full, not both, so it's
1157 * the caller's responsibility to be sure that all the destinations
1158 * need just an incremental (and from the same time), if that's
1162 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1163 fromDate, manyDests *destinations, afs_int32 spare,
1164 struct restoreCookie *cookie, manyResults *results)
1166 afs_int32 securityIndex;
1167 struct rx_securityClass *securityObject;
1168 char caller[MAXKTCNAMELEN];
1169 struct volser_trans *tt;
1170 afs_int32 ec, code, *codes;
1171 struct rx_connection **tcons;
1172 struct rx_call **tcalls;
1174 int i, is_incremental;
1177 memset(results, 0, sizeof(manyResults));
1179 if (!afsconf_SuperUser(tdir, acid, caller))
1180 return VOLSERBAD_ACCESS; /*not a super user */
1181 tt = FindTrans(fromTrans);
1184 if (tt->vflags & VTDeleted) {
1185 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1190 strcpy(tt->lastProcName, "ForwardMulti");
1192 /* (fromDate == 0) ==> full dump */
1193 is_incremental = (fromDate ? 1 : 0);
1195 i = results->manyResults_len = destinations->manyDests_len;
1196 results->manyResults_val = codes =
1197 (afs_int32 *) malloc(i * sizeof(afs_int32));
1199 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1200 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1202 /* get auth info for this connection (uses afs from ticket file) */
1203 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1205 goto fail; /* in order to audit each failure */
1208 /* make connections to all the other servers */
1209 for (i = 0; i < destinations->manyDests_len; i++) {
1210 struct replica *dest = &(destinations->manyDests_val[i]);
1212 rx_NewConnection(htonl(dest->server.destHost),
1213 htons(dest->server.destPort), VOLSERVICE_ID,
1214 securityObject, securityIndex);
1216 codes[i] = ENOTCONN;
1218 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1219 codes[i] = ENOTCONN;
1222 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1225 (void)rx_EndCall(tcalls[i], 0);
1227 rx_DestroyConnection(tcons[i]);
1234 /* these next calls implictly call rx_Write when writing out data */
1235 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1239 for (i--; i >= 0; i--) {
1240 struct replica *dest = &(destinations->manyDests_val[i]);
1242 if (!code && tcalls[i] && !codes[i]) {
1243 EndAFSVolRestore(tcalls[i]);
1246 ec = rx_EndCall(tcalls[i], 0);
1251 rx_DestroyConnection(tcons[i]); /* done with the connection */
1254 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1255 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1256 dest->trans, AUD_END);
1262 tt->rxCallPtr = (struct rx_call *)0;
1263 if (TRELE(tt) && !code) /* return the first code if it's set */
1264 return VOLSERTRELE_ERROR;
1271 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1275 code = VolDump(acid, fromTrans, fromDate, 0);
1276 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1281 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1285 code = VolDump(acid, fromTrans, fromDate, flags);
1286 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1291 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1294 register struct volser_trans *tt;
1295 char caller[MAXKTCNAMELEN];
1297 if (!afsconf_SuperUser(tdir, acid, caller))
1298 return VOLSERBAD_ACCESS; /*not a super user */
1299 tt = FindTrans(fromTrans);
1302 if (tt->vflags & VTDeleted) {
1303 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1307 strcpy(tt->lastProcName, "Dump");
1308 tt->rxCallPtr = acid;
1309 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1310 ? 0 : 1); /* squirt out the volume's data, too */
1312 tt->rxCallPtr = (struct rx_call *)0;
1316 tt->rxCallPtr = (struct rx_call *)0;
1319 return VOLSERTRELE_ERROR;
1325 * Ha! No more helper process!
1328 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1329 struct restoreCookie *cookie)
1333 code = VolRestore(acid, atrans, aflags, cookie);
1334 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1339 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1340 struct restoreCookie *cookie)
1342 register struct volser_trans *tt;
1343 register afs_int32 code, tcode;
1344 char caller[MAXKTCNAMELEN];
1346 if (!afsconf_SuperUser(tdir, acid, caller))
1347 return VOLSERBAD_ACCESS; /*not a super user */
1348 tt = FindTrans(atrans);
1351 if (tt->vflags & VTDeleted) {
1352 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1356 strcpy(tt->lastProcName, "Restore");
1357 tt->rxCallPtr = acid;
1359 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1361 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1362 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1363 tt->rxCallPtr = (struct rx_call *)0;
1366 return (code ? code : tcode);
1369 /* end a transaction, returning the transaction's final error code in rcode */
1371 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1375 code = VolEndTrans(acid, destTrans, rcode);
1376 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1381 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1383 register struct volser_trans *tt;
1384 char caller[MAXKTCNAMELEN];
1386 if (!afsconf_SuperUser(tdir, acid, caller))
1387 return VOLSERBAD_ACCESS; /*not a super user */
1388 tt = FindTrans(destTrans);
1392 *rcode = tt->returnCode;
1393 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1399 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1403 code = VolSetForwarding(acid, atid, anewsite);
1404 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1410 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1412 register struct volser_trans *tt;
1413 char caller[MAXKTCNAMELEN];
1415 if (!afsconf_SuperUser(tdir, acid, caller))
1416 return VOLSERBAD_ACCESS; /*not a super user */
1417 tt = FindTrans(atid);
1420 if (tt->vflags & VTDeleted) {
1421 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1426 strcpy(tt->lastProcName, "SetForwarding");
1427 tt->rxCallPtr = acid;
1428 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
1429 tt->rxCallPtr = (struct rx_call *)0;
1431 return VOLSERTRELE_ERROR;
1437 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1438 register struct volser_status *astatus)
1442 code = VolGetStatus(acid, atrans, astatus);
1443 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1448 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1449 register struct volser_status *astatus)
1451 register struct Volume *tv;
1452 register struct VolumeDiskData *td;
1453 struct volser_trans *tt;
1456 tt = FindTrans(atrans);
1459 if (tt->vflags & VTDeleted) {
1460 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1465 strcpy(tt->lastProcName, "GetStatus");
1466 tt->rxCallPtr = acid;
1469 tt->rxCallPtr = (struct rx_call *)0;
1474 td = &tv->header->diskstuff;
1475 astatus->volID = td->id;
1476 astatus->nextUnique = td->uniquifier;
1477 astatus->type = td->type;
1478 astatus->parentID = td->parentId;
1479 astatus->cloneID = td->cloneId;
1480 astatus->backupID = td->backupId;
1481 astatus->restoredFromID = td->restoredFromId;
1482 astatus->maxQuota = td->maxquota;
1483 astatus->minQuota = td->minquota;
1484 astatus->owner = td->owner;
1485 astatus->creationDate = td->creationDate;
1486 astatus->accessDate = td->accessDate;
1487 astatus->updateDate = td->updateDate;
1488 astatus->expirationDate = td->expirationDate;
1489 astatus->backupDate = td->backupDate;
1490 astatus->copyDate = td->copyDate;
1491 tt->rxCallPtr = (struct rx_call *)0;
1493 return VOLSERTRELE_ERROR;
1499 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1500 register struct volintInfo *astatus)
1504 code = VolSetInfo(acid, atrans, astatus);
1505 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1510 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1511 register struct volintInfo *astatus)
1513 register struct Volume *tv;
1514 register struct VolumeDiskData *td;
1515 struct volser_trans *tt;
1516 char caller[MAXKTCNAMELEN];
1519 if (!afsconf_SuperUser(tdir, acid, caller))
1520 return VOLSERBAD_ACCESS; /*not a super user */
1521 tt = FindTrans(atrans);
1524 if (tt->vflags & VTDeleted) {
1525 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1529 strcpy(tt->lastProcName, "SetStatus");
1530 tt->rxCallPtr = acid;
1533 tt->rxCallPtr = (struct rx_call *)0;
1538 td = &tv->header->diskstuff;
1540 * Add more fields as necessary
1542 if (astatus->maxquota != -1)
1543 td->maxquota = astatus->maxquota;
1544 if (astatus->dayUse != -1)
1545 td->dayUse = astatus->dayUse;
1546 if (astatus->creationDate != -1)
1547 td->creationDate = astatus->creationDate;
1548 if (astatus->updateDate != -1)
1549 td->updateDate = astatus->updateDate;
1550 if (astatus->spare2 != -1)
1551 td->volUpdateCounter = (unsigned int)astatus->spare2;
1552 VUpdateVolume(&error, tv);
1553 tt->rxCallPtr = (struct rx_call *)0;
1555 return VOLSERTRELE_ERROR;
1561 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1565 code = VolGetName(acid, atrans, aname);
1566 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1571 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1573 register struct Volume *tv;
1574 register struct VolumeDiskData *td;
1575 struct volser_trans *tt;
1579 tt = FindTrans(atrans);
1582 if (tt->vflags & VTDeleted) {
1583 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1587 strcpy(tt->lastProcName, "GetName");
1588 tt->rxCallPtr = acid;
1591 tt->rxCallPtr = (struct rx_call *)0;
1596 td = &tv->header->diskstuff;
1597 len = strlen(td->name) + 1; /* don't forget the null */
1599 tt->rxCallPtr = (struct rx_call *)0;
1603 *aname = (char *)malloc(len);
1604 strcpy(*aname, td->name);
1605 tt->rxCallPtr = (struct rx_call *)0;
1607 return VOLSERTRELE_ERROR;
1612 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1615 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1616 afs_int32 parentId, afs_int32 cloneId)
1622 /*return a list of all partitions on the server. The non mounted
1623 *partitions are returned as -1 in the corresponding slot in partIds*/
1625 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1629 code = VolListPartitions(acid, partIds);
1630 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1635 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1640 strcpy(namehead, "/vicep"); /*7 including null terminator */
1642 /* Just return attached partitions. */
1644 for (i = 0; i < 26; i++) {
1645 namehead[6] = i + 'a';
1646 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1652 /*return a list of all partitions on the server. The non mounted
1653 *partitions are returned as -1 in the corresponding slot in partIds*/
1655 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1659 code = XVolListPartitions(acid, pEntries);
1660 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1665 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1667 struct stat rbuf, pbuf;
1669 struct partList partList;
1670 struct DiskPartition *dp;
1673 strcpy(namehead, "/vicep"); /*7 including null terminator */
1675 /* Only report attached partitions */
1676 for (i = 0; i < VOLMAXPARTS; i++) {
1677 #ifdef AFS_DEMAND_ATTACH_FS
1678 dp = VGetPartitionById(i, 0);
1681 namehead[6] = i + 'a';
1685 namehead[6] = 'a' + (k / 26);
1686 namehead[7] = 'a' + (k % 26);
1689 dp = VGetPartition(namehead, 0);
1692 partList.partId[j++] = i;
1694 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1695 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1697 pEntries->partEntries_len = j;
1702 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1704 ExtractVolId(char vname[])
1707 char name[VOLSER_MAXVOLNAME + 1];
1709 strcpy(name, vname);
1711 while (name[i] == 'V' || name[i] == '0')
1714 name[11] = '\0'; /* smash the "." */
1715 return (atol(&name[i]));
1718 /*return the name of the next volume header in the directory associated with dirp and dp.
1719 *the volume id is returned in volid, and volume header name is returned in volname*/
1721 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1725 dp = readdir(dirp); /*read next entry in the directory */
1727 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1728 *volid = ExtractVolId(dp->d_name);
1729 strcpy(volname, dp->d_name);
1730 return 0; /*return the name of the file representing a volume */
1732 strcpy(volname, "");
1733 return 0; /*volname doesnot represent a volume */
1736 strcpy(volname, "EOD");
1737 return 0; /*end of directory */
1742 /*return the header information about the <volid> */
1744 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1745 volumeId, volEntries *volumeInfo)
1749 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
1750 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1755 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1756 volumeId, volEntries *volumeInfo)
1759 register struct Volume *tv;
1760 struct DiskPartition *partP;
1761 struct volser_trans *ttc;
1762 char pname[9], volname[20];
1763 afs_int32 error = 0;
1769 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
1770 pntr = volumeInfo->volEntries_val;
1771 volumeInfo->volEntries_len = 1;
1772 if (GetPartName(partid, pname))
1773 return VOLSERILLEGAL_PARTITION;
1774 if (!(partP = VGetPartition(pname, 0)))
1775 return VOLSERILLEGAL_PARTITION;
1776 dirp = opendir(VPartitionPath(partP));
1778 return VOLSERILLEGAL_PARTITION;
1779 strcpy(volname, "");
1780 ttc = (struct volser_trans *)0;
1781 tv = (Volume *) 0; /* volume not attached */
1783 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
1785 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
1786 GetNextVol(dirp, volname, &volid);
1787 continue; /*back to while loop */
1790 if (volid == volumeId) { /*copy other things too */
1792 #ifndef AFS_PTHREAD_ENV
1793 IOMGR_Poll(); /*make sure that the client doesnot time out */
1795 ttc = NewTrans(volid, partid);
1797 pntr->status = VBUSY;
1798 pntr->volid = volid;
1801 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
1803 pntr->status = 0; /*things are messed up */
1804 strcpy(pntr->name, volname);
1805 pntr->volid = volid;
1806 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
1809 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1810 /*this volume will be salvaged */
1812 strcpy(pntr->name, volname);
1813 pntr->volid = volid;
1814 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
1818 if (tv->header->diskstuff.needsSalvaged) {
1819 /*this volume will be salvaged */
1821 strcpy(pntr->name, volname);
1822 pntr->volid = volid;
1823 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
1827 /*read in the relevant info */
1828 pntr->status = VOK; /*its ok */
1829 pntr->volid = tv->header->diskstuff.id;
1830 strcpy(pntr->name, tv->header->diskstuff.name);
1831 pntr->type = tv->header->diskstuff.type; /*if ro volume */
1832 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
1833 pntr->backupID = tv->header->diskstuff.backupId;
1834 pntr->parentID = tv->header->diskstuff.parentId;
1835 pntr->copyDate = tv->header->diskstuff.copyDate;
1836 pntr->inUse = tv->header->diskstuff.inUse;
1837 pntr->size = tv->header->diskstuff.diskused;
1838 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1839 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1840 pntr->maxquota = tv->header->diskstuff.maxquota;
1841 pntr->filecount = tv->header->diskstuff.filecount;
1842 now = FT_ApproxTime();
1843 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1846 pntr->dayUse = tv->header->diskstuff.dayUse;
1847 pntr->creationDate = tv->header->diskstuff.creationDate;
1848 pntr->accessDate = tv->header->diskstuff.accessDate;
1849 pntr->updateDate = tv->header->diskstuff.updateDate;
1850 pntr->backupDate = tv->header->diskstuff.backupDate;
1851 pntr->spare0 = tv->header->diskstuff.minquota;
1853 (long)tv->header->diskstuff.weekUse[0] +
1854 (long)tv->header->diskstuff.weekUse[1] +
1855 (long)tv->header->diskstuff.weekUse[2] +
1856 (long)tv->header->diskstuff.weekUse[3] +
1857 (long)tv->header->diskstuff.weekUse[4] +
1858 (long)tv->header->diskstuff.weekUse[5] +
1859 (long)tv->header->diskstuff.weekUse[6];
1860 pntr->spare2 = V_volUpCounter(tv);
1861 pntr->flags = pntr->spare3 = (long)0;
1862 VDetachVolume(&error, tv); /*free the volume */
1865 pntr->status = 0; /*things are messed up */
1866 strcpy(pntr->name, volname);
1867 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
1872 GetNextVol(dirp, volname, &volid);
1876 VDetachVolume(&error, tv);
1880 DeleteTrans(ttc, 1);
1881 ttc = (struct volser_trans *)0;
1891 /*------------------------------------------------------------------------
1892 * EXPORTED SAFSVolXListOneVolume
1895 * Returns extended info on volume a_volID on partition a_partID.
1898 * a_rxCidP : Pointer to the Rx call we're performing.
1899 * a_partID : Partition for which we want the extended list.
1900 * a_volID : Volume ID we wish to know about.
1901 * a_volumeXInfoP : Ptr to the extended info blob.
1904 * 0 Successful operation
1905 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1908 * Nothing interesting.
1912 *------------------------------------------------------------------------*/
1915 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1916 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1920 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1921 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1926 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1927 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1928 { /*SAFSVolXListOneVolume */
1930 volintXInfo *xInfoP; /*Ptr to the extended vol info */
1931 register struct Volume *tv; /*Volume ptr */
1932 struct volser_trans *ttc; /*Volume transaction ptr */
1933 struct DiskPartition *partP; /*Ptr to partition */
1934 char pname[9], volname[20]; /*Partition, volume names */
1935 afs_int32 error; /*Error code */
1936 afs_int32 code; /*Return code */
1937 DIR *dirp; /*Partition directory ptr */
1938 afs_int32 currVolID; /*Current volume ID */
1939 int found = 0; /*Did we find the volume we need? */
1940 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
1941 int numStatBytes; /*Num stat bytes to copy per volume */
1945 * Set up our pointers for action, marking our structure to hold exactly
1946 * one entry. Also, assume we'll fail in our quest.
1948 a_volumeXInfoP->volXEntries_val =
1949 (volintXInfo *) malloc(sizeof(volintXInfo));
1950 xInfoP = a_volumeXInfoP->volXEntries_val;
1951 a_volumeXInfoP->volXEntries_len = 1;
1955 * If the partition name we've been given is bad, bogue out.
1957 if (GetPartName(a_partID, pname))
1958 return (VOLSERILLEGAL_PARTITION);
1961 * Open the directory representing the given AFS parttion. If we can't
1964 if (!(partP = VGetPartition(pname, 0)))
1965 return VOLSERILLEGAL_PARTITION;
1966 dirp = opendir(VPartitionPath(partP));
1968 return (VOLSERILLEGAL_PARTITION);
1971 * Sweep through the partition directory, looking for the desired entry.
1972 * First, of course, figure out how many stat bytes to copy out of each
1976 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1977 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1978 strcpy(volname, "");
1979 ttc = (struct volser_trans *)0; /*No transaction yet */
1980 tv = (Volume *) 0; /*Volume not yet attached */
1982 while (strcmp(volname, "EOD") && !found) {
1984 * If this is not a volume, move on to the next entry in the
1985 * partition's directory.
1987 if (!strcmp(volname, "")) {
1988 GetNextVol(dirp, volname, &currVolID);
1992 if (currVolID == a_volID) {
1994 * We found the volume entry we're interested. Pull out the
1995 * extended information, remembering to poll (so that the client
1996 * doesn't time out) and to set up a transaction on the volume.
1999 #ifndef AFS_PTHREAD_ENV
2002 ttc = NewTrans(currVolID, a_partID);
2005 * Couldn't get a transaction on this volume; let our caller
2008 xInfoP->status = VBUSY;
2009 xInfoP->volid = currVolID;
2014 * Attach the volume, give up on the volume if we can't.
2016 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2018 xInfoP->status = 0; /*things are messed up */
2019 strcpy(xInfoP->name, volname);
2020 xInfoP->volid = currVolID;
2021 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
2027 * Also bag out on this volume if it's been marked as needing a
2028 * salvage or to-be-destroyed.
2030 volDiskDataP = &(tv->header->diskstuff);
2031 if (volDiskDataP->destroyMe == DESTROY_ME) {
2033 strcpy(xInfoP->name, volname);
2034 xInfoP->volid = currVolID;
2035 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2039 if (volDiskDataP->needsSalvaged) {
2041 strcpy(xInfoP->name, volname);
2042 xInfoP->volid = currVolID;
2043 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
2048 * Pull out the desired info and stuff it into the area we'll be
2049 * returning to our caller.
2051 strcpy(xInfoP->name, volDiskDataP->name);
2052 xInfoP->volid = volDiskDataP->id;
2053 xInfoP->type = volDiskDataP->type;
2054 xInfoP->backupID = volDiskDataP->backupId;
2055 xInfoP->parentID = volDiskDataP->parentId;
2056 xInfoP->cloneID = volDiskDataP->cloneId;
2057 xInfoP->status = VOK;
2058 xInfoP->copyDate = volDiskDataP->copyDate;
2059 xInfoP->inUse = volDiskDataP->inUse;
2060 xInfoP->creationDate = volDiskDataP->creationDate;
2061 xInfoP->accessDate = volDiskDataP->accessDate;
2062 xInfoP->updateDate = volDiskDataP->updateDate;
2063 xInfoP->backupDate = volDiskDataP->backupDate;
2064 xInfoP->filecount = volDiskDataP->filecount;
2065 xInfoP->maxquota = volDiskDataP->maxquota;
2066 xInfoP->size = volDiskDataP->diskused;
2069 * Copy out the stat fields in a single operation.
2071 now = FT_ApproxTime();
2072 if (now - volDiskDataP->dayUseDate > OneDay) {
2074 memset((char *)&(xInfoP->stat_reads[0]), 0, numStatBytes);
2076 xInfoP->dayUse = volDiskDataP->dayUse;
2077 memcpy((char *)&(xInfoP->stat_reads[0]),
2078 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2082 * We're done copying. Detach the volume and iterate (at this
2083 * point, since we found our volume, we'll then drop out of the
2086 VDetachVolume(&error, tv);
2090 strcpy(xInfoP->name, volname);
2091 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2097 * At this point, we're golden.
2100 } /*Found desired volume */
2101 GetNextVol(dirp, volname, &currVolID);
2105 * Drop the transaction we have for this volume.
2109 VDetachVolume(&error, tv);
2113 DeleteTrans(ttc, 1);
2114 ttc = (struct volser_trans *)0;
2118 * Clean up before going to dinner: close the partition directory,
2119 * return the proper value.
2124 } /*SAFSVolXListOneVolume */
2126 /*returns all the volumes on partition partid. If flags = 1 then all the
2127 * relevant info about the volumes is also returned */
2129 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2130 volEntries *volumeInfo)
2134 code = VolListVolumes(acid, partid, flags, volumeInfo);
2135 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2140 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2141 volEntries *volumeInfo)
2144 register struct Volume *tv;
2145 struct DiskPartition *partP;
2146 struct volser_trans *ttc;
2147 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2148 char pname[9], volname[20];
2149 afs_int32 error = 0;
2154 volumeInfo->volEntries_val =
2155 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2156 pntr = volumeInfo->volEntries_val;
2157 volumeInfo->volEntries_len = 0;
2158 if (GetPartName(partid, pname))
2159 return VOLSERILLEGAL_PARTITION;
2160 if (!(partP = VGetPartition(pname, 0)))
2161 return VOLSERILLEGAL_PARTITION;
2162 dirp = opendir(VPartitionPath(partP));
2164 return VOLSERILLEGAL_PARTITION;
2165 strcpy(volname, "");
2166 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2167 ttc = (struct volser_trans *)0; /* new one for each pass */
2168 tv = (Volume *) 0; /* volume not attached */
2170 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2171 GetNextVol(dirp, volname, &volid);
2172 continue; /*back to while loop */
2175 if (flags) { /*copy other things too */
2176 #ifndef AFS_PTHREAD_ENV
2177 IOMGR_Poll(); /*make sure that the client doesnot time out */
2179 ttc = NewTrans(volid, partid);
2181 pntr->status = VBUSY;
2182 pntr->volid = volid;
2185 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2187 pntr->status = 0; /*things are messed up */
2188 strcpy(pntr->name, volname);
2189 pntr->volid = volid;
2190 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
2193 if (tv->header->diskstuff.needsSalvaged) {
2194 /*this volume will be salvaged */
2196 strcpy(pntr->name, volname);
2197 pntr->volid = volid;
2198 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
2202 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2203 /*this volume will be salvaged */
2206 /*read in the relevant info */
2207 pntr->status = VOK; /*its ok */
2208 pntr->volid = tv->header->diskstuff.id;
2209 strcpy(pntr->name, tv->header->diskstuff.name);
2210 pntr->type = tv->header->diskstuff.type; /*if ro volume */
2211 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
2212 pntr->backupID = tv->header->diskstuff.backupId;
2213 pntr->parentID = tv->header->diskstuff.parentId;
2214 pntr->copyDate = tv->header->diskstuff.copyDate;
2215 pntr->inUse = tv->header->diskstuff.inUse;
2216 pntr->size = tv->header->diskstuff.diskused;
2217 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2218 pntr->maxquota = tv->header->diskstuff.maxquota;
2219 pntr->filecount = tv->header->diskstuff.filecount;
2220 now = FT_ApproxTime();
2221 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2224 pntr->dayUse = tv->header->diskstuff.dayUse;
2225 pntr->creationDate = tv->header->diskstuff.creationDate;
2226 pntr->accessDate = tv->header->diskstuff.accessDate;
2227 pntr->updateDate = tv->header->diskstuff.updateDate;
2228 pntr->backupDate = tv->header->diskstuff.backupDate;
2229 pntr->spare0 = tv->header->diskstuff.minquota;
2231 (long)tv->header->diskstuff.weekUse[0] +
2232 (long)tv->header->diskstuff.weekUse[1] +
2233 (long)tv->header->diskstuff.weekUse[2] +
2234 (long)tv->header->diskstuff.weekUse[3] +
2235 (long)tv->header->diskstuff.weekUse[4] +
2236 (long)tv->header->diskstuff.weekUse[5] +
2237 (long)tv->header->diskstuff.weekUse[6];
2238 pntr->spare2 = V_volUpCounter(tv);
2239 pntr->flags = pntr->spare3 = (long)0;
2240 VDetachVolume(&error, tv); /*free the volume */
2243 pntr->status = 0; /*things are messed up */
2244 strcpy(pntr->name, volname);
2245 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2250 pntr->volid = volid;
2251 /*just volids are needed */
2256 DeleteTrans(ttc, 1);
2257 ttc = (struct volser_trans *)0;
2260 volumeInfo->volEntries_len += 1;
2261 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2262 /*running out of space, allocate more space */
2263 allocSize = (allocSize * 3) / 2;
2265 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2266 allocSize * sizeof(volintInfo));
2269 VDetachVolume(&error, tv);
2273 DeleteTrans(ttc, 1);
2274 ttc = (struct volser_trans *)0;
2277 return VOLSERNO_MEMORY;
2279 volumeInfo->volEntries_val = pntr; /* point to new block */
2280 /* set pntr to the right position */
2281 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2287 VDetachVolume(&error, tv);
2291 DeleteTrans(ttc, 1);
2292 ttc = (struct volser_trans *)0;
2294 GetNextVol(dirp, volname, &volid);
2299 DeleteTrans(ttc, 1);
2304 /*------------------------------------------------------------------------
2305 * EXPORTED SAFSVolXListVolumes
2308 * Returns all the volumes on partition a_partID. If a_flags
2309 * is set to 1, then all the relevant extended volume information
2313 * a_rxCidP : Pointer to the Rx call we're performing.
2314 * a_partID : Partition for which we want the extended list.
2315 * a_flags : Various flags.
2316 * a_volumeXInfoP : Ptr to the extended info blob.
2319 * 0 Successful operation
2320 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2321 * VOLSERNO_MEMORY if we ran out of memory allocating
2325 * Nothing interesting.
2329 *------------------------------------------------------------------------*/
2332 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2333 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2337 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2338 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2343 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2344 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2345 { /*SAFSVolXListVolumes */
2347 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2348 register struct Volume *tv; /*Volume ptr */
2349 struct DiskPartition *partP; /*Ptr to partition */
2350 struct volser_trans *ttc; /*Volume transaction ptr */
2351 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2352 char pname[9], volname[20]; /*Partition, volume names */
2353 afs_int32 error = 0; /*Return code */
2354 DIR *dirp; /*Partition directory ptr */
2355 afs_int32 volid; /*Current volume ID */
2356 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2357 int numStatBytes; /*Num stat bytes to copy per volume */
2361 * Allocate a large array of extended volume info structures, then
2362 * set it up for action.
2364 a_volumeXInfoP->volXEntries_val =
2365 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2366 xInfoP = a_volumeXInfoP->volXEntries_val;
2367 a_volumeXInfoP->volXEntries_len = 0;
2370 * If the partition name we've been given is bad, bogue out.
2372 if (GetPartName(a_partID, pname))
2373 return (VOLSERILLEGAL_PARTITION);
2376 * Open the directory representing the given AFS parttion. If we can't
2379 if (!(partP = VGetPartition(pname, 0)))
2380 return VOLSERILLEGAL_PARTITION;
2381 dirp = opendir(VPartitionPath(partP));
2383 return (VOLSERILLEGAL_PARTITION);
2386 * Sweep through the partition directory, acting on each entry. First,
2387 * of course, figure out how many stat bytes to copy out of each volume.
2390 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2391 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2392 strcpy(volname, "");
2393 while (strcmp(volname, "EOD")) {
2394 ttc = (struct volser_trans *)0; /*New one for each pass */
2395 tv = (Volume *) 0; /*Volume not yet attached */
2398 * If this is not a volume, move on to the next entry in the
2399 * partition's directory.
2401 if (!strcmp(volname, "")) {
2402 GetNextVol(dirp, volname, &volid);
2408 * Full info about the volume desired. Poll to make sure the
2409 * client doesn't time out, then start up a new transaction.
2411 #ifndef AFS_PTHREAD_ENV
2414 ttc = NewTrans(volid, a_partID);
2417 * Couldn't get a transaction on this volume; let our caller
2420 xInfoP->status = VBUSY;
2421 xInfoP->volid = volid;
2426 * Attach the volume, give up on this volume if we can't.
2428 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2430 xInfoP->status = 0; /*things are messed up */
2431 strcpy(xInfoP->name, volname);
2432 xInfoP->volid = volid;
2433 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2439 * Also bag out on this volume if it's been marked as needing a
2440 * salvage or to-be-destroyed.
2442 volDiskDataP = &(tv->header->diskstuff);
2443 if (volDiskDataP->needsSalvaged) {
2445 strcpy(xInfoP->name, volname);
2446 xInfoP->volid = volid;
2447 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
2451 if (volDiskDataP->destroyMe == DESTROY_ME)
2455 * Pull out the desired info and stuff it into the area we'll be
2456 * returning to our caller.
2458 strcpy(xInfoP->name, volDiskDataP->name);
2459 xInfoP->volid = volDiskDataP->id;
2460 xInfoP->type = volDiskDataP->type;
2461 xInfoP->backupID = volDiskDataP->backupId;
2462 xInfoP->parentID = volDiskDataP->parentId;
2463 xInfoP->cloneID = volDiskDataP->cloneId;
2464 xInfoP->status = VOK;
2465 xInfoP->copyDate = volDiskDataP->copyDate;
2466 xInfoP->inUse = volDiskDataP->inUse;
2467 xInfoP->creationDate = volDiskDataP->creationDate;
2468 xInfoP->accessDate = volDiskDataP->accessDate;
2469 xInfoP->updateDate = volDiskDataP->updateDate;
2470 xInfoP->backupDate = volDiskDataP->backupDate;
2471 now = FT_ApproxTime();
2472 if (now - volDiskDataP->dayUseDate > OneDay)
2475 xInfoP->dayUse = volDiskDataP->dayUse;
2476 xInfoP->filecount = volDiskDataP->filecount;
2477 xInfoP->maxquota = volDiskDataP->maxquota;
2478 xInfoP->size = volDiskDataP->diskused;
2481 * Copy out the stat fields in a single operation.
2483 memcpy((char *)&(xInfoP->stat_reads[0]),
2484 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2487 * We're done copying. Detach the volume and iterate.
2489 VDetachVolume(&error, tv);
2493 strcpy(xInfoP->name, volname);
2494 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2498 } /*Full contents desired */
2501 * Just volume IDs are needed.
2503 xInfoP->volid = volid;
2507 * Drop the transaction we have for this volume.
2510 DeleteTrans(ttc, 1);
2511 ttc = (struct volser_trans *)0;
2515 * Bump the pointer in the data area we're building, along with
2516 * the count of the number of entries it contains.
2519 (a_volumeXInfoP->volXEntries_len)++;
2520 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2522 * We're running out of space in the area we've built. Grow it.
2524 allocSize = (allocSize * 3) / 2;
2525 xInfoP = (volintXInfo *)
2526 realloc((char *)a_volumeXInfoP->volXEntries_val,
2527 (allocSize * sizeof(volintXInfo)));
2528 if (xInfoP == NULL) {
2530 * Bummer, no memory. Bag it, tell our caller what went wrong.
2533 VDetachVolume(&error, tv);
2537 DeleteTrans(ttc, 1);
2538 ttc = (struct volser_trans *)0;
2541 return (VOLSERNO_MEMORY);
2545 * Memory reallocation worked. Correct our pointers so they
2546 * now point to the new block and the current open position within
2549 a_volumeXInfoP->volXEntries_val = xInfoP;
2551 a_volumeXInfoP->volXEntries_val +
2552 a_volumeXInfoP->volXEntries_len;
2554 /*Need more space */
2557 * Detach our current volume and the transaction on it, then move on
2558 * to the next volume in the partition directory.
2561 VDetachVolume(&error, tv);
2565 DeleteTrans(ttc, 1);
2566 ttc = (struct volser_trans *)0;
2568 GetNextVol(dirp, volname, &volid);
2569 } /*Sweep through the partition directory */
2572 * We've examined all entries in the partition directory. Close it,
2573 * delete our transaction (if any), and go home happy.
2577 DeleteTrans(ttc, 1);
2580 } /*SAFSVolXListVolumes */
2582 /*this call is used to monitor the status of volser for debugging purposes.
2583 *information about all the active transactions is returned in transInfo*/
2585 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2589 code = VolMonitor(acid, transInfo);
2590 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2595 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2597 transDebugInfo *pntr;
2598 afs_int32 allocSize = 50;
2599 struct volser_trans *tt, *allTrans;
2601 transInfo->transDebugEntries_val =
2602 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2603 pntr = transInfo->transDebugEntries_val;
2604 transInfo->transDebugEntries_len = 0;
2605 allTrans = TransList();
2606 if (allTrans == (struct volser_trans *)0)
2607 return 0; /*no active transactions */
2608 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2609 pntr->tid = tt->tid;
2610 pntr->time = tt->time;
2611 pntr->creationTime = tt->creationTime;
2612 pntr->returnCode = tt->returnCode;
2613 pntr->volid = tt->volid;
2614 pntr->partition = tt->partition;
2615 pntr->iflags = tt->iflags;
2616 pntr->vflags = tt->vflags;
2617 pntr->tflags = tt->tflags;
2618 strcpy(pntr->lastProcName, tt->lastProcName);
2619 pntr->callValid = 0;
2620 if (tt->rxCallPtr) { /*record call related info */
2621 pntr->callValid = 1;
2622 pntr->readNext = tt->rxCallPtr->rnext;
2623 pntr->transmitNext = tt->rxCallPtr->tnext;
2624 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2625 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2628 transInfo->transDebugEntries_len += 1;
2629 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2630 allocSize = (allocSize * 3) / 2;
2632 (transDebugInfo *) realloc((char *)transInfo->
2633 transDebugEntries_val,
2635 sizeof(transDebugInfo));
2636 transInfo->transDebugEntries_val = pntr;
2638 transInfo->transDebugEntries_val +
2639 transInfo->transDebugEntries_len;
2640 /*set pntr to right position */
2649 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2653 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2654 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2655 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2661 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2664 afs_int32 error = 0;
2665 register struct volser_trans *tt;
2666 char caller[MAXKTCNAMELEN];
2668 if (strlen(name) > 31)
2669 return VOLSERBADNAME;
2670 if (!afsconf_SuperUser(tdir, acid, caller))
2671 return VOLSERBAD_ACCESS; /*not a super user */
2672 /* find the trans */
2673 tt = FindTrans(atid);
2676 if (tt->vflags & VTDeleted) {
2677 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2681 strcpy(tt->lastProcName, "SetIdsTypes");
2682 tt->rxCallPtr = acid;
2686 V_backupId(tv) = backupId;
2687 V_cloneId(tv) = cloneId;
2688 V_parentId(tv) = pId;
2689 strcpy((&V_disk(tv))->name, name);
2690 VUpdateVolume(&error, tv);
2692 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2696 tt->rxCallPtr = (struct rx_call *)0;
2697 if (TRELE(tt) && !error)
2698 return VOLSERTRELE_ERROR;
2702 tt->rxCallPtr = (struct rx_call *)0;
2703 if (TRELE(tt) && !error)
2704 return VOLSERTRELE_ERROR;
2709 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2713 code = VolSetDate(acid, atid, cdate);
2714 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2720 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2723 afs_int32 error = 0;
2724 register struct volser_trans *tt;
2725 char caller[MAXKTCNAMELEN];
2727 if (!afsconf_SuperUser(tdir, acid, caller))
2728 return VOLSERBAD_ACCESS; /*not a super user */
2729 /* find the trans */
2730 tt = FindTrans(atid);
2733 if (tt->vflags & VTDeleted) {
2734 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2738 strcpy(tt->lastProcName, "SetDate");
2739 tt->rxCallPtr = acid;
2742 V_creationDate(tv) = cdate;
2743 VUpdateVolume(&error, tv);
2745 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2749 tt->rxCallPtr = (struct rx_call *)0;
2750 if (TRELE(tt) && !error)
2751 return VOLSERTRELE_ERROR;
2755 tt->rxCallPtr = (struct rx_call *)0;
2756 if (TRELE(tt) && !error)
2757 return VOLSERTRELE_ERROR;
2762 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2768 char caller[MAXKTCNAMELEN];
2770 register struct volser_trans *ttc;
2771 char pname[16], volname[20];
2772 struct DiskPartition *partP;
2773 afs_int32 ret = ENODEV;
2776 if (!afsconf_SuperUser(tdir, acid, caller))
2777 return VOLSERBAD_ACCESS; /*not a super user */
2778 if (GetPartName(partId, pname))
2779 return VOLSERILLEGAL_PARTITION;
2780 if (!(partP = VGetPartition(pname, 0)))
2781 return VOLSERILLEGAL_PARTITION;
2782 dirp = opendir(VPartitionPath(partP));
2784 return VOLSERILLEGAL_PARTITION;
2785 strcpy(volname, "");
2786 ttc = (struct volser_trans *)0;
2788 while (strcmp(volname, "EOD")) {
2789 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2790 GetNextVol(dirp, volname, &volid);
2791 continue; /*back to while loop */
2794 if (volid == volumeId) { /*copy other things too */
2795 #ifndef AFS_PTHREAD_ENV
2796 IOMGR_Poll(); /*make sure that the client doesnot time out */
2798 ttc = NewTrans(volumeId, partId);
2802 #ifdef AFS_NAMEI_ENV
2803 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2805 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2809 GetNextVol(dirp, volname, &volid);
2813 DeleteTrans(ttc, 1);
2814 ttc = (struct volser_trans *)0;
2823 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2824 register struct volintSize *size)
2827 register struct volser_trans *tt;
2828 char caller[MAXKTCNAMELEN];
2830 if (!afsconf_SuperUser(tdir, acid, caller))
2831 return VOLSERBAD_ACCESS; /*not a super user */
2832 tt = FindTrans(fromTrans);
2835 if (tt->vflags & VTDeleted) {
2839 strcpy(tt->lastProcName, "GetSize");
2840 tt->rxCallPtr = acid;
2841 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2842 tt->rxCallPtr = (struct rx_call *)0;
2844 return VOLSERTRELE_ERROR;
2846 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2850 /* GetPartName - map partid (a decimal number) into pname (a string)
2851 * Since for NT we actually want to return the drive name, we map through the
2855 GetPartName(afs_int32 partid, char *pname)
2860 strcpy(pname, "/vicep");
2861 pname[6] = 'a' + partid;
2864 } else if (partid < VOLMAXPARTS) {
2865 strcpy(pname, "/vicep");
2867 pname[6] = 'a' + (partid / 26);
2868 pname[7] = 'a' + (partid % 26);