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/daemon_com.h>
65 #include <afs/fssync.h>
67 #include "afs/audit.h"
73 #include "volser_prototypes.h"
76 extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
77 extern struct afsconf_dir *tdir;
79 /* Needed by Irix. Leave, or include a header */
80 extern char *volutil_PartitionName();
82 extern void LogError(afs_int32 errcode);
84 /* Forward declarations */
85 static int GetPartName(afs_int32 partid, char *pname);
87 #define OneDay (24*60*60)
93 afs_int32 localTid = 1;
94 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
95 VolDeleteVolume(), VolClone();
96 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
97 VolForward(), VolDump();
98 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
99 VolSetInfo(), VolGetName();
100 afs_int32 VolListPartitions(), VolListOneVolume(),
101 VolXListOneVolume(), VolXListVolumes();
102 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
103 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
105 /* this call unlocks all of the partition locks we've set */
109 register struct DiskPartition *tp;
110 for (tp = DiskPartitionList; tp; tp = tp->next) {
111 if (tp->lock_fd != -1) {
112 close(tp->lock_fd); /* releases flock held on this partition */
119 /* get partition id from a name */
121 PartitionID(char *aname)
124 register int code = 0;
129 return -1; /* unknown */
131 /* otherwise check for vicepa or /vicepa, or just plain "a" */
133 if (!strncmp(aname, "/vicep", 6)) {
134 strncpy(ascii, aname + 6, 2);
136 return -1; /* bad partition name */
137 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
138 * from 0. Do the appropriate conversion */
140 /* one char name, 0..25 */
141 if (ascii[0] < 'a' || ascii[0] > 'z')
142 return -1; /* wrongo */
143 return ascii[0] - 'a';
145 /* two char name, 26 .. <whatever> */
146 if (ascii[0] < 'a' || ascii[0] > 'z')
147 return -1; /* wrongo */
148 if (ascii[1] < 'a' || ascii[1] > 'z')
149 return -1; /* just as bad */
150 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
151 if (code > VOLMAXPARTS)
158 ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
162 /* 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 */
163 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
168 ConvertPartition(int apartno, char *aname, int asize)
174 strcpy(aname, "/vicep");
176 aname[6] = 'a' + apartno;
180 aname[6] = 'a' + (apartno / 26);
181 aname[7] = 'a' + (apartno % 26);
187 /* the only attach function that takes a partition is "...ByName", so we use it */
189 XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
191 char pbuf[30], vbuf[20];
192 register struct Volume *tv;
194 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
198 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
202 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
206 /* Adapted from the file server; create a root directory for this volume */
208 ViceCreateRoot(Volume *vp)
211 struct acl_accessList *ACL;
213 Inode inodeNumber, nearInode;
214 char buf[SIZEOF_LARGEDISKVNODE];
215 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
216 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
222 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
224 V_pref(vp, nearInode);
226 IH_CREATE(V_linkHandle(vp), V_device(vp),
227 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
229 assert(VALID_INO(inodeNumber));
231 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
232 did.Volume = V_id(vp);
233 did.Vnode = (VnodeId) 1;
236 assert(!(MakeDir(&dir, &did, &did)));
237 DFlush(); /* flush all modified dir buffers out */
238 DZap(&dir); /* Remove all buffers for this dir */
239 length = Length(&dir); /* Remember size of this directory */
241 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
243 /* build a single entry ACL that gives all rights to system:administrators */
244 /* this section of code assumes that access list format is not going to
247 ACL = VVnodeDiskACL(vnode);
248 ACL->size = sizeof(struct acl_accessList);
249 ACL->version = ACL_ACLVERSION;
253 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
254 ACL->entries[0].rights =
255 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
256 | PRSFS_LOCK | PRSFS_ADMINISTER;
258 vnode->type = vDirectory;
260 vnode->modeBits = 0777;
261 vnode->linkCount = 2;
262 VNDISK_SET_LEN(vnode, length);
263 vnode->uniquifier = 1;
264 V_uniquifier(vp) = vnode->uniquifier + 1;
265 vnode->dataVersion = 1;
266 VNDISK_SET_INO(vnode, inodeNumber);
267 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
271 vnode->vnodeMagic = vcp->magic;
273 IH_INIT(h, vp->device, V_parentId(vp),
274 vp->vnodeIndex[vLarge].handle->ih_ino);
277 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
279 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
280 assert(code == SIZEOF_LARGEDISKVNODE);
281 FDH_REALLYCLOSE(fdP);
283 VNDISK_GET_LEN(length, vnode);
284 V_diskused(vp) = nBlocks(length);
290 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
295 code = VolPartitionInfo(acid, pname, partition);
296 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
301 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
304 register struct DiskPartition *dp;
307 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
310 dp = VGetPartition(pname, 0);
312 strncpy(partition->name, dp->name, 32);
313 strncpy(partition->devName, dp->devName, 32);
314 partition->lock_fd = dp->lock_fd;
315 partition->free = dp->free;
316 partition->minFree = dp->totalUsable;
319 return VOLSERILLEGAL_PARTITION;
322 /* obliterate a volume completely, and slowly. */
324 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
328 code = VolNukeVolume(acid, apartID, avolID);
329 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
334 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
339 register afs_int32 code;
341 char caller[MAXKTCNAMELEN];
343 /* check for access */
344 if (!afsconf_SuperUser(tdir, acid, caller))
345 return VOLSERBAD_ACCESS;
347 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
349 tp = volutil_PartitionName(apartID);
352 strcpy(partName, tp); /* remember it for later */
353 /* we first try to attach the volume in update mode, so that the file
354 * server doesn't try to use it (and abort) while (or after) we delete it.
355 * If we don't get the volume, that's fine, too. We just won't put it back.
357 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
358 code = nuke(partName, avolID);
360 VDetachVolume(&error, tvp);
364 /* create a new volume, with name aname, on the specified partition (1..n)
365 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
366 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
367 * for the volume id (useful for things like volume restore).
368 * Return the new volume id in *avolid.
371 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
372 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
378 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
379 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
380 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
386 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
387 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
392 afs_int32 junk; /* discardable error code */
393 register afs_int32 volumeID, doCreateRoot = 1;
394 register struct volser_trans *tt;
396 char caller[MAXKTCNAMELEN];
398 if (strlen(aname) > 31)
399 return VOLSERBADNAME;
400 if (!afsconf_SuperUser(tdir, acid, caller))
401 return VOLSERBAD_ACCESS;
403 Log("%s is executing CreateVolume '%s'\n", caller, aname);
404 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
405 return error; /*a standard unix error */
406 if (atype != readwriteVolume && atype != readonlyVolume
407 && atype != backupVolume)
409 if ((volumeID = *avolid) == 0) {
411 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
415 if ((aparent == volumeID) && (atype == readwriteVolume)) {
420 tt = NewTrans(volumeID, apart);
422 Log("1 createvolume: failed to create trans\n");
423 return VOLSERVOLBUSY; /* volume already busy! */
425 vp = VCreateVolume(&error, ppath, volumeID, aparent);
427 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
432 V_uniquifier(vp) = 1;
433 V_creationDate(vp) = V_copyDate(vp);
434 V_inService(vp) = V_blessed(vp) = 1;
436 AssignVolumeName(&V_disk(vp), aname, 0);
439 V_destroyMe(vp) = DESTROY_ME;
441 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
442 VUpdateVolume(&error, vp);
444 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
447 VDetachVolume(&junk, vp); /* rather return the real error code */
452 strcpy(tt->lastProcName, "CreateVolume");
453 tt->rxCallPtr = acid;
454 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
455 tt->rxCallPtr = (struct rx_call *)0;
457 return VOLSERTRELE_ERROR;
461 /* delete the volume associated with this transaction */
463 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
467 code = VolDeleteVolume(acid, atrans);
468 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
473 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
475 register struct volser_trans *tt;
477 char caller[MAXKTCNAMELEN];
479 if (!afsconf_SuperUser(tdir, acid, caller))
480 return VOLSERBAD_ACCESS;
481 tt = FindTrans(atrans);
484 if (tt->vflags & VTDeleted) {
485 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
490 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
491 strcpy(tt->lastProcName, "DeleteVolume");
492 tt->rxCallPtr = acid;
493 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
494 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
495 tt->rxCallPtr = (struct rx_call *)0;
497 return VOLSERTRELE_ERROR;
499 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
500 return 0; /* vpurgevolume doesn't set an error code */
503 /* make a clone of the volume associated with atrans, possibly giving it a new
504 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
505 * for the clone's id). The new clone is given the name newName. Finally, due to
506 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
507 * the clone operation. This may be useful when making new backup volumes, for instance
508 * since the net result of a clone and a purge generally leaves many inode ref counts
509 * the same, while doing them separately would result in far more iincs and idecs being
510 * peformed (and they are slow operations).
512 /* for efficiency reasons, sometimes faster to piggyback a purge here */
514 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
515 afs_int32 newType, char *newName, afs_int32 *newNumber)
519 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
520 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
521 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
527 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
528 afs_int32 newType, char *newName, afs_int32 *newNumber)
531 register struct Volume *originalvp, *purgevp, *newvp;
533 register struct volser_trans *tt, *ttc;
534 char caller[MAXKTCNAMELEN];
536 if (strlen(newName) > 31)
537 return VOLSERBADNAME;
538 if (!afsconf_SuperUser(tdir, acid, caller))
539 return VOLSERBAD_ACCESS; /*not a super user */
541 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
543 originalvp = (Volume *) 0;
544 purgevp = (Volume *) 0;
545 newvp = (Volume *) 0;
546 tt = ttc = (struct volser_trans *)0;
548 if (!newNumber || !*newNumber) {
549 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
554 if (newType != readonlyVolume && newType != backupVolume)
556 tt = FindTrans(atrans);
559 if (tt->vflags & VTDeleted) {
560 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
564 ttc = NewTrans(newId, tt->partition);
565 if (!ttc) { /* someone is messing with the clone already */
569 strcpy(tt->lastProcName, "Clone");
570 tt->rxCallPtr = acid;
574 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
576 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
582 originalvp = tt->volume;
583 if ((V_type(originalvp) == backupVolume)
584 || (V_type(originalvp) == readonlyVolume)) {
585 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
589 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
590 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
596 if (originalvp->device != purgevp->device) {
597 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
601 if (V_type(purgevp) != readonlyVolume) {
602 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
606 if (V_type(originalvp) == readonlyVolume
607 && V_parentId(originalvp) != V_parentId(purgevp)) {
608 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
612 if (V_type(originalvp) == readwriteVolume
613 && tt->volid != V_parentId(purgevp)) {
614 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
623 VCreateVolume(&error, originalvp->partition->name, newId,
624 V_parentId(originalvp));
626 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
627 newvp = (Volume *) 0;
630 if (newType == readonlyVolume)
631 V_cloneId(originalvp) = newId;
632 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
635 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
636 CloneVolume(&error, originalvp, newvp, purgevp);
637 purgevp = NULL; /* clone releases it, maybe even if error */
639 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
643 if (newType == readonlyVolume) {
644 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
645 V_type(newvp) = readonlyVolume;
646 } else if (newType == backupVolume) {
647 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
648 V_type(newvp) = backupVolume;
649 V_backupId(originalvp) = newId;
651 strcpy(newvp->header->diskstuff.name, newName);
652 V_creationDate(newvp) = V_copyDate(newvp);
653 ClearVolumeStats(&V_disk(newvp));
654 V_destroyMe(newvp) = DESTROY_ME;
655 V_inService(newvp) = 0;
656 if (newType == backupVolume) {
657 V_backupDate(originalvp) = V_copyDate(newvp);
658 V_backupDate(newvp) = V_copyDate(newvp);
661 VUpdateVolume(&error, newvp);
663 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
667 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
669 VUpdateVolume(&error, originalvp);
671 Log("1 Volser: Clone: original update %u\n", error);
675 tt->rxCallPtr = (struct rx_call *)0;
677 tt = (struct volser_trans *)0;
678 error = VOLSERTRELE_ERROR;
686 VDetachVolume(&code, purgevp);
688 VDetachVolume(&code, newvp);
690 tt->rxCallPtr = (struct rx_call *)0;
698 /* reclone this volume into the specified id */
700 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
704 code = VolReClone(acid, atrans, cloneId);
705 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
711 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
713 register struct Volume *originalvp, *clonevp;
716 register struct volser_trans *tt, *ttc;
717 char caller[MAXKTCNAMELEN];
719 /*not a super user */
720 if (!afsconf_SuperUser(tdir, acid, caller))
721 return VOLSERBAD_ACCESS;
723 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
725 clonevp = originalvp = (Volume *) 0;
726 tt = (struct volser_trans *)0;
728 tt = FindTrans(atrans);
731 if (tt->vflags & VTDeleted) {
732 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
736 ttc = NewTrans(cloneId, tt->partition);
737 if (!ttc) { /* someone is messing with the clone already */
741 strcpy(tt->lastProcName, "ReClone");
742 tt->rxCallPtr = acid;
744 originalvp = tt->volume;
745 if ((V_type(originalvp) == backupVolume)
746 || (V_type(originalvp) == readonlyVolume)) {
747 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
751 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
752 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
758 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
760 Log("1 Volser: can't attach clone %d\n", cloneId);
764 newType = V_type(clonevp); /* type of the new volume */
766 if (originalvp->device != clonevp->device) {
767 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
772 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
773 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
777 if (V_type(originalvp) == readonlyVolume
778 && V_parentId(originalvp) != V_parentId(clonevp)) {
779 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
783 if (V_type(originalvp) == readwriteVolume
784 && tt->volid != V_parentId(clonevp)) {
785 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
791 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
793 CloneVolume(&error, originalvp, clonevp, clonevp);
795 Log("1 Volser: Clone: reclone operation failed with code %d\n",
801 /* fix up volume name and type, CloneVolume just propagated RW's */
802 if (newType == readonlyVolume) {
803 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
804 V_type(clonevp) = readonlyVolume;
805 } else if (newType == backupVolume) {
806 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
807 V_type(clonevp) = backupVolume;
808 V_backupId(originalvp) = cloneId;
810 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
812 /* pretend recloned volume is a totally new instance */
813 V_copyDate(clonevp) = time(0);
814 V_creationDate(clonevp) = V_copyDate(clonevp);
815 ClearVolumeStats(&V_disk(clonevp));
816 V_destroyMe(clonevp) = 0;
817 V_inService(clonevp) = 0;
818 if (newType == backupVolume) {
819 V_backupDate(originalvp) = V_copyDate(clonevp);
820 V_backupDate(clonevp) = V_copyDate(clonevp);
822 V_inUse(clonevp) = 0;
823 VUpdateVolume(&error, clonevp);
825 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
829 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
831 VUpdateVolume(&error, originalvp);
833 Log("1 Volser: Clone: original update %u\n", error);
837 tt->rxCallPtr = (struct rx_call *)0;
839 tt = (struct volser_trans *)0;
840 error = VOLSERTRELE_ERROR;
847 struct DiskPartition *tpartp = originalvp->partition;
848 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
854 VDetachVolume(&code, clonevp);
856 tt->rxCallPtr = (struct rx_call *)0;
864 /* create a new transaction, associated with volume and partition. Type of
865 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
866 * See volser.h for definition of iflags (the constants are named IT*).
869 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
870 afs_int32 iflags, afs_int32 *ttid)
874 code = VolTransCreate(acid, volume, partition, iflags, ttid);
875 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
881 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
882 afs_int32 iflags, afs_int32 *ttid)
884 register struct volser_trans *tt;
886 afs_int32 error, code;
888 char caller[MAXKTCNAMELEN];
890 if (!afsconf_SuperUser(tdir, acid, caller))
891 return VOLSERBAD_ACCESS; /*not a super user */
892 if (iflags & ITCreate)
894 else if (iflags & ITBusy)
896 else if (iflags & ITReadOnly)
898 else if (iflags & ITOffline)
901 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
906 tt = NewTrans(volume, partition);
908 /* can't create a transaction? put the volume back */
909 Log("1 transcreate: can't create transaction\n");
910 return VOLSERVOLBUSY;
912 tv = XAttachVolume(&error, volume, partition, mode);
916 VDetachVolume(&code, tv);
924 strcpy(tt->lastProcName, "TransCreate");
926 return VOLSERTRELE_ERROR;
931 /* using aindex as a 0-based index, return the aindex'th volume on this server
932 * Both the volume number and partition number (one-based) are returned.
935 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
940 code = VolGetNthVolume(acid, aindex, avolume, apart);
941 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
946 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
949 Log("1 Volser: GetNthVolume: Not yet implemented\n");
953 /* return the volume flags (VT* constants in volser.h) associated with this
957 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
961 code = VolGetFlags(acid, atid, aflags);
962 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
967 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
969 register struct volser_trans *tt;
971 tt = FindTrans(atid);
974 if (tt->vflags & VTDeleted) {
975 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
980 strcpy(tt->lastProcName, "GetFlags");
981 tt->rxCallPtr = acid;
982 *aflags = tt->vflags;
983 tt->rxCallPtr = (struct rx_call *)0;
985 return VOLSERTRELE_ERROR;
990 /* Change the volume flags (VT* constants in volser.h) associated with this
991 * transaction. Effects take place immediately on volume, although volume
992 * remains attached as usual by the transaction.
995 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
999 code = VolSetFlags(acid, atid, aflags);
1000 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1006 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1008 register struct volser_trans *tt;
1009 register struct Volume *vp;
1011 char caller[MAXKTCNAMELEN];
1013 if (!afsconf_SuperUser(tdir, acid, caller))
1014 return VOLSERBAD_ACCESS; /*not a super user */
1015 /* find the trans */
1016 tt = FindTrans(atid);
1019 if (tt->vflags & VTDeleted) {
1020 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1025 strcpy(tt->lastProcName, "SetFlags");
1026 tt->rxCallPtr = acid;
1027 vp = tt->volume; /* pull volume out of transaction */
1029 /* check if we're allowed to make any updates */
1030 if (tt->iflags & ITReadOnly) {
1035 /* handle delete-on-salvage flag */
1036 if (aflags & VTDeleteOnSalvage) {
1037 V_destroyMe(tt->volume) = DESTROY_ME;
1039 V_destroyMe(tt->volume) = 0;
1042 if (aflags & VTOutOfService) {
1043 V_inService(vp) = 0;
1045 V_inService(vp) = 1;
1047 VUpdateVolume(&error, vp);
1048 tt->vflags = aflags;
1049 tt->rxCallPtr = (struct rx_call *)0;
1050 if (TRELE(tt) && !error)
1051 return VOLSERTRELE_ERROR;
1056 /* dumpS the volume associated with a particular transaction from a particular
1057 * date. Send the dump to a different transaction (destTrans) on the server
1058 * specified by the destServer structure.
1061 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1062 struct destServer *destination, afs_int32 destTrans,
1063 struct restoreCookie *cookie)
1068 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1069 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1070 destination->destHost, AUD_LONG, destTrans, AUD_END);
1075 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1076 struct destServer *destination, afs_int32 destTrans,
1077 struct restoreCookie *cookie)
1079 register struct volser_trans *tt;
1080 register afs_int32 code;
1081 register struct rx_connection *tcon;
1082 struct rx_call *tcall;
1083 register struct Volume *vp;
1084 struct rx_securityClass *securityObject;
1085 afs_int32 securityIndex;
1086 char caller[MAXKTCNAMELEN];
1088 if (!afsconf_SuperUser(tdir, acid, caller))
1089 return VOLSERBAD_ACCESS; /*not a super user */
1090 /* initialize things */
1091 tcon = (struct rx_connection *)0;
1092 tt = (struct volser_trans *)0;
1094 /* find the local transaction */
1095 tt = FindTrans(fromTrans);
1098 if (tt->vflags & VTDeleted) {
1099 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1104 strcpy(tt->lastProcName, "Forward");
1106 /* get auth info for the this connection (uses afs from ticket file) */
1107 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1113 /* make an rpc connection to the other server */
1115 rx_NewConnection(htonl(destination->destHost),
1116 htons(destination->destPort), VOLSERVICE_ID,
1117 securityObject, securityIndex);
1119 tt->rxCallPtr = (struct rx_call *)0;
1123 tcall = rx_NewCall(tcon);
1124 tt->rxCallPtr = tcall;
1125 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1126 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1131 /* these next calls implictly call rx_Write when writing out data */
1132 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1135 EndAFSVolRestore(tcall); /* probably doesn't do much */
1136 tt->rxCallPtr = (struct rx_call *)0;
1137 code = rx_EndCall(tcall, 0);
1138 rx_DestroyConnection(tcon); /* done with the connection */
1143 return VOLSERTRELE_ERROR;
1149 (void)rx_EndCall(tcall, 0);
1150 rx_DestroyConnection(tcon);
1153 tt->rxCallPtr = (struct rx_call *)0;
1159 /* Start a dump and send it to multiple places simultaneously.
1160 * If this returns an error (eg, return ENOENT), it means that
1161 * none of the releases worked. If this returns 0, that means
1162 * that one or more of the releases worked, and the caller has
1163 * to examine the results array to see which one(s).
1164 * This will only do EITHER incremental or full, not both, so it's
1165 * the caller's responsibility to be sure that all the destinations
1166 * need just an incremental (and from the same time), if that's
1170 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1171 fromDate, manyDests *destinations, afs_int32 spare,
1172 struct restoreCookie *cookie, manyResults *results)
1174 afs_int32 securityIndex;
1175 struct rx_securityClass *securityObject;
1176 char caller[MAXKTCNAMELEN];
1177 struct volser_trans *tt;
1178 afs_int32 ec, code, *codes;
1179 struct rx_connection **tcons;
1180 struct rx_call **tcalls;
1182 int i, is_incremental;
1185 memset(results, 0, sizeof(manyResults));
1187 if (!afsconf_SuperUser(tdir, acid, caller))
1188 return VOLSERBAD_ACCESS; /*not a super user */
1189 tt = FindTrans(fromTrans);
1192 if (tt->vflags & VTDeleted) {
1193 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1198 strcpy(tt->lastProcName, "ForwardMulti");
1200 /* (fromDate == 0) ==> incremental dump */
1201 is_incremental = (fromDate ? 1 : 0);
1203 i = results->manyResults_len = destinations->manyDests_len;
1204 results->manyResults_val = codes =
1205 (afs_int32 *) malloc(i * sizeof(afs_int32));
1207 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1208 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1210 /* get auth info for this connection (uses afs from ticket file) */
1211 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1213 goto fail; /* in order to audit each failure */
1216 /* make connections to all the other servers */
1217 for (i = 0; i < destinations->manyDests_len; i++) {
1218 struct replica *dest = &(destinations->manyDests_val[i]);
1220 rx_NewConnection(htonl(dest->server.destHost),
1221 htons(dest->server.destPort), VOLSERVICE_ID,
1222 securityObject, securityIndex);
1224 codes[i] = ENOTCONN;
1226 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1227 codes[i] = ENOTCONN;
1230 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1233 (void)rx_EndCall(tcalls[i], 0);
1235 rx_DestroyConnection(tcons[i]);
1242 /* these next calls implictly call rx_Write when writing out data */
1243 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1247 for (i--; i >= 0; i--) {
1248 struct replica *dest = &(destinations->manyDests_val[i]);
1250 if (!code && tcalls[i] && !codes[i]) {
1251 EndAFSVolRestore(tcalls[i]);
1254 ec = rx_EndCall(tcalls[i], 0);
1259 rx_DestroyConnection(tcons[i]); /* done with the connection */
1262 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1263 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1264 dest->trans, AUD_END);
1270 tt->rxCallPtr = (struct rx_call *)0;
1271 if (TRELE(tt) && !code) /* return the first code if it's set */
1272 return VOLSERTRELE_ERROR;
1279 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1283 code = VolDump(acid, fromTrans, fromDate);
1284 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1289 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1292 register struct volser_trans *tt;
1293 char caller[MAXKTCNAMELEN];
1295 if (!afsconf_SuperUser(tdir, acid, caller))
1296 return VOLSERBAD_ACCESS; /*not a super user */
1297 tt = FindTrans(fromTrans);
1300 if (tt->vflags & VTDeleted) {
1301 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1305 strcpy(tt->lastProcName, "Dump");
1306 tt->rxCallPtr = acid;
1307 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1309 tt->rxCallPtr = (struct rx_call *)0;
1313 tt->rxCallPtr = (struct rx_call *)0;
1316 return VOLSERTRELE_ERROR;
1322 * Ha! No more helper process!
1325 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1326 struct restoreCookie *cookie)
1330 code = VolRestore(acid, atrans, aflags, cookie);
1331 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1336 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1337 struct restoreCookie *cookie)
1339 register struct volser_trans *tt;
1340 register afs_int32 code, tcode;
1341 char caller[MAXKTCNAMELEN];
1343 if (!afsconf_SuperUser(tdir, acid, caller))
1344 return VOLSERBAD_ACCESS; /*not a super user */
1345 tt = FindTrans(atrans);
1348 if (tt->vflags & VTDeleted) {
1349 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1353 strcpy(tt->lastProcName, "Restore");
1354 tt->rxCallPtr = acid;
1356 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1358 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1359 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1360 tt->rxCallPtr = (struct rx_call *)0;
1363 return (code ? code : tcode);
1366 /* end a transaction, returning the transaction's final error code in rcode */
1368 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1372 code = VolEndTrans(acid, destTrans, rcode);
1373 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1378 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1380 register struct volser_trans *tt;
1381 char caller[MAXKTCNAMELEN];
1383 if (!afsconf_SuperUser(tdir, acid, caller))
1384 return VOLSERBAD_ACCESS; /*not a super user */
1385 tt = FindTrans(destTrans);
1389 *rcode = tt->returnCode;
1390 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1396 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1400 code = VolSetForwarding(acid, atid, anewsite);
1401 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1407 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1409 register struct volser_trans *tt;
1410 char caller[MAXKTCNAMELEN];
1412 if (!afsconf_SuperUser(tdir, acid, caller))
1413 return VOLSERBAD_ACCESS; /*not a super user */
1414 tt = FindTrans(atid);
1417 if (tt->vflags & VTDeleted) {
1418 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1423 strcpy(tt->lastProcName, "SetForwarding");
1424 tt->rxCallPtr = acid;
1425 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
1426 tt->rxCallPtr = (struct rx_call *)0;
1428 return VOLSERTRELE_ERROR;
1434 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1435 register struct volser_status *astatus)
1439 code = VolGetStatus(acid, atrans, astatus);
1440 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1445 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1446 register struct volser_status *astatus)
1448 register struct Volume *tv;
1449 register struct VolumeDiskData *td;
1450 struct volser_trans *tt;
1453 tt = FindTrans(atrans);
1456 if (tt->vflags & VTDeleted) {
1457 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1462 strcpy(tt->lastProcName, "GetStatus");
1463 tt->rxCallPtr = acid;
1466 tt->rxCallPtr = (struct rx_call *)0;
1471 td = &tv->header->diskstuff;
1472 astatus->volID = td->id;
1473 astatus->nextUnique = td->uniquifier;
1474 astatus->type = td->type;
1475 astatus->parentID = td->parentId;
1476 astatus->cloneID = td->cloneId;
1477 astatus->backupID = td->backupId;
1478 astatus->restoredFromID = td->restoredFromId;
1479 astatus->maxQuota = td->maxquota;
1480 astatus->minQuota = td->minquota;
1481 astatus->owner = td->owner;
1482 astatus->creationDate = td->creationDate;
1483 astatus->accessDate = td->accessDate;
1484 astatus->updateDate = td->updateDate;
1485 astatus->expirationDate = td->expirationDate;
1486 astatus->backupDate = td->backupDate;
1487 astatus->copyDate = td->copyDate;
1488 tt->rxCallPtr = (struct rx_call *)0;
1490 return VOLSERTRELE_ERROR;
1496 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1497 register struct volintInfo *astatus)
1501 code = VolSetInfo(acid, atrans, astatus);
1502 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1507 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1508 register struct volintInfo *astatus)
1510 register struct Volume *tv;
1511 register struct VolumeDiskData *td;
1512 struct volser_trans *tt;
1513 char caller[MAXKTCNAMELEN];
1516 if (!afsconf_SuperUser(tdir, acid, caller))
1517 return VOLSERBAD_ACCESS; /*not a super user */
1518 tt = FindTrans(atrans);
1521 if (tt->vflags & VTDeleted) {
1522 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1526 strcpy(tt->lastProcName, "SetStatus");
1527 tt->rxCallPtr = acid;
1530 tt->rxCallPtr = (struct rx_call *)0;
1535 td = &tv->header->diskstuff;
1537 * Add more fields as necessary
1539 if (astatus->maxquota != -1)
1540 td->maxquota = astatus->maxquota;
1541 if (astatus->dayUse != -1)
1542 td->dayUse = astatus->dayUse;
1543 if (astatus->creationDate != -1)
1544 td->creationDate = astatus->creationDate;
1545 if (astatus->updateDate != -1)
1546 td->updateDate = astatus->updateDate;
1547 if (astatus->spare2 != -1)
1548 td->volUpdateCounter = (unsigned int)astatus->spare2;
1549 VUpdateVolume(&error, tv);
1550 tt->rxCallPtr = (struct rx_call *)0;
1552 return VOLSERTRELE_ERROR;
1558 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1562 code = VolGetName(acid, atrans, aname);
1563 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1568 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1570 register struct Volume *tv;
1571 register struct VolumeDiskData *td;
1572 struct volser_trans *tt;
1576 tt = FindTrans(atrans);
1579 if (tt->vflags & VTDeleted) {
1580 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1584 strcpy(tt->lastProcName, "GetName");
1585 tt->rxCallPtr = acid;
1588 tt->rxCallPtr = (struct rx_call *)0;
1593 td = &tv->header->diskstuff;
1594 len = strlen(td->name) + 1; /* don't forget the null */
1596 tt->rxCallPtr = (struct rx_call *)0;
1600 *aname = (char *)malloc(len);
1601 strcpy(*aname, td->name);
1602 tt->rxCallPtr = (struct rx_call *)0;
1604 return VOLSERTRELE_ERROR;
1609 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1612 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1613 afs_int32 parentId, afs_int32 cloneId)
1619 /*return a list of all partitions on the server. The non mounted
1620 *partitions are returned as -1 in the corresponding slot in partIds*/
1622 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1626 code = VolListPartitions(acid, partIds);
1627 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1632 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1637 strcpy(namehead, "/vicep"); /*7 including null terminator */
1639 /* Just return attached partitions. */
1641 for (i = 0; i < 26; i++) {
1642 namehead[6] = i + 'a';
1643 if (VGetPartition(namehead, 0))
1644 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1650 /*return a list of all partitions on the server. The non mounted
1651 *partitions are returned as -1 in the corresponding slot in partIds*/
1653 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1657 code = XVolListPartitions(acid, pEntries);
1658 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1663 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1665 struct stat rbuf, pbuf;
1667 struct partList partList;
1668 struct DiskPartition *dp;
1671 strcpy(namehead, "/vicep"); /*7 including null terminator */
1673 /* Only report attached partitions */
1674 for (i = 0; i < VOLMAXPARTS; i++) {
1675 #ifdef AFS_DEMAND_ATTACH_FS
1676 dp = VGetPartitionById(i, 0);
1679 namehead[6] = i + 'a';
1683 namehead[6] = 'a' + (k / 26);
1684 namehead[7] = 'a' + (k % 26);
1687 dp = VGetPartition(namehead, 0);
1690 partList.partId[j++] = i;
1692 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1693 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1695 pEntries->partEntries_len = j;
1700 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1702 ExtractVolId(char vname[])
1705 char name[VOLSER_MAXVOLNAME + 1];
1707 strcpy(name, vname);
1709 while (name[i] == 'V' || name[i] == '0')
1712 name[11] = '\0'; /* smash the "." */
1713 return (atol(&name[i]));
1716 /*return the name of the next volume header in the directory associated with dirp and dp.
1717 *the volume id is returned in volid, and volume header name is returned in volname*/
1719 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1723 dp = readdir(dirp); /*read next entry in the directory */
1725 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1726 *volid = ExtractVolId(dp->d_name);
1727 strcpy(volname, dp->d_name);
1728 return 0; /*return the name of the file representing a volume */
1730 strcpy(volname, "");
1731 return 0; /*volname doesnot represent a volume */
1734 strcpy(volname, "EOD");
1735 return 0; /*end of directory */
1740 /*return the header information about the <volid> */
1742 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1743 volumeId, volEntries *volumeInfo)
1747 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
1748 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1753 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1754 volumeId, volEntries *volumeInfo)
1757 register struct Volume *tv;
1758 struct DiskPartition *partP;
1759 struct volser_trans *ttc;
1760 char pname[9], volname[20];
1761 afs_int32 error = 0;
1767 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
1768 pntr = volumeInfo->volEntries_val;
1769 volumeInfo->volEntries_len = 1;
1770 if (GetPartName(partid, pname))
1771 return VOLSERILLEGAL_PARTITION;
1772 if (!(partP = VGetPartition(pname, 0)))
1773 return VOLSERILLEGAL_PARTITION;
1774 dirp = opendir(VPartitionPath(partP));
1776 return VOLSERILLEGAL_PARTITION;
1777 strcpy(volname, "");
1778 ttc = (struct volser_trans *)0;
1779 tv = (Volume *) 0; /* volume not attached */
1781 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
1783 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
1784 GetNextVol(dirp, volname, &volid);
1785 continue; /*back to while loop */
1788 if (volid == volumeId) { /*copy other things too */
1790 #ifndef AFS_PTHREAD_ENV
1791 IOMGR_Poll(); /*make sure that the client doesnot time out */
1793 ttc = NewTrans(volid, partid);
1795 pntr->status = VBUSY;
1796 pntr->volid = volid;
1799 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
1801 pntr->status = 0; /*things are messed up */
1802 strcpy(pntr->name, volname);
1803 pntr->volid = volid;
1804 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
1807 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1808 /*this volume will be salvaged */
1810 strcpy(pntr->name, volname);
1811 pntr->volid = volid;
1812 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
1816 if (tv->header->diskstuff.needsSalvaged) {
1817 /*this volume will be salvaged */
1819 strcpy(pntr->name, volname);
1820 pntr->volid = volid;
1821 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
1825 /*read in the relevant info */
1826 pntr->status = VOK; /*its ok */
1827 pntr->volid = tv->header->diskstuff.id;
1828 strcpy(pntr->name, tv->header->diskstuff.name);
1829 pntr->type = tv->header->diskstuff.type; /*if ro volume */
1830 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
1831 pntr->backupID = tv->header->diskstuff.backupId;
1832 pntr->parentID = tv->header->diskstuff.parentId;
1833 pntr->copyDate = tv->header->diskstuff.copyDate;
1834 pntr->inUse = tv->header->diskstuff.inUse;
1835 pntr->size = tv->header->diskstuff.diskused;
1836 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1837 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1838 pntr->maxquota = tv->header->diskstuff.maxquota;
1839 pntr->filecount = tv->header->diskstuff.filecount;
1840 now = FT_ApproxTime();
1841 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1844 pntr->dayUse = tv->header->diskstuff.dayUse;
1845 pntr->creationDate = tv->header->diskstuff.creationDate;
1846 pntr->accessDate = tv->header->diskstuff.accessDate;
1847 pntr->updateDate = tv->header->diskstuff.updateDate;
1848 pntr->backupDate = tv->header->diskstuff.backupDate;
1849 pntr->spare0 = tv->header->diskstuff.minquota;
1851 (long)tv->header->diskstuff.weekUse[0] +
1852 (long)tv->header->diskstuff.weekUse[1] +
1853 (long)tv->header->diskstuff.weekUse[2] +
1854 (long)tv->header->diskstuff.weekUse[3] +
1855 (long)tv->header->diskstuff.weekUse[4] +
1856 (long)tv->header->diskstuff.weekUse[5] +
1857 (long)tv->header->diskstuff.weekUse[6];
1858 pntr->spare2 = V_volUpCounter(tv);
1859 pntr->flags = pntr->spare3 = (long)0;
1860 VDetachVolume(&error, tv); /*free the volume */
1863 pntr->status = 0; /*things are messed up */
1864 strcpy(pntr->name, volname);
1865 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
1870 GetNextVol(dirp, volname, &volid);
1874 VDetachVolume(&error, tv);
1878 DeleteTrans(ttc, 1);
1879 ttc = (struct volser_trans *)0;
1889 /*------------------------------------------------------------------------
1890 * EXPORTED SAFSVolXListOneVolume
1893 * Returns extended info on volume a_volID on partition a_partID.
1896 * a_rxCidP : Pointer to the Rx call we're performing.
1897 * a_partID : Partition for which we want the extended list.
1898 * a_volID : Volume ID we wish to know about.
1899 * a_volumeXInfoP : Ptr to the extended info blob.
1902 * 0 Successful operation
1903 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1906 * Nothing interesting.
1910 *------------------------------------------------------------------------*/
1913 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1914 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1918 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1919 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1924 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1925 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1926 { /*SAFSVolXListOneVolume */
1928 volintXInfo *xInfoP; /*Ptr to the extended vol info */
1929 register struct Volume *tv; /*Volume ptr */
1930 struct volser_trans *ttc; /*Volume transaction ptr */
1931 struct DiskPartition *partP; /*Ptr to partition */
1932 char pname[9], volname[20]; /*Partition, volume names */
1933 afs_int32 error; /*Error code */
1934 afs_int32 code; /*Return code */
1935 DIR *dirp; /*Partition directory ptr */
1936 afs_int32 currVolID; /*Current volume ID */
1937 int found = 0; /*Did we find the volume we need? */
1938 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
1939 int numStatBytes; /*Num stat bytes to copy per volume */
1943 * Set up our pointers for action, marking our structure to hold exactly
1944 * one entry. Also, assume we'll fail in our quest.
1946 a_volumeXInfoP->volXEntries_val =
1947 (volintXInfo *) malloc(sizeof(volintXInfo));
1948 xInfoP = a_volumeXInfoP->volXEntries_val;
1949 a_volumeXInfoP->volXEntries_len = 1;
1953 * If the partition name we've been given is bad, bogue out.
1955 if (GetPartName(a_partID, pname))
1956 return (VOLSERILLEGAL_PARTITION);
1959 * Open the directory representing the given AFS parttion. If we can't
1962 if (!(partP = VGetPartition(pname, 0)))
1963 return VOLSERILLEGAL_PARTITION;
1964 dirp = opendir(VPartitionPath(partP));
1966 return (VOLSERILLEGAL_PARTITION);
1969 * Sweep through the partition directory, looking for the desired entry.
1970 * First, of course, figure out how many stat bytes to copy out of each
1974 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1975 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1976 strcpy(volname, "");
1977 ttc = (struct volser_trans *)0; /*No transaction yet */
1978 tv = (Volume *) 0; /*Volume not yet attached */
1980 while (strcmp(volname, "EOD") && !found) {
1982 * If this is not a volume, move on to the next entry in the
1983 * partition's directory.
1985 if (!strcmp(volname, "")) {
1986 GetNextVol(dirp, volname, &currVolID);
1990 if (currVolID == a_volID) {
1992 * We found the volume entry we're interested. Pull out the
1993 * extended information, remembering to poll (so that the client
1994 * doesn't time out) and to set up a transaction on the volume.
1997 #ifndef AFS_PTHREAD_ENV
2000 ttc = NewTrans(currVolID, a_partID);
2003 * Couldn't get a transaction on this volume; let our caller
2006 xInfoP->status = VBUSY;
2007 xInfoP->volid = currVolID;
2012 * Attach the volume, give up on the volume if we can't.
2014 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2016 xInfoP->status = 0; /*things are messed up */
2017 strcpy(xInfoP->name, volname);
2018 xInfoP->volid = currVolID;
2019 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
2025 * Also bag out on this volume if it's been marked as needing a
2026 * salvage or to-be-destroyed.
2028 volDiskDataP = &(tv->header->diskstuff);
2029 if (volDiskDataP->destroyMe == DESTROY_ME) {
2031 strcpy(xInfoP->name, volname);
2032 xInfoP->volid = currVolID;
2033 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2037 if (volDiskDataP->needsSalvaged) {
2039 strcpy(xInfoP->name, volname);
2040 xInfoP->volid = currVolID;
2041 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
2046 * Pull out the desired info and stuff it into the area we'll be
2047 * returning to our caller.
2049 strcpy(xInfoP->name, volDiskDataP->name);
2050 xInfoP->volid = volDiskDataP->id;
2051 xInfoP->type = volDiskDataP->type;
2052 xInfoP->backupID = volDiskDataP->backupId;
2053 xInfoP->parentID = volDiskDataP->parentId;
2054 xInfoP->cloneID = volDiskDataP->cloneId;
2055 xInfoP->status = VOK;
2056 xInfoP->copyDate = volDiskDataP->copyDate;
2057 xInfoP->inUse = volDiskDataP->inUse;
2058 xInfoP->creationDate = volDiskDataP->creationDate;
2059 xInfoP->accessDate = volDiskDataP->accessDate;
2060 xInfoP->updateDate = volDiskDataP->updateDate;
2061 xInfoP->backupDate = volDiskDataP->backupDate;
2062 now = FT_ApproxTime();
2063 if (now - volDiskDataP->dayUseDate > OneDay)
2066 xInfoP->dayUse = volDiskDataP->dayUse;
2067 xInfoP->filecount = volDiskDataP->filecount;
2068 xInfoP->maxquota = volDiskDataP->maxquota;
2069 xInfoP->size = volDiskDataP->diskused;
2072 * Copy out the stat fields in a single operation.
2074 memcpy((char *)&(xInfoP->stat_reads[0]),
2075 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2078 * We're done copying. Detach the volume and iterate (at this
2079 * point, since we found our volume, we'll then drop out of the
2082 VDetachVolume(&error, tv);
2086 strcpy(xInfoP->name, volname);
2087 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2093 * At this point, we're golden.
2096 } /*Found desired volume */
2097 GetNextVol(dirp, volname, &currVolID);
2101 * Drop the transaction we have for this volume.
2105 VDetachVolume(&error, tv);
2109 DeleteTrans(ttc, 1);
2110 ttc = (struct volser_trans *)0;
2114 * Clean up before going to dinner: close the partition directory,
2115 * return the proper value.
2120 } /*SAFSVolXListOneVolume */
2122 /*returns all the volumes on partition partid. If flags = 1 then all the
2123 * relevant info about the volumes is also returned */
2125 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2126 volEntries *volumeInfo)
2130 code = VolListVolumes(acid, partid, flags, volumeInfo);
2131 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2136 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2137 volEntries *volumeInfo)
2140 register struct Volume *tv;
2141 struct DiskPartition *partP;
2142 struct volser_trans *ttc;
2143 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2144 char pname[9], volname[20];
2145 afs_int32 error = 0;
2150 volumeInfo->volEntries_val =
2151 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2152 pntr = volumeInfo->volEntries_val;
2153 volumeInfo->volEntries_len = 0;
2154 if (GetPartName(partid, pname))
2155 return VOLSERILLEGAL_PARTITION;
2156 if (!(partP = VGetPartition(pname, 0)))
2157 return VOLSERILLEGAL_PARTITION;
2158 dirp = opendir(VPartitionPath(partP));
2160 return VOLSERILLEGAL_PARTITION;
2161 strcpy(volname, "");
2162 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2163 ttc = (struct volser_trans *)0; /* new one for each pass */
2164 tv = (Volume *) 0; /* volume not attached */
2166 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2167 GetNextVol(dirp, volname, &volid);
2168 continue; /*back to while loop */
2171 if (flags) { /*copy other things too */
2172 #ifndef AFS_PTHREAD_ENV
2173 IOMGR_Poll(); /*make sure that the client doesnot time out */
2175 ttc = NewTrans(volid, partid);
2177 pntr->status = VBUSY;
2178 pntr->volid = volid;
2181 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2183 pntr->status = 0; /*things are messed up */
2184 strcpy(pntr->name, volname);
2185 pntr->volid = volid;
2186 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
2189 if (tv->header->diskstuff.needsSalvaged) {
2190 /*this volume will be salvaged */
2192 strcpy(pntr->name, volname);
2193 pntr->volid = volid;
2194 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
2198 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2199 /*this volume will be salvaged */
2202 /*read in the relevant info */
2203 pntr->status = VOK; /*its ok */
2204 pntr->volid = tv->header->diskstuff.id;
2205 strcpy(pntr->name, tv->header->diskstuff.name);
2206 pntr->type = tv->header->diskstuff.type; /*if ro volume */
2207 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
2208 pntr->backupID = tv->header->diskstuff.backupId;
2209 pntr->parentID = tv->header->diskstuff.parentId;
2210 pntr->copyDate = tv->header->diskstuff.copyDate;
2211 pntr->inUse = tv->header->diskstuff.inUse;
2212 pntr->size = tv->header->diskstuff.diskused;
2213 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2214 pntr->maxquota = tv->header->diskstuff.maxquota;
2215 pntr->filecount = tv->header->diskstuff.filecount;
2216 now = FT_ApproxTime();
2217 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2220 pntr->dayUse = tv->header->diskstuff.dayUse;
2221 pntr->creationDate = tv->header->diskstuff.creationDate;
2222 pntr->accessDate = tv->header->diskstuff.accessDate;
2223 pntr->updateDate = tv->header->diskstuff.updateDate;
2224 pntr->backupDate = tv->header->diskstuff.backupDate;
2225 pntr->spare0 = tv->header->diskstuff.minquota;
2227 (long)tv->header->diskstuff.weekUse[0] +
2228 (long)tv->header->diskstuff.weekUse[1] +
2229 (long)tv->header->diskstuff.weekUse[2] +
2230 (long)tv->header->diskstuff.weekUse[3] +
2231 (long)tv->header->diskstuff.weekUse[4] +
2232 (long)tv->header->diskstuff.weekUse[5] +
2233 (long)tv->header->diskstuff.weekUse[6];
2234 pntr->spare2 = V_volUpCounter(tv);
2235 pntr->flags = pntr->spare3 = (long)0;
2236 VDetachVolume(&error, tv); /*free the volume */
2239 pntr->status = 0; /*things are messed up */
2240 strcpy(pntr->name, volname);
2241 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2246 pntr->volid = volid;
2247 /*just volids are needed */
2252 DeleteTrans(ttc, 1);
2253 ttc = (struct volser_trans *)0;
2256 volumeInfo->volEntries_len += 1;
2257 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2258 /*running out of space, allocate more space */
2259 allocSize = (allocSize * 3) / 2;
2261 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2262 allocSize * sizeof(volintInfo));
2265 VDetachVolume(&error, tv);
2269 DeleteTrans(ttc, 1);
2270 ttc = (struct volser_trans *)0;
2273 return VOLSERNO_MEMORY;
2275 volumeInfo->volEntries_val = pntr; /* point to new block */
2276 /* set pntr to the right position */
2277 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2283 VDetachVolume(&error, tv);
2287 DeleteTrans(ttc, 1);
2288 ttc = (struct volser_trans *)0;
2290 GetNextVol(dirp, volname, &volid);
2295 DeleteTrans(ttc, 1);
2300 /*------------------------------------------------------------------------
2301 * EXPORTED SAFSVolXListVolumes
2304 * Returns all the volumes on partition a_partID. If a_flags
2305 * is set to 1, then all the relevant extended volume information
2309 * a_rxCidP : Pointer to the Rx call we're performing.
2310 * a_partID : Partition for which we want the extended list.
2311 * a_flags : Various flags.
2312 * a_volumeXInfoP : Ptr to the extended info blob.
2315 * 0 Successful operation
2316 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2317 * VOLSERNO_MEMORY if we ran out of memory allocating
2321 * Nothing interesting.
2325 *------------------------------------------------------------------------*/
2328 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2329 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2333 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2334 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2339 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2340 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2341 { /*SAFSVolXListVolumes */
2343 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2344 register struct Volume *tv; /*Volume ptr */
2345 struct DiskPartition *partP; /*Ptr to partition */
2346 struct volser_trans *ttc; /*Volume transaction ptr */
2347 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2348 char pname[9], volname[20]; /*Partition, volume names */
2349 afs_int32 error = 0; /*Return code */
2350 DIR *dirp; /*Partition directory ptr */
2351 afs_int32 volid; /*Current volume ID */
2352 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2353 int numStatBytes; /*Num stat bytes to copy per volume */
2357 * Allocate a large array of extended volume info structures, then
2358 * set it up for action.
2360 a_volumeXInfoP->volXEntries_val =
2361 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2362 xInfoP = a_volumeXInfoP->volXEntries_val;
2363 a_volumeXInfoP->volXEntries_len = 0;
2366 * If the partition name we've been given is bad, bogue out.
2368 if (GetPartName(a_partID, pname))
2369 return (VOLSERILLEGAL_PARTITION);
2372 * Open the directory representing the given AFS parttion. If we can't
2375 if (!(partP = VGetPartition(pname, 0)))
2376 return VOLSERILLEGAL_PARTITION;
2377 dirp = opendir(VPartitionPath(partP));
2379 return (VOLSERILLEGAL_PARTITION);
2382 * Sweep through the partition directory, acting on each entry. First,
2383 * of course, figure out how many stat bytes to copy out of each volume.
2386 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2387 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2388 strcpy(volname, "");
2389 while (strcmp(volname, "EOD")) {
2390 ttc = (struct volser_trans *)0; /*New one for each pass */
2391 tv = (Volume *) 0; /*Volume not yet attached */
2394 * If this is not a volume, move on to the next entry in the
2395 * partition's directory.
2397 if (!strcmp(volname, "")) {
2398 GetNextVol(dirp, volname, &volid);
2404 * Full info about the volume desired. Poll to make sure the
2405 * client doesn't time out, then start up a new transaction.
2407 #ifndef AFS_PTHREAD_ENV
2410 ttc = NewTrans(volid, a_partID);
2413 * Couldn't get a transaction on this volume; let our caller
2416 xInfoP->status = VBUSY;
2417 xInfoP->volid = volid;
2422 * Attach the volume, give up on this volume if we can't.
2424 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2426 xInfoP->status = 0; /*things are messed up */
2427 strcpy(xInfoP->name, volname);
2428 xInfoP->volid = volid;
2429 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2435 * Also bag out on this volume if it's been marked as needing a
2436 * salvage or to-be-destroyed.
2438 volDiskDataP = &(tv->header->diskstuff);
2439 if (volDiskDataP->needsSalvaged) {
2441 strcpy(xInfoP->name, volname);
2442 xInfoP->volid = volid;
2443 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
2447 if (volDiskDataP->destroyMe == DESTROY_ME)
2451 * Pull out the desired info and stuff it into the area we'll be
2452 * returning to our caller.
2454 strcpy(xInfoP->name, volDiskDataP->name);
2455 xInfoP->volid = volDiskDataP->id;
2456 xInfoP->type = volDiskDataP->type;
2457 xInfoP->backupID = volDiskDataP->backupId;
2458 xInfoP->parentID = volDiskDataP->parentId;
2459 xInfoP->cloneID = volDiskDataP->cloneId;
2460 xInfoP->status = VOK;
2461 xInfoP->copyDate = volDiskDataP->copyDate;
2462 xInfoP->inUse = volDiskDataP->inUse;
2463 xInfoP->creationDate = volDiskDataP->creationDate;
2464 xInfoP->accessDate = volDiskDataP->accessDate;
2465 xInfoP->updateDate = volDiskDataP->updateDate;
2466 xInfoP->backupDate = volDiskDataP->backupDate;
2467 now = FT_ApproxTime();
2468 if (now - volDiskDataP->dayUseDate > OneDay)
2471 xInfoP->dayUse = volDiskDataP->dayUse;
2472 xInfoP->filecount = volDiskDataP->filecount;
2473 xInfoP->maxquota = volDiskDataP->maxquota;
2474 xInfoP->size = volDiskDataP->diskused;
2477 * Copy out the stat fields in a single operation.
2479 memcpy((char *)&(xInfoP->stat_reads[0]),
2480 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2483 * We're done copying. Detach the volume and iterate.
2485 VDetachVolume(&error, tv);
2489 strcpy(xInfoP->name, volname);
2490 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2494 } /*Full contents desired */
2497 * Just volume IDs are needed.
2499 xInfoP->volid = volid;
2503 * Drop the transaction we have for this volume.
2506 DeleteTrans(ttc, 1);
2507 ttc = (struct volser_trans *)0;
2511 * Bump the pointer in the data area we're building, along with
2512 * the count of the number of entries it contains.
2515 (a_volumeXInfoP->volXEntries_len)++;
2516 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2518 * We're running out of space in the area we've built. Grow it.
2520 allocSize = (allocSize * 3) / 2;
2521 xInfoP = (volintXInfo *)
2522 realloc((char *)a_volumeXInfoP->volXEntries_val,
2523 (allocSize * sizeof(volintXInfo)));
2524 if (xInfoP == NULL) {
2526 * Bummer, no memory. Bag it, tell our caller what went wrong.
2529 VDetachVolume(&error, tv);
2533 DeleteTrans(ttc, 1);
2534 ttc = (struct volser_trans *)0;
2537 return (VOLSERNO_MEMORY);
2541 * Memory reallocation worked. Correct our pointers so they
2542 * now point to the new block and the current open position within
2545 a_volumeXInfoP->volXEntries_val = xInfoP;
2547 a_volumeXInfoP->volXEntries_val +
2548 a_volumeXInfoP->volXEntries_len;
2550 /*Need more space */
2553 * Detach our current volume and the transaction on it, then move on
2554 * to the next volume in the partition directory.
2557 VDetachVolume(&error, tv);
2561 DeleteTrans(ttc, 1);
2562 ttc = (struct volser_trans *)0;
2564 GetNextVol(dirp, volname, &volid);
2565 } /*Sweep through the partition directory */
2568 * We've examined all entries in the partition directory. Close it,
2569 * delete our transaction (if any), and go home happy.
2573 DeleteTrans(ttc, 1);
2576 } /*SAFSVolXListVolumes */
2578 /*this call is used to monitor the status of volser for debugging purposes.
2579 *information about all the active transactions is returned in transInfo*/
2581 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2585 code = VolMonitor(acid, transInfo);
2586 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2591 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2593 transDebugInfo *pntr;
2594 afs_int32 allocSize = 50;
2595 struct volser_trans *tt, *allTrans;
2597 transInfo->transDebugEntries_val =
2598 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2599 pntr = transInfo->transDebugEntries_val;
2600 transInfo->transDebugEntries_len = 0;
2601 allTrans = TransList();
2602 if (allTrans == (struct volser_trans *)0)
2603 return 0; /*no active transactions */
2604 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2605 pntr->tid = tt->tid;
2606 pntr->time = tt->time;
2607 pntr->creationTime = tt->creationTime;
2608 pntr->returnCode = tt->returnCode;
2609 pntr->volid = tt->volid;
2610 pntr->partition = tt->partition;
2611 pntr->iflags = tt->iflags;
2612 pntr->vflags = tt->vflags;
2613 pntr->tflags = tt->tflags;
2614 strcpy(pntr->lastProcName, tt->lastProcName);
2615 pntr->callValid = 0;
2616 if (tt->rxCallPtr) { /*record call related info */
2617 pntr->callValid = 1;
2618 pntr->readNext = tt->rxCallPtr->rnext;
2619 pntr->transmitNext = tt->rxCallPtr->tnext;
2620 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2621 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2624 transInfo->transDebugEntries_len += 1;
2625 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2626 allocSize = (allocSize * 3) / 2;
2628 (transDebugInfo *) realloc((char *)transInfo->
2629 transDebugEntries_val,
2631 sizeof(transDebugInfo));
2632 transInfo->transDebugEntries_val = pntr;
2634 transInfo->transDebugEntries_val +
2635 transInfo->transDebugEntries_len;
2636 /*set pntr to right position */
2645 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2649 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2650 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2651 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2657 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2660 afs_int32 error = 0;
2661 register struct volser_trans *tt;
2662 char caller[MAXKTCNAMELEN];
2664 if (strlen(name) > 31)
2665 return VOLSERBADNAME;
2666 if (!afsconf_SuperUser(tdir, acid, caller))
2667 return VOLSERBAD_ACCESS; /*not a super user */
2668 /* find the trans */
2669 tt = FindTrans(atid);
2672 if (tt->vflags & VTDeleted) {
2673 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2677 strcpy(tt->lastProcName, "SetIdsTypes");
2678 tt->rxCallPtr = acid;
2682 V_backupId(tv) = backupId;
2683 V_cloneId(tv) = cloneId;
2684 V_parentId(tv) = pId;
2685 strcpy((&V_disk(tv))->name, name);
2686 VUpdateVolume(&error, tv);
2688 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2692 tt->rxCallPtr = (struct rx_call *)0;
2693 if (TRELE(tt) && !error)
2694 return VOLSERTRELE_ERROR;
2698 tt->rxCallPtr = (struct rx_call *)0;
2699 if (TRELE(tt) && !error)
2700 return VOLSERTRELE_ERROR;
2705 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2709 code = VolSetDate(acid, atid, cdate);
2710 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2716 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2719 afs_int32 error = 0;
2720 register struct volser_trans *tt;
2721 char caller[MAXKTCNAMELEN];
2723 if (!afsconf_SuperUser(tdir, acid, caller))
2724 return VOLSERBAD_ACCESS; /*not a super user */
2725 /* find the trans */
2726 tt = FindTrans(atid);
2729 if (tt->vflags & VTDeleted) {
2730 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2734 strcpy(tt->lastProcName, "SetDate");
2735 tt->rxCallPtr = acid;
2738 V_creationDate(tv) = cdate;
2739 VUpdateVolume(&error, tv);
2741 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2745 tt->rxCallPtr = (struct rx_call *)0;
2746 if (TRELE(tt) && !error)
2747 return VOLSERTRELE_ERROR;
2751 tt->rxCallPtr = (struct rx_call *)0;
2752 if (TRELE(tt) && !error)
2753 return VOLSERTRELE_ERROR;
2757 #ifdef AFS_NAMEI_ENV
2759 * Inode number format (from namei_ops.c):
2760 * low 26 bits - vnode number - all 1's if volume special file.
2762 * next 3 bits spare (0's)
2763 * high 32 bits - uniquifier (regular) or type if spare
2765 #define NAMEI_VNODEMASK 0x003ffffff
2766 #define NAMEI_TAGMASK 0x7
2767 #define NAMEI_TAGSHIFT 26
2768 #define NAMEI_UNIQMASK 0xffffffff
2769 #define NAMEI_UNIQSHIFT 32
2770 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2771 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2772 #endif /* AFS_NAMEI_ENV */
2775 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2778 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2782 afs_int32 error = 0;
2785 char caller[MAXKTCNAMELEN];
2786 char headername[16];
2789 struct VolumeDiskHeader h;
2793 struct DiskPartition *dp;
2795 if (!afsconf_SuperUser(tdir, acid, caller))
2796 return VOLSERBAD_ACCESS; /*not a super user */
2797 if (GetPartName(partId, pname))
2798 return VOLSERILLEGAL_PARTITION;
2799 dirp = opendir(pname);
2801 return VOLSERILLEGAL_PARTITION;
2802 strcpy(volname, "");
2804 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2805 GetNextVol(dirp, volname, &volid);
2806 if (strcmp(volname, "")) { /* its a volume */
2807 if (volid == volumeId)
2813 (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
2814 (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
2815 fd = open(opath, O_RDONLY);
2817 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2820 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2821 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2826 FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
2828 for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
2831 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2834 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
2835 IH_INIT(ih, dp->device, h.parent, ino);
2837 error = namei_ConvertROtoRWvolume(ih, volumeId);
2841 h.volumeInfo_hi = h.id;
2842 h.smallVnodeIndex_hi = h.id;
2843 h.largeVnodeIndex_hi = h.id;
2844 h.linkTable_hi = h.id;
2845 (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
2846 (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
2847 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
2849 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
2852 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
2853 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
2858 if (unlink(opath) < 0) {
2859 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
2861 FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
2862 FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
2864 #else /* AFS_NAMEI_ENV */
2866 #endif /* AFS_NAMEI_ENV */
2870 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2871 register struct volintSize *size)
2874 register struct volser_trans *tt;
2875 char caller[MAXKTCNAMELEN];
2877 if (!afsconf_SuperUser(tdir, acid, caller))
2878 return VOLSERBAD_ACCESS; /*not a super user */
2879 tt = FindTrans(fromTrans);
2882 if (tt->vflags & VTDeleted) {
2886 strcpy(tt->lastProcName, "GetSize");
2887 tt->rxCallPtr = acid;
2888 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2889 tt->rxCallPtr = (struct rx_call *)0;
2891 return VOLSERTRELE_ERROR;
2893 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2897 /* GetPartName - map partid (a decimal number) into pname (a string)
2898 * Since for NT we actually want to return the drive name, we map through the
2902 GetPartName(afs_int32 partid, char *pname)
2907 strcpy(pname, "/vicep");
2908 pname[6] = 'a' + partid;
2911 } else if (partid < VOLMAXPARTS) {
2912 strcpy(pname, "/vicep");
2914 pname[6] = 'a' + (partid / 26);
2915 pname[7] = 'a' + (partid % 26);