2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <sys/types.h>
24 #include <netinet/in.h>
41 #include <afs/afsint.h>
43 #ifdef AFS_PTHREAD_ENV
45 #else /* AFS_PTHREAD_ENV */
46 #include <afs/assert.h>
47 #endif /* AFS_PTHREAD_ENV */
48 #include <afs/prs_fs.h>
53 #include <afs/cellconfig.h>
56 #include <afs/ihandle.h>
58 #include <afs/ntops.h>
60 #include <afs/vnode.h>
61 #include <afs/volume.h>
62 #include <afs/partition.h>
64 #include <afs/fssync.h>
66 #include "afs/audit.h"
72 #include <volser_prototypes.h>
75 extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
76 extern struct afsconf_dir *tdir;
77 extern char *volutil_PartitionName();
79 extern void LogError(afs_int32 errcode);
81 /* Forward declarations */
82 static int GetPartName(afs_int32 partid, char *pname);
84 #define OneDay (24*60*60)
90 afs_int32 localTid = 1;
91 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
92 VolDeleteVolume(), VolClone();
93 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
94 VolForward(), VolDump();
95 afs_int32 VolForwardMultiple();
96 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
97 VolSetInfo(), VolGetName();
98 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(),
99 VolXListOneVolume(), VolXListVolumes();
100 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
101 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
103 /* this call unlocks all of the partition locks we've set */
107 register struct DiskPartition *tp;
108 for (tp = DiskPartitionList; tp; tp = tp->next) {
109 if (tp->lock_fd != -1) {
110 close(tp->lock_fd); /* releases flock held on this partition */
117 /* get partition id from a name */
119 PartitionID(char *aname)
122 register int code = 0;
127 return -1; /* unknown */
129 /* otherwise check for vicepa or /vicepa, or just plain "a" */
131 if (!strncmp(aname, "/vicep", 6)) {
132 strncpy(ascii, aname + 6, 2);
134 return -1; /* bad partition name */
135 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
136 * from 0. Do the appropriate conversion */
138 /* one char name, 0..25 */
139 if (ascii[0] < 'a' || ascii[0] > 'z')
140 return -1; /* wrongo */
141 return ascii[0] - 'a';
143 /* two char name, 26 .. <whatever> */
144 if (ascii[0] < 'a' || ascii[0] > 'z')
145 return -1; /* wrongo */
146 if (ascii[1] < 'a' || ascii[1] > 'z')
147 return -1; /* just as bad */
148 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
149 if (code > VOLMAXPARTS)
156 ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
160 /* 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 */
161 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
166 ConvertPartition(int apartno, char *aname, int asize)
172 strcpy(aname, "/vicep");
174 aname[6] = 'a' + apartno;
178 aname[6] = 'a' + (apartno / 26);
179 aname[7] = 'a' + (apartno % 26);
185 /* the only attach function that takes a partition is "...ByName", so we use it */
187 XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
189 char pbuf[30], vbuf[20];
190 register struct Volume *tv;
192 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
196 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
200 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
204 /* Adapted from the file server; create a root directory for this volume */
206 ViceCreateRoot(Volume *vp)
209 struct acl_accessList *ACL;
211 Inode inodeNumber, nearInode;
212 char buf[SIZEOF_LARGEDISKVNODE];
213 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
214 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
220 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
222 V_pref(vp, nearInode);
224 IH_CREATE(V_linkHandle(vp), V_device(vp),
225 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
227 assert(VALID_INO(inodeNumber));
229 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
230 did.Volume = V_id(vp);
231 did.Vnode = (VnodeId) 1;
234 assert(!(MakeDir(&dir, &did, &did)));
235 DFlush(); /* flush all modified dir buffers out */
236 DZap(&dir); /* Remove all buffers for this dir */
237 length = Length(&dir); /* Remember size of this directory */
239 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
241 /* build a single entry ACL that gives all rights to system:administrators */
242 /* this section of code assumes that access list format is not going to
245 ACL = VVnodeDiskACL(vnode);
246 ACL->size = sizeof(struct acl_accessList);
247 ACL->version = ACL_ACLVERSION;
251 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
252 ACL->entries[0].rights =
253 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
254 | PRSFS_LOCK | PRSFS_ADMINISTER;
256 vnode->type = vDirectory;
258 vnode->modeBits = 0777;
259 vnode->linkCount = 2;
260 VNDISK_SET_LEN(vnode, length);
261 vnode->uniquifier = 1;
262 V_uniquifier(vp) = vnode->uniquifier + 1;
263 vnode->dataVersion = 1;
264 VNDISK_SET_INO(vnode, inodeNumber);
265 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
269 vnode->vnodeMagic = vcp->magic;
271 IH_INIT(h, vp->device, V_parentId(vp),
272 vp->vnodeIndex[vLarge].handle->ih_ino);
275 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
277 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
278 assert(code == SIZEOF_LARGEDISKVNODE);
279 FDH_REALLYCLOSE(fdP);
281 VNDISK_GET_LEN(length, vnode);
282 V_diskused(vp) = nBlocks(length);
288 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
293 code = VolPartitionInfo(acid, pname, partition);
294 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
299 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
302 register struct DiskPartition *dp;
305 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
308 dp = VGetPartition(pname, 0);
310 strncpy(partition->name, dp->name, 32);
311 strncpy(partition->devName, dp->devName, 32);
312 partition->lock_fd = dp->lock_fd;
313 partition->free = dp->free;
314 partition->minFree = dp->totalUsable;
317 return VOLSERILLEGAL_PARTITION;
320 /* obliterate a volume completely, and slowly. */
322 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
326 code = VolNukeVolume(acid, apartID, avolID);
327 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
332 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
337 register afs_int32 code;
339 char caller[MAXKTCNAMELEN];
341 /* check for access */
342 if (!afsconf_SuperUser(tdir, acid, caller))
343 return VOLSERBAD_ACCESS;
345 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
347 tp = volutil_PartitionName(apartID);
350 strcpy(partName, tp); /* remember it for later */
351 /* we first try to attach the volume in update mode, so that the file
352 * server doesn't try to use it (and abort) while (or after) we delete it.
353 * If we don't get the volume, that's fine, too. We just won't put it back.
355 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
356 code = nuke(partName, avolID);
358 VDetachVolume(&error, tvp);
362 /* create a new volume, with name aname, on the specified partition (1..n)
363 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
364 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
365 * for the volume id (useful for things like volume restore).
366 * Return the new volume id in *avolid.
369 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
370 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
376 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
377 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
378 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
384 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
385 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
390 afs_int32 junk; /* discardable error code */
391 register afs_int32 volumeID, doCreateRoot = 1;
392 register struct volser_trans *tt;
394 char caller[MAXKTCNAMELEN];
396 if (strlen(aname) > 31)
397 return VOLSERBADNAME;
398 if (!afsconf_SuperUser(tdir, acid, caller))
399 return VOLSERBAD_ACCESS;
401 Log("%s is executing CreateVolume '%s'\n", caller, aname);
402 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
403 return error; /*a standard unix error */
404 if (atype != readwriteVolume && atype != readonlyVolume
405 && atype != backupVolume)
407 if ((volumeID = *avolid) == 0) {
409 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
413 if ((aparent == volumeID) && (atype == readwriteVolume)) {
418 tt = NewTrans(volumeID, apart);
420 Log("1 createvolume: failed to create trans\n");
421 return VOLSERVOLBUSY; /* volume already busy! */
423 vp = VCreateVolume(&error, ppath, volumeID, aparent);
425 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
430 V_uniquifier(vp) = 1;
431 V_creationDate(vp) = V_copyDate(vp);
432 V_inService(vp) = V_blessed(vp) = 1;
434 AssignVolumeName(&V_disk(vp), aname, 0);
437 V_destroyMe(vp) = DESTROY_ME;
439 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
440 VUpdateVolume(&error, vp);
442 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
445 VDetachVolume(&junk, vp); /* rather return the real error code */
450 strcpy(tt->lastProcName, "CreateVolume");
451 tt->rxCallPtr = acid;
452 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
453 tt->rxCallPtr = (struct rx_call *)0;
455 return VOLSERTRELE_ERROR;
459 /* delete the volume associated with this transaction */
461 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
465 code = VolDeleteVolume(acid, atrans);
466 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
471 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
473 register struct volser_trans *tt;
475 char caller[MAXKTCNAMELEN];
477 if (!afsconf_SuperUser(tdir, acid, caller))
478 return VOLSERBAD_ACCESS;
479 tt = FindTrans(atrans);
482 if (tt->vflags & VTDeleted) {
483 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
488 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
489 strcpy(tt->lastProcName, "DeleteVolume");
490 tt->rxCallPtr = acid;
491 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
492 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
493 tt->rxCallPtr = (struct rx_call *)0;
495 return VOLSERTRELE_ERROR;
497 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
498 return 0; /* vpurgevolume doesn't set an error code */
501 /* make a clone of the volume associated with atrans, possibly giving it a new
502 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
503 * for the clone's id). The new clone is given the name newName. Finally, due to
504 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
505 * the clone operation. This may be useful when making new backup volumes, for instance
506 * since the net result of a clone and a purge generally leaves many inode ref counts
507 * the same, while doing them separately would result in far more iincs and idecs being
508 * peformed (and they are slow operations).
510 /* for efficiency reasons, sometimes faster to piggyback a purge here */
512 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
513 afs_int32 newType, char *newName, afs_int32 *newNumber)
517 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
518 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
519 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
525 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
526 afs_int32 newType, char *newName, afs_int32 *newNumber)
529 register struct Volume *originalvp, *purgevp, *newvp;
531 register struct volser_trans *tt, *ttc;
532 char caller[MAXKTCNAMELEN];
534 if (strlen(newName) > 31)
535 return VOLSERBADNAME;
536 if (!afsconf_SuperUser(tdir, acid, caller))
537 return VOLSERBAD_ACCESS; /*not a super user */
539 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
541 originalvp = (Volume *) 0;
542 purgevp = (Volume *) 0;
543 newvp = (Volume *) 0;
544 tt = ttc = (struct volser_trans *)0;
546 if (!newNumber || !*newNumber) {
547 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
552 if (newType != readonlyVolume && newType != backupVolume)
554 tt = FindTrans(atrans);
557 if (tt->vflags & VTDeleted) {
558 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
562 ttc = NewTrans(newId, tt->partition);
563 if (!ttc) { /* someone is messing with the clone already */
567 strcpy(tt->lastProcName, "Clone");
568 tt->rxCallPtr = acid;
572 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
574 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
580 originalvp = tt->volume;
581 if ((V_type(originalvp) == backupVolume)
582 || (V_type(originalvp) == readonlyVolume)) {
583 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
587 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
588 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
594 if (originalvp->device != purgevp->device) {
595 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
599 if (V_type(purgevp) != readonlyVolume) {
600 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
604 if (V_type(originalvp) == readonlyVolume
605 && V_parentId(originalvp) != V_parentId(purgevp)) {
606 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
610 if (V_type(originalvp) == readwriteVolume
611 && tt->volid != V_parentId(purgevp)) {
612 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
621 VCreateVolume(&error, originalvp->partition->name, newId,
622 V_parentId(originalvp));
624 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
625 newvp = (Volume *) 0;
628 if (newType == readonlyVolume)
629 V_cloneId(originalvp) = newId;
630 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
633 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
634 CloneVolume(&error, originalvp, newvp, purgevp);
635 purgevp = NULL; /* clone releases it, maybe even if error */
637 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
641 if (newType == readonlyVolume) {
642 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
643 V_type(newvp) = readonlyVolume;
644 } else if (newType == backupVolume) {
645 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
646 V_type(newvp) = backupVolume;
647 V_backupId(originalvp) = newId;
649 strcpy(newvp->header->diskstuff.name, newName);
650 V_creationDate(newvp) = V_copyDate(newvp);
651 ClearVolumeStats(&V_disk(newvp));
652 V_destroyMe(newvp) = DESTROY_ME;
653 V_inService(newvp) = 0;
654 if (newType == backupVolume) {
655 V_backupDate(originalvp) = V_copyDate(newvp);
656 V_backupDate(newvp) = V_copyDate(newvp);
659 VUpdateVolume(&error, newvp);
661 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
665 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
667 VUpdateVolume(&error, originalvp);
669 Log("1 Volser: Clone: original update %u\n", error);
673 tt->rxCallPtr = (struct rx_call *)0;
675 tt = (struct volser_trans *)0;
676 error = VOLSERTRELE_ERROR;
684 VDetachVolume(&code, purgevp);
686 VDetachVolume(&code, newvp);
688 tt->rxCallPtr = (struct rx_call *)0;
696 /* reclone this volume into the specified id */
698 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
702 code = VolReClone(acid, atrans, cloneId);
703 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
709 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
711 register struct Volume *originalvp, *clonevp;
714 register struct volser_trans *tt, *ttc;
715 char caller[MAXKTCNAMELEN];
717 /*not a super user */
718 if (!afsconf_SuperUser(tdir, acid, caller))
719 return VOLSERBAD_ACCESS;
721 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
723 clonevp = originalvp = (Volume *) 0;
724 tt = (struct volser_trans *)0;
726 tt = FindTrans(atrans);
729 if (tt->vflags & VTDeleted) {
730 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
734 ttc = NewTrans(cloneId, tt->partition);
735 if (!ttc) { /* someone is messing with the clone already */
739 strcpy(tt->lastProcName, "ReClone");
740 tt->rxCallPtr = acid;
742 originalvp = tt->volume;
743 if ((V_type(originalvp) == backupVolume)
744 || (V_type(originalvp) == readonlyVolume)) {
745 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
749 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
750 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
756 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
758 Log("1 Volser: can't attach clone %d\n", cloneId);
762 newType = V_type(clonevp); /* type of the new volume */
764 if (originalvp->device != clonevp->device) {
765 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
770 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
771 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
775 if (V_type(originalvp) == readonlyVolume
776 && V_parentId(originalvp) != V_parentId(clonevp)) {
777 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
781 if (V_type(originalvp) == readwriteVolume
782 && tt->volid != V_parentId(clonevp)) {
783 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
789 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
791 CloneVolume(&error, originalvp, clonevp, clonevp);
793 Log("1 Volser: Clone: reclone operation failed with code %d\n",
799 /* fix up volume name and type, CloneVolume just propagated RW's */
800 if (newType == readonlyVolume) {
801 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
802 V_type(clonevp) = readonlyVolume;
803 } else if (newType == backupVolume) {
804 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
805 V_type(clonevp) = backupVolume;
806 V_backupId(originalvp) = cloneId;
808 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
810 /* pretend recloned volume is a totally new instance */
811 V_copyDate(clonevp) = time(0);
812 V_creationDate(clonevp) = V_copyDate(clonevp);
813 ClearVolumeStats(&V_disk(clonevp));
814 V_destroyMe(clonevp) = 0;
815 V_inService(clonevp) = 0;
816 if (newType == backupVolume) {
817 V_backupDate(originalvp) = V_copyDate(clonevp);
818 V_backupDate(clonevp) = V_copyDate(clonevp);
820 V_inUse(clonevp) = 0;
821 VUpdateVolume(&error, clonevp);
823 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
827 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
829 VUpdateVolume(&error, originalvp);
831 Log("1 Volser: Clone: original update %u\n", error);
835 tt->rxCallPtr = (struct rx_call *)0;
837 tt = (struct volser_trans *)0;
838 error = VOLSERTRELE_ERROR;
845 struct DiskPartition *tpartp = originalvp->partition;
846 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
852 VDetachVolume(&code, clonevp);
854 tt->rxCallPtr = (struct rx_call *)0;
862 /* create a new transaction, associated with volume and partition. Type of
863 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
864 * See volser.h for definition of iflags (the constants are named IT*).
867 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
868 afs_int32 iflags, afs_int32 *ttid)
872 code = VolTransCreate(acid, volume, partition, iflags, ttid);
873 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
879 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
880 afs_int32 iflags, afs_int32 *ttid)
882 register struct volser_trans *tt;
884 afs_int32 error, code;
886 char caller[MAXKTCNAMELEN];
888 if (!afsconf_SuperUser(tdir, acid, caller))
889 return VOLSERBAD_ACCESS; /*not a super user */
890 if (iflags & ITCreate)
892 else if (iflags & ITBusy)
894 else if (iflags & ITReadOnly)
896 else if (iflags & ITOffline)
899 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
904 tt = NewTrans(volume, partition);
906 /* can't create a transaction? put the volume back */
907 Log("1 transcreate: can't create transaction\n");
908 return VOLSERVOLBUSY;
910 tv = XAttachVolume(&error, volume, partition, mode);
914 VDetachVolume(&code, tv);
922 strcpy(tt->lastProcName, "TransCreate");
924 return VOLSERTRELE_ERROR;
929 /* using aindex as a 0-based index, return the aindex'th volume on this server
930 * Both the volume number and partition number (one-based) are returned.
933 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
938 code = VolGetNthVolume(acid, aindex, avolume, apart);
939 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
944 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
947 Log("1 Volser: GetNthVolume: Not yet implemented\n");
951 /* return the volume flags (VT* constants in volser.h) associated with this
955 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
959 code = VolGetFlags(acid, atid, aflags);
960 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
965 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
967 register struct volser_trans *tt;
969 tt = FindTrans(atid);
972 if (tt->vflags & VTDeleted) {
973 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
978 strcpy(tt->lastProcName, "GetFlags");
979 tt->rxCallPtr = acid;
980 *aflags = tt->vflags;
981 tt->rxCallPtr = (struct rx_call *)0;
983 return VOLSERTRELE_ERROR;
988 /* Change the volume flags (VT* constants in volser.h) associated with this
989 * transaction. Effects take place immediately on volume, although volume
990 * remains attached as usual by the transaction.
993 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
997 code = VolSetFlags(acid, atid, aflags);
998 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1004 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1006 register struct volser_trans *tt;
1007 register struct Volume *vp;
1009 char caller[MAXKTCNAMELEN];
1011 if (!afsconf_SuperUser(tdir, acid, caller))
1012 return VOLSERBAD_ACCESS; /*not a super user */
1013 /* find the trans */
1014 tt = FindTrans(atid);
1017 if (tt->vflags & VTDeleted) {
1018 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1023 strcpy(tt->lastProcName, "SetFlags");
1024 tt->rxCallPtr = acid;
1025 vp = tt->volume; /* pull volume out of transaction */
1027 /* check if we're allowed to make any updates */
1028 if (tt->iflags & ITReadOnly) {
1033 /* handle delete-on-salvage flag */
1034 if (aflags & VTDeleteOnSalvage) {
1035 V_destroyMe(tt->volume) = DESTROY_ME;
1037 V_destroyMe(tt->volume) = 0;
1040 if (aflags & VTOutOfService) {
1041 V_inService(vp) = 0;
1043 V_inService(vp) = 1;
1045 VUpdateVolume(&error, vp);
1046 tt->vflags = aflags;
1047 tt->rxCallPtr = (struct rx_call *)0;
1048 if (TRELE(tt) && !error)
1049 return VOLSERTRELE_ERROR;
1054 /* dumpS the volume associated with a particular transaction from a particular
1055 * date. Send the dump to a different transaction (destTrans) on the server
1056 * specified by the destServer structure.
1059 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1060 struct destServer *destination, afs_int32 destTrans,
1061 struct restoreCookie *cookie)
1066 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1067 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1068 destination->destHost, AUD_LONG, destTrans, AUD_END);
1073 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1074 struct destServer *destination, afs_int32 destTrans,
1075 struct restoreCookie *cookie)
1077 register struct volser_trans *tt;
1078 register afs_int32 code;
1079 register struct rx_connection *tcon;
1080 struct rx_call *tcall;
1081 register struct Volume *vp;
1082 struct rx_securityClass *securityObject;
1083 afs_int32 securityIndex;
1084 char caller[MAXKTCNAMELEN];
1086 if (!afsconf_SuperUser(tdir, acid, caller))
1087 return VOLSERBAD_ACCESS; /*not a super user */
1088 /* initialize things */
1089 tcon = (struct rx_connection *)0;
1090 tt = (struct volser_trans *)0;
1092 /* find the local transaction */
1093 tt = FindTrans(fromTrans);
1096 if (tt->vflags & VTDeleted) {
1097 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1102 strcpy(tt->lastProcName, "Forward");
1104 /* get auth info for the this connection (uses afs from ticket file) */
1105 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1111 /* make an rpc connection to the other server */
1113 rx_NewConnection(htonl(destination->destHost),
1114 htons(destination->destPort), VOLSERVICE_ID,
1115 securityObject, securityIndex);
1117 tt->rxCallPtr = (struct rx_call *)0;
1121 tcall = rx_NewCall(tcon);
1122 tt->rxCallPtr = tcall;
1123 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1124 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1129 /* these next calls implictly call rx_Write when writing out data */
1130 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1133 EndAFSVolRestore(tcall); /* probably doesn't do much */
1134 tt->rxCallPtr = (struct rx_call *)0;
1135 code = rx_EndCall(tcall, 0);
1136 rx_DestroyConnection(tcon); /* done with the connection */
1141 return VOLSERTRELE_ERROR;
1147 (void)rx_EndCall(tcall, 0);
1148 rx_DestroyConnection(tcon);
1151 tt->rxCallPtr = (struct rx_call *)0;
1157 /* Start a dump and send it to multiple places simultaneously.
1158 * If this returns an error (eg, return ENOENT), it means that
1159 * none of the releases worked. If this returns 0, that means
1160 * that one or more of the releases worked, and the caller has
1161 * to examine the results array to see which one(s).
1162 * This will only do EITHER incremental or full, not both, so it's
1163 * the caller's responsibility to be sure that all the destinations
1164 * need just an incremental (and from the same time), if that's
1168 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1169 fromDate, manyDests *destinations, afs_int32 spare,
1170 struct restoreCookie *cookie, manyResults *results)
1172 afs_int32 securityIndex;
1173 struct rx_securityClass *securityObject;
1174 char caller[MAXKTCNAMELEN];
1175 struct volser_trans *tt;
1176 afs_int32 ec, code, *codes;
1177 struct rx_connection **tcons;
1178 struct rx_call **tcalls;
1180 int i, nconns, is_incremental;
1183 memset(results, 0, sizeof(manyResults));
1185 if (!afsconf_SuperUser(tdir, acid, caller))
1186 return VOLSERBAD_ACCESS; /*not a super user */
1187 tt = FindTrans(fromTrans);
1190 if (tt->vflags & VTDeleted) {
1191 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1196 strcpy(tt->lastProcName, "ForwardMulti");
1198 /* (fromDate == 0) ==> incremental dump */
1199 is_incremental = (fromDate ? 1 : 0);
1201 i = results->manyResults_len = destinations->manyDests_len;
1202 results->manyResults_val = codes =
1203 (afs_int32 *) malloc(i * sizeof(afs_int32));
1205 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1206 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1208 /* get auth info for this connection (uses afs from ticket file) */
1209 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1211 goto fail; /* in order to audit each failure */
1214 /* make connections to all the other servers */
1215 for (i = 0; i < destinations->manyDests_len; i++) {
1216 struct replica *dest = &(destinations->manyDests_val[i]);
1218 rx_NewConnection(htonl(dest->server.destHost),
1219 htons(dest->server.destPort), VOLSERVICE_ID,
1220 securityObject, securityIndex);
1222 codes[i] = ENOTCONN;
1224 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1225 codes[i] = ENOTCONN;
1228 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1231 (void)rx_EndCall(tcalls[i], 0);
1233 rx_DestroyConnection(tcons[i]);
1240 /* these next calls implictly call rx_Write when writing out data */
1241 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1245 for (i--; i >= 0; i--) {
1246 struct replica *dest = &(destinations->manyDests_val[i]);
1248 if (!code && tcalls[i] && !codes[i]) {
1249 EndAFSVolRestore(tcalls[i]);
1252 ec = rx_EndCall(tcalls[i], 0);
1257 rx_DestroyConnection(tcons[i]); /* done with the connection */
1260 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1261 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1262 dest->trans, AUD_END);
1268 tt->rxCallPtr = (struct rx_call *)0;
1269 if (TRELE(tt) && !code) /* return the first code if it's set */
1270 return VOLSERTRELE_ERROR;
1277 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1281 code = VolDump(acid, fromTrans, fromDate);
1282 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1287 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1290 register struct volser_trans *tt;
1291 char caller[MAXKTCNAMELEN];
1293 if (!afsconf_SuperUser(tdir, acid, caller))
1294 return VOLSERBAD_ACCESS; /*not a super user */
1295 tt = FindTrans(fromTrans);
1298 if (tt->vflags & VTDeleted) {
1299 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1303 strcpy(tt->lastProcName, "Dump");
1304 tt->rxCallPtr = acid;
1305 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1307 tt->rxCallPtr = (struct rx_call *)0;
1311 tt->rxCallPtr = (struct rx_call *)0;
1314 return VOLSERTRELE_ERROR;
1320 * Ha! No more helper process!
1323 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1324 struct restoreCookie *cookie)
1328 code = VolRestore(acid, atrans, aflags, cookie);
1329 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1334 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1335 struct restoreCookie *cookie)
1337 register struct volser_trans *tt;
1338 register afs_int32 code, tcode;
1339 char caller[MAXKTCNAMELEN];
1341 if (!afsconf_SuperUser(tdir, acid, caller))
1342 return VOLSERBAD_ACCESS; /*not a super user */
1343 tt = FindTrans(atrans);
1346 if (tt->vflags & VTDeleted) {
1347 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1351 strcpy(tt->lastProcName, "Restore");
1352 tt->rxCallPtr = acid;
1354 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1356 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1357 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l); /*break call backs on the
1358 * restored volume */
1359 tt->rxCallPtr = (struct rx_call *)0;
1362 return (code ? code : tcode);
1365 /* end a transaction, returning the transaction's final error code in rcode */
1367 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1371 code = VolEndTrans(acid, destTrans, rcode);
1372 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1377 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1379 register struct volser_trans *tt;
1380 char caller[MAXKTCNAMELEN];
1382 if (!afsconf_SuperUser(tdir, acid, caller))
1383 return VOLSERBAD_ACCESS; /*not a super user */
1384 tt = FindTrans(destTrans);
1388 *rcode = tt->returnCode;
1389 DeleteTrans(tt); /* this does an implicit TRELE */
1395 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1399 code = VolSetForwarding(acid, atid, anewsite);
1400 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1406 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1408 register struct volser_trans *tt;
1409 char caller[MAXKTCNAMELEN];
1411 if (!afsconf_SuperUser(tdir, acid, caller))
1412 return VOLSERBAD_ACCESS; /*not a super user */
1413 tt = FindTrans(atid);
1416 if (tt->vflags & VTDeleted) {
1417 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1422 strcpy(tt->lastProcName, "SetForwarding");
1423 tt->rxCallPtr = acid;
1424 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1425 tt->rxCallPtr = (struct rx_call *)0;
1427 return VOLSERTRELE_ERROR;
1433 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1434 register struct volser_status *astatus)
1438 code = VolGetStatus(acid, atrans, astatus);
1439 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1444 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1445 register struct volser_status *astatus)
1447 register struct Volume *tv;
1448 register struct VolumeDiskData *td;
1449 struct volser_trans *tt;
1452 tt = FindTrans(atrans);
1455 if (tt->vflags & VTDeleted) {
1456 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1461 strcpy(tt->lastProcName, "GetStatus");
1462 tt->rxCallPtr = acid;
1465 tt->rxCallPtr = (struct rx_call *)0;
1470 td = &tv->header->diskstuff;
1471 astatus->volID = td->id;
1472 astatus->nextUnique = td->uniquifier;
1473 astatus->type = td->type;
1474 astatus->parentID = td->parentId;
1475 astatus->cloneID = td->cloneId;
1476 astatus->backupID = td->backupId;
1477 astatus->restoredFromID = td->restoredFromId;
1478 astatus->maxQuota = td->maxquota;
1479 astatus->minQuota = td->minquota;
1480 astatus->owner = td->owner;
1481 astatus->creationDate = td->creationDate;
1482 astatus->accessDate = td->accessDate;
1483 astatus->updateDate = td->updateDate;
1484 astatus->expirationDate = td->expirationDate;
1485 astatus->backupDate = td->backupDate;
1486 astatus->copyDate = td->copyDate;
1487 tt->rxCallPtr = (struct rx_call *)0;
1489 return VOLSERTRELE_ERROR;
1495 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1496 register struct volintInfo *astatus)
1500 code = VolSetInfo(acid, atrans, astatus);
1501 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1506 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1507 register struct volintInfo *astatus)
1509 register struct Volume *tv;
1510 register struct VolumeDiskData *td;
1511 struct volser_trans *tt;
1512 char caller[MAXKTCNAMELEN];
1515 if (!afsconf_SuperUser(tdir, acid, caller))
1516 return VOLSERBAD_ACCESS; /*not a super user */
1517 tt = FindTrans(atrans);
1520 if (tt->vflags & VTDeleted) {
1521 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1525 strcpy(tt->lastProcName, "SetStatus");
1526 tt->rxCallPtr = acid;
1529 tt->rxCallPtr = (struct rx_call *)0;
1534 td = &tv->header->diskstuff;
1536 * Add more fields as necessary
1538 if (astatus->maxquota != -1)
1539 td->maxquota = astatus->maxquota;
1540 if (astatus->dayUse != -1)
1541 td->dayUse = astatus->dayUse;
1542 VUpdateVolume(&error, tv);
1543 tt->rxCallPtr = (struct rx_call *)0;
1545 return VOLSERTRELE_ERROR;
1551 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1555 code = VolGetName(acid, atrans, aname);
1556 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1561 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1563 register struct Volume *tv;
1564 register struct VolumeDiskData *td;
1565 struct volser_trans *tt;
1569 tt = FindTrans(atrans);
1572 if (tt->vflags & VTDeleted) {
1573 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1577 strcpy(tt->lastProcName, "GetName");
1578 tt->rxCallPtr = acid;
1581 tt->rxCallPtr = (struct rx_call *)0;
1586 td = &tv->header->diskstuff;
1587 len = strlen(td->name) + 1; /* don't forget the null */
1589 tt->rxCallPtr = (struct rx_call *)0;
1593 *aname = (char *)malloc(len);
1594 strcpy(*aname, td->name);
1595 tt->rxCallPtr = (struct rx_call *)0;
1597 return VOLSERTRELE_ERROR;
1602 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1605 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1606 afs_int32 parentId, afs_int32 cloneId)
1612 /*return a list of all partitions on the server. The non mounted
1613 *partitions are returned as -1 in the corresponding slot in partIds*/
1615 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1619 code = VolListPartitions(acid, partIds);
1620 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1625 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1631 strcpy(namehead, "/vicep"); /*7 including null terminator */
1633 /* Just return attached partitions. */
1635 for (i = 0; i < 26; i++) {
1636 namehead[6] = i + 'a';
1637 if (VGetPartition(namehead, 0))
1638 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1644 /*return a list of all partitions on the server. The non mounted
1645 *partitions are returned as -1 in the corresponding slot in partIds*/
1647 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1651 code = XVolListPartitions(acid, pEntries);
1652 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1657 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1659 struct stat rbuf, pbuf;
1661 struct partList partList;
1662 struct DiskPartition *dp;
1665 strcpy(namehead, "/vicep"); /*7 including null terminator */
1667 /* Only report attached partitions */
1668 for (i = 0; i < VOLMAXPARTS; i++) {
1670 namehead[6] = i + 'a';
1674 namehead[6] = 'a' + (k / 26);
1675 namehead[7] = 'a' + (k % 26);
1678 dp = VGetPartition(namehead, 0);
1680 partList.partId[j++] = i;
1682 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1683 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1685 pEntries->partEntries_len = j;
1690 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1692 ExtractVolId(char vname[])
1695 char name[VOLSER_MAXVOLNAME + 1];
1697 strcpy(name, vname);
1699 while (name[i] == 'V' || name[i] == '0')
1702 name[11] = '\0'; /* smash the "." */
1703 return (atol(&name[i]));
1706 /*return the name of the next volume header in the directory associated with dirp and dp.
1707 *the volume id is returned in volid, and volume header name is returned in volname*/
1709 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1713 dp = readdir(dirp); /*read next entry in the directory */
1715 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1716 *volid = ExtractVolId(dp->d_name);
1717 strcpy(volname, dp->d_name);
1718 return 0; /*return the name of the file representing a volume */
1720 strcpy(volname, "");
1721 return 0; /*volname doesnot represent a volume */
1724 strcpy(volname, "EOD");
1725 return 0; /*end of directory */
1730 /*return the header information about the <volid> */
1732 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1733 volumeId, volEntries *volumeInfo)
1737 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
1738 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1743 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
1744 volumeId, volEntries *volumeInfo)
1747 register struct Volume *tv;
1748 struct DiskPartition *partP;
1749 struct volser_trans *ttc;
1750 char pname[9], volname[20];
1751 afs_int32 error = 0;
1757 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
1758 pntr = volumeInfo->volEntries_val;
1759 volumeInfo->volEntries_len = 1;
1760 if (GetPartName(partid, pname))
1761 return VOLSERILLEGAL_PARTITION;
1762 if (!(partP = VGetPartition(pname, 0)))
1763 return VOLSERILLEGAL_PARTITION;
1764 dirp = opendir(VPartitionPath(partP));
1766 return VOLSERILLEGAL_PARTITION;
1767 strcpy(volname, "");
1768 ttc = (struct volser_trans *)0;
1769 tv = (Volume *) 0; /* volume not attached */
1771 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
1773 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
1774 GetNextVol(dirp, volname, &volid);
1775 continue; /*back to while loop */
1778 if (volid == volumeId) { /*copy other things too */
1780 #ifndef AFS_PTHREAD_ENV
1781 IOMGR_Poll(); /*make sure that the client doesnot time out */
1783 ttc = NewTrans(volid, partid);
1785 pntr->status = VBUSY;
1786 pntr->volid = volid;
1789 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1791 pntr->status = 0; /*things are messed up */
1792 strcpy(pntr->name, volname);
1793 pntr->volid = volid;
1794 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
1797 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1798 /*this volume will be salvaged */
1800 strcpy(pntr->name, volname);
1801 pntr->volid = volid;
1802 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
1806 if (tv->header->diskstuff.needsSalvaged) {
1807 /*this volume will be salvaged */
1809 strcpy(pntr->name, volname);
1810 pntr->volid = volid;
1811 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
1815 /*read in the relevant info */
1816 pntr->status = VOK; /*its ok */
1817 pntr->volid = tv->header->diskstuff.id;
1818 strcpy(pntr->name, tv->header->diskstuff.name);
1819 pntr->type = tv->header->diskstuff.type; /*if ro volume */
1820 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
1821 pntr->backupID = tv->header->diskstuff.backupId;
1822 pntr->parentID = tv->header->diskstuff.parentId;
1823 pntr->copyDate = tv->header->diskstuff.copyDate;
1824 pntr->inUse = tv->header->diskstuff.inUse;
1825 pntr->size = tv->header->diskstuff.diskused;
1826 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1827 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1828 pntr->maxquota = tv->header->diskstuff.maxquota;
1829 pntr->filecount = tv->header->diskstuff.filecount;
1830 now = FT_ApproxTime();
1831 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1834 pntr->dayUse = tv->header->diskstuff.dayUse;
1835 pntr->creationDate = tv->header->diskstuff.creationDate;
1836 pntr->accessDate = tv->header->diskstuff.accessDate;
1837 pntr->updateDate = tv->header->diskstuff.updateDate;
1838 pntr->backupDate = tv->header->diskstuff.backupDate;
1839 pntr->spare0 = tv->header->diskstuff.minquota;
1841 (long)tv->header->diskstuff.weekUse[0] +
1842 (long)tv->header->diskstuff.weekUse[1] +
1843 (long)tv->header->diskstuff.weekUse[2] +
1844 (long)tv->header->diskstuff.weekUse[3] +
1845 (long)tv->header->diskstuff.weekUse[4] +
1846 (long)tv->header->diskstuff.weekUse[5] +
1847 (long)tv->header->diskstuff.weekUse[6];
1848 pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
1849 VDetachVolume(&error, tv); /*free the volume */
1852 pntr->status = 0; /*things are messed up */
1853 strcpy(pntr->name, volname);
1854 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
1859 GetNextVol(dirp, volname, &volid);
1863 VDetachVolume(&error, tv);
1868 ttc = (struct volser_trans *)0;
1878 /*------------------------------------------------------------------------
1879 * EXPORTED SAFSVolXListOneVolume
1882 * Returns extended info on volume a_volID on partition a_partID.
1885 * a_rxCidP : Pointer to the Rx call we're performing.
1886 * a_partID : Partition for which we want the extended list.
1887 * a_volID : Volume ID we wish to know about.
1888 * a_volumeXInfoP : Ptr to the extended info blob.
1891 * 0 Successful operation
1892 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1895 * Nothing interesting.
1899 *------------------------------------------------------------------------*/
1902 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1903 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1907 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1908 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1913 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
1914 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
1915 { /*SAFSVolXListOneVolume */
1917 volintXInfo *xInfoP; /*Ptr to the extended vol info */
1918 register struct Volume *tv; /*Volume ptr */
1919 struct volser_trans *ttc; /*Volume transaction ptr */
1920 struct DiskPartition *partP; /*Ptr to partition */
1921 char pname[9], volname[20]; /*Partition, volume names */
1922 afs_int32 error; /*Error code */
1923 afs_int32 code; /*Return code */
1924 DIR *dirp; /*Partition directory ptr */
1925 afs_int32 currVolID; /*Current volume ID */
1926 int found = 0; /*Did we find the volume we need? */
1927 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
1928 int numStatBytes; /*Num stat bytes to copy per volume */
1932 * Set up our pointers for action, marking our structure to hold exactly
1933 * one entry. Also, assume we'll fail in our quest.
1935 a_volumeXInfoP->volXEntries_val =
1936 (volintXInfo *) malloc(sizeof(volintXInfo));
1937 xInfoP = a_volumeXInfoP->volXEntries_val;
1938 a_volumeXInfoP->volXEntries_len = 1;
1942 * If the partition name we've been given is bad, bogue out.
1944 if (GetPartName(a_partID, pname))
1945 return (VOLSERILLEGAL_PARTITION);
1948 * Open the directory representing the given AFS parttion. If we can't
1951 if (!(partP = VGetPartition(pname, 0)))
1952 return VOLSERILLEGAL_PARTITION;
1953 dirp = opendir(VPartitionPath(partP));
1955 return (VOLSERILLEGAL_PARTITION);
1958 * Sweep through the partition directory, looking for the desired entry.
1959 * First, of course, figure out how many stat bytes to copy out of each
1963 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1964 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1965 strcpy(volname, "");
1966 ttc = (struct volser_trans *)0; /*No transaction yet */
1967 tv = (Volume *) 0; /*Volume not yet attached */
1969 while (strcmp(volname, "EOD") && !found) {
1971 * If this is not a volume, move on to the next entry in the
1972 * partition's directory.
1974 if (!strcmp(volname, "")) {
1975 GetNextVol(dirp, volname, &currVolID);
1979 if (currVolID == a_volID) {
1981 * We found the volume entry we're interested. Pull out the
1982 * extended information, remembering to poll (so that the client
1983 * doesn't time out) and to set up a transaction on the volume.
1986 #ifndef AFS_PTHREAD_ENV
1989 ttc = NewTrans(currVolID, a_partID);
1992 * Couldn't get a transaction on this volume; let our caller
1995 xInfoP->status = VBUSY;
1996 xInfoP->volid = currVolID;
2001 * Attach the volume, give up on the volume if we can't.
2003 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2005 xInfoP->status = 0; /*things are messed up */
2006 strcpy(xInfoP->name, volname);
2007 xInfoP->volid = currVolID;
2008 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
2014 * Also bag out on this volume if it's been marked as needing a
2015 * salvage or to-be-destroyed.
2017 volDiskDataP = &(tv->header->diskstuff);
2018 if (volDiskDataP->destroyMe == DESTROY_ME) {
2020 strcpy(xInfoP->name, volname);
2021 xInfoP->volid = currVolID;
2022 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2026 if (volDiskDataP->needsSalvaged) {
2028 strcpy(xInfoP->name, volname);
2029 xInfoP->volid = currVolID;
2030 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
2035 * Pull out the desired info and stuff it into the area we'll be
2036 * returning to our caller.
2038 strcpy(xInfoP->name, volDiskDataP->name);
2039 xInfoP->volid = volDiskDataP->id;
2040 xInfoP->type = volDiskDataP->type;
2041 xInfoP->backupID = volDiskDataP->backupId;
2042 xInfoP->parentID = volDiskDataP->parentId;
2043 xInfoP->cloneID = volDiskDataP->cloneId;
2044 xInfoP->status = VOK;
2045 xInfoP->copyDate = volDiskDataP->copyDate;
2046 xInfoP->inUse = volDiskDataP->inUse;
2047 xInfoP->creationDate = volDiskDataP->creationDate;
2048 xInfoP->accessDate = volDiskDataP->accessDate;
2049 xInfoP->updateDate = volDiskDataP->updateDate;
2050 xInfoP->backupDate = volDiskDataP->backupDate;
2051 now = FT_ApproxTime();
2052 if (now - volDiskDataP->dayUseDate > OneDay)
2055 xInfoP->dayUse = volDiskDataP->dayUse;
2056 xInfoP->filecount = volDiskDataP->filecount;
2057 xInfoP->maxquota = volDiskDataP->maxquota;
2058 xInfoP->size = volDiskDataP->diskused;
2061 * Copy out the stat fields in a single operation.
2063 memcpy((char *)&(xInfoP->stat_reads[0]),
2064 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2067 * We're done copying. Detach the volume and iterate (at this
2068 * point, since we found our volume, we'll then drop out of the
2071 VDetachVolume(&error, tv);
2075 strcpy(xInfoP->name, volname);
2076 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2082 * At this point, we're golden.
2085 } /*Found desired volume */
2086 GetNextVol(dirp, volname, &currVolID);
2090 * Drop the transaction we have for this volume.
2094 VDetachVolume(&error, tv);
2099 ttc = (struct volser_trans *)0;
2103 * Clean up before going to dinner: close the partition directory,
2104 * return the proper value.
2109 } /*SAFSVolXListOneVolume */
2111 /*returns all the volumes on partition partid. If flags = 1 then all the
2112 * relevant info about the volumes is also returned */
2114 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2115 volEntries *volumeInfo)
2119 code = VolListVolumes(acid, partid, flags, volumeInfo);
2120 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2125 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2126 volEntries *volumeInfo)
2129 register struct Volume *tv;
2130 struct DiskPartition *partP;
2131 struct volser_trans *ttc;
2132 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2133 char pname[9], volname[20];
2134 afs_int32 error = 0;
2139 volumeInfo->volEntries_val =
2140 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2141 pntr = volumeInfo->volEntries_val;
2142 volumeInfo->volEntries_len = 0;
2143 if (GetPartName(partid, pname))
2144 return VOLSERILLEGAL_PARTITION;
2145 if (!(partP = VGetPartition(pname, 0)))
2146 return VOLSERILLEGAL_PARTITION;
2147 dirp = opendir(VPartitionPath(partP));
2149 return VOLSERILLEGAL_PARTITION;
2150 strcpy(volname, "");
2151 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2152 ttc = (struct volser_trans *)0; /* new one for each pass */
2153 tv = (Volume *) 0; /* volume not attached */
2155 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2156 GetNextVol(dirp, volname, &volid);
2157 continue; /*back to while loop */
2160 if (flags) { /*copy other things too */
2161 #ifndef AFS_PTHREAD_ENV
2162 IOMGR_Poll(); /*make sure that the client doesnot time out */
2164 ttc = NewTrans(volid, partid);
2166 pntr->status = VBUSY;
2167 pntr->volid = volid;
2170 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2172 pntr->status = 0; /*things are messed up */
2173 strcpy(pntr->name, volname);
2174 pntr->volid = volid;
2175 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
2178 if (tv->header->diskstuff.needsSalvaged) {
2179 /*this volume will be salvaged */
2181 strcpy(pntr->name, volname);
2182 pntr->volid = volid;
2183 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
2187 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2188 /*this volume will be salvaged */
2191 /*read in the relevant info */
2192 pntr->status = VOK; /*its ok */
2193 pntr->volid = tv->header->diskstuff.id;
2194 strcpy(pntr->name, tv->header->diskstuff.name);
2195 pntr->type = tv->header->diskstuff.type; /*if ro volume */
2196 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
2197 pntr->backupID = tv->header->diskstuff.backupId;
2198 pntr->parentID = tv->header->diskstuff.parentId;
2199 pntr->copyDate = tv->header->diskstuff.copyDate;
2200 pntr->inUse = tv->header->diskstuff.inUse;
2201 pntr->size = tv->header->diskstuff.diskused;
2202 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2203 pntr->maxquota = tv->header->diskstuff.maxquota;
2204 pntr->filecount = tv->header->diskstuff.filecount;
2205 now = FT_ApproxTime();
2206 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2209 pntr->dayUse = tv->header->diskstuff.dayUse;
2210 pntr->creationDate = tv->header->diskstuff.creationDate;
2211 pntr->accessDate = tv->header->diskstuff.accessDate;
2212 pntr->updateDate = tv->header->diskstuff.updateDate;
2213 pntr->backupDate = tv->header->diskstuff.backupDate;
2214 pntr->spare0 = tv->header->diskstuff.minquota;
2216 (long)tv->header->diskstuff.weekUse[0] +
2217 (long)tv->header->diskstuff.weekUse[1] +
2218 (long)tv->header->diskstuff.weekUse[2] +
2219 (long)tv->header->diskstuff.weekUse[3] +
2220 (long)tv->header->diskstuff.weekUse[4] +
2221 (long)tv->header->diskstuff.weekUse[5] +
2222 (long)tv->header->diskstuff.weekUse[6];
2223 pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
2224 VDetachVolume(&error, tv); /*free the volume */
2227 pntr->status = 0; /*things are messed up */
2228 strcpy(pntr->name, volname);
2229 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2234 pntr->volid = volid;
2235 /*just volids are needed */
2241 ttc = (struct volser_trans *)0;
2244 volumeInfo->volEntries_len += 1;
2245 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2246 /*running out of space, allocate more space */
2247 allocSize = (allocSize * 3) / 2;
2249 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2250 allocSize * sizeof(volintInfo));
2253 VDetachVolume(&error, tv);
2258 ttc = (struct volser_trans *)0;
2261 return VOLSERNO_MEMORY;
2263 volumeInfo->volEntries_val = pntr; /* point to new block */
2264 /* set pntr to the right position */
2265 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2271 VDetachVolume(&error, tv);
2276 ttc = (struct volser_trans *)0;
2278 GetNextVol(dirp, volname, &volid);
2288 /*------------------------------------------------------------------------
2289 * EXPORTED SAFSVolXListVolumes
2292 * Returns all the volumes on partition a_partID. If a_flags
2293 * is set to 1, then all the relevant extended volume information
2297 * a_rxCidP : Pointer to the Rx call we're performing.
2298 * a_partID : Partition for which we want the extended list.
2299 * a_flags : Various flags.
2300 * a_volumeXInfoP : Ptr to the extended info blob.
2303 * 0 Successful operation
2304 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2305 * VOLSERNO_MEMORY if we ran out of memory allocating
2309 * Nothing interesting.
2313 *------------------------------------------------------------------------*/
2316 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2317 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2321 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2322 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2327 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2328 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2329 { /*SAFSVolXListVolumes */
2331 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2332 register struct Volume *tv; /*Volume ptr */
2333 struct DiskPartition *partP; /*Ptr to partition */
2334 struct volser_trans *ttc; /*Volume transaction ptr */
2335 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2336 char pname[9], volname[20]; /*Partition, volume names */
2337 afs_int32 error = 0; /*Return code */
2338 DIR *dirp; /*Partition directory ptr */
2339 afs_int32 volid; /*Current volume ID */
2340 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2341 int numStatBytes; /*Num stat bytes to copy per volume */
2345 * Allocate a large array of extended volume info structures, then
2346 * set it up for action.
2348 a_volumeXInfoP->volXEntries_val =
2349 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2350 xInfoP = a_volumeXInfoP->volXEntries_val;
2351 a_volumeXInfoP->volXEntries_len = 0;
2354 * If the partition name we've been given is bad, bogue out.
2356 if (GetPartName(a_partID, pname))
2357 return (VOLSERILLEGAL_PARTITION);
2360 * Open the directory representing the given AFS parttion. If we can't
2363 if (!(partP = VGetPartition(pname, 0)))
2364 return VOLSERILLEGAL_PARTITION;
2365 dirp = opendir(VPartitionPath(partP));
2367 return (VOLSERILLEGAL_PARTITION);
2370 * Sweep through the partition directory, acting on each entry. First,
2371 * of course, figure out how many stat bytes to copy out of each volume.
2374 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2375 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2376 strcpy(volname, "");
2377 while (strcmp(volname, "EOD")) {
2378 ttc = (struct volser_trans *)0; /*New one for each pass */
2379 tv = (Volume *) 0; /*Volume not yet attached */
2382 * If this is not a volume, move on to the next entry in the
2383 * partition's directory.
2385 if (!strcmp(volname, "")) {
2386 GetNextVol(dirp, volname, &volid);
2392 * Full info about the volume desired. Poll to make sure the
2393 * client doesn't time out, then start up a new transaction.
2395 #ifndef AFS_PTHREAD_ENV
2398 ttc = NewTrans(volid, a_partID);
2401 * Couldn't get a transaction on this volume; let our caller
2404 xInfoP->status = VBUSY;
2405 xInfoP->volid = volid;
2410 * Attach the volume, give up on this volume if we can't.
2412 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2414 xInfoP->status = 0; /*things are messed up */
2415 strcpy(xInfoP->name, volname);
2416 xInfoP->volid = volid;
2417 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2423 * Also bag out on this volume if it's been marked as needing a
2424 * salvage or to-be-destroyed.
2426 volDiskDataP = &(tv->header->diskstuff);
2427 if (volDiskDataP->needsSalvaged) {
2429 strcpy(xInfoP->name, volname);
2430 xInfoP->volid = volid;
2431 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
2435 if (volDiskDataP->destroyMe == DESTROY_ME)
2439 * Pull out the desired info and stuff it into the area we'll be
2440 * returning to our caller.
2442 strcpy(xInfoP->name, volDiskDataP->name);
2443 xInfoP->volid = volDiskDataP->id;
2444 xInfoP->type = volDiskDataP->type;
2445 xInfoP->backupID = volDiskDataP->backupId;
2446 xInfoP->parentID = volDiskDataP->parentId;
2447 xInfoP->cloneID = volDiskDataP->cloneId;
2448 xInfoP->status = VOK;
2449 xInfoP->copyDate = volDiskDataP->copyDate;
2450 xInfoP->inUse = volDiskDataP->inUse;
2451 xInfoP->creationDate = volDiskDataP->creationDate;
2452 xInfoP->accessDate = volDiskDataP->accessDate;
2453 xInfoP->updateDate = volDiskDataP->updateDate;
2454 xInfoP->backupDate = volDiskDataP->backupDate;
2455 now = FT_ApproxTime();
2456 if (now - volDiskDataP->dayUseDate > OneDay)
2459 xInfoP->dayUse = volDiskDataP->dayUse;
2460 xInfoP->filecount = volDiskDataP->filecount;
2461 xInfoP->maxquota = volDiskDataP->maxquota;
2462 xInfoP->size = volDiskDataP->diskused;
2465 * Copy out the stat fields in a single operation.
2467 memcpy((char *)&(xInfoP->stat_reads[0]),
2468 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2471 * We're done copying. Detach the volume and iterate.
2473 VDetachVolume(&error, tv);
2477 strcpy(xInfoP->name, volname);
2478 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2482 } /*Full contents desired */
2485 * Just volume IDs are needed.
2487 xInfoP->volid = volid;
2491 * Drop the transaction we have for this volume.
2495 ttc = (struct volser_trans *)0;
2499 * Bump the pointer in the data area we're building, along with
2500 * the count of the number of entries it contains.
2503 (a_volumeXInfoP->volXEntries_len)++;
2504 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2506 * We're running out of space in the area we've built. Grow it.
2508 allocSize = (allocSize * 3) / 2;
2509 xInfoP = (volintXInfo *)
2510 realloc((char *)a_volumeXInfoP->volXEntries_val,
2511 (allocSize * sizeof(volintXInfo)));
2512 if (xInfoP == NULL) {
2514 * Bummer, no memory. Bag it, tell our caller what went wrong.
2517 VDetachVolume(&error, tv);
2522 ttc = (struct volser_trans *)0;
2525 return (VOLSERNO_MEMORY);
2529 * Memory reallocation worked. Correct our pointers so they
2530 * now point to the new block and the current open position within
2533 a_volumeXInfoP->volXEntries_val = xInfoP;
2535 a_volumeXInfoP->volXEntries_val +
2536 a_volumeXInfoP->volXEntries_len;
2538 /*Need more space */
2541 * Detach our current volume and the transaction on it, then move on
2542 * to the next volume in the partition directory.
2545 VDetachVolume(&error, tv);
2550 ttc = (struct volser_trans *)0;
2552 GetNextVol(dirp, volname, &volid);
2553 } /*Sweep through the partition directory */
2556 * We've examined all entries in the partition directory. Close it,
2557 * delete our transaction (if any), and go home happy.
2564 } /*SAFSVolXListVolumes */
2566 /*this call is used to monitor the status of volser for debugging purposes.
2567 *information about all the active transactions is returned in transInfo*/
2569 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2573 code = VolMonitor(acid, transInfo);
2574 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2579 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2581 transDebugInfo *pntr;
2582 afs_int32 allocSize = 50;
2583 struct volser_trans *tt, *allTrans;
2585 transInfo->transDebugEntries_val =
2586 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2587 pntr = transInfo->transDebugEntries_val;
2588 transInfo->transDebugEntries_len = 0;
2589 allTrans = TransList();
2590 if (allTrans == (struct volser_trans *)0)
2591 return 0; /*no active transactions */
2592 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2593 pntr->tid = tt->tid;
2594 pntr->time = tt->time;
2595 pntr->creationTime = tt->creationTime;
2596 pntr->returnCode = tt->returnCode;
2597 pntr->volid = tt->volid;
2598 pntr->partition = tt->partition;
2599 pntr->iflags = tt->iflags;
2600 pntr->vflags = tt->vflags;
2601 pntr->tflags = tt->tflags;
2602 strcpy(pntr->lastProcName, tt->lastProcName);
2603 pntr->callValid = 0;
2604 if (tt->rxCallPtr) { /*record call related info */
2605 pntr->callValid = 1;
2606 pntr->readNext = tt->rxCallPtr->rnext;
2607 pntr->transmitNext = tt->rxCallPtr->tnext;
2608 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2609 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2612 transInfo->transDebugEntries_len += 1;
2613 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2614 allocSize = (allocSize * 3) / 2;
2616 (transDebugInfo *) realloc((char *)transInfo->
2617 transDebugEntries_val,
2619 sizeof(transDebugInfo));
2620 transInfo->transDebugEntries_val = pntr;
2622 transInfo->transDebugEntries_val +
2623 transInfo->transDebugEntries_len;
2624 /*set pntr to right position */
2633 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2637 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2638 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2639 AUD_STR, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2645 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2648 afs_int32 error = 0;
2649 register struct volser_trans *tt;
2650 char caller[MAXKTCNAMELEN];
2652 if (strlen(name) > 31)
2653 return VOLSERBADNAME;
2654 if (!afsconf_SuperUser(tdir, acid, caller))
2655 return VOLSERBAD_ACCESS; /*not a super user */
2656 /* find the trans */
2657 tt = FindTrans(atid);
2660 if (tt->vflags & VTDeleted) {
2661 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2665 strcpy(tt->lastProcName, "SetIdsTypes");
2666 tt->rxCallPtr = acid;
2670 V_backupId(tv) = backupId;
2671 V_cloneId(tv) = cloneId;
2672 V_parentId(tv) = pId;
2673 strcpy((&V_disk(tv))->name, name);
2674 VUpdateVolume(&error, tv);
2676 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2680 tt->rxCallPtr = (struct rx_call *)0;
2681 if (TRELE(tt) && !error)
2682 return VOLSERTRELE_ERROR;
2686 tt->rxCallPtr = (struct rx_call *)0;
2687 if (TRELE(tt) && !error)
2688 return VOLSERTRELE_ERROR;
2693 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2697 code = VolSetDate(acid, atid, cdate);
2698 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2704 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2707 afs_int32 error = 0;
2708 register struct volser_trans *tt;
2709 char caller[MAXKTCNAMELEN];
2711 if (!afsconf_SuperUser(tdir, acid, caller))
2712 return VOLSERBAD_ACCESS; /*not a super user */
2713 /* find the trans */
2714 tt = FindTrans(atid);
2717 if (tt->vflags & VTDeleted) {
2718 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2722 strcpy(tt->lastProcName, "SetDate");
2723 tt->rxCallPtr = acid;
2726 V_creationDate(tv) = cdate;
2727 VUpdateVolume(&error, tv);
2729 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2733 tt->rxCallPtr = (struct rx_call *)0;
2734 if (TRELE(tt) && !error)
2735 return VOLSERTRELE_ERROR;
2739 tt->rxCallPtr = (struct rx_call *)0;
2740 if (TRELE(tt) && !error)
2741 return VOLSERTRELE_ERROR;
2745 #ifdef AFS_NAMEI_ENV
2747 * Inode number format (from namei_ops.c):
2748 * low 26 bits - vnode number - all 1's if volume special file.
2750 * next 3 bits spare (0's)
2751 * high 32 bits - uniquifier (regular) or type if spare
2753 #define NAMEI_VNODEMASK 0x003ffffff
2754 #define NAMEI_TAGMASK 0x7
2755 #define NAMEI_TAGSHIFT 26
2756 #define NAMEI_UNIQMASK 0xffffffff
2757 #define NAMEI_UNIQSHIFT 32
2758 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2759 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2760 #endif /* AFS_NAMEI_ENV */
2763 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2766 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2770 afs_int32 error = 0;
2773 char caller[MAXKTCNAMELEN];
2774 char headername[16];
2777 struct VolumeDiskHeader h;
2781 struct DiskPartition *dp;
2783 if (!afsconf_SuperUser(tdir, acid, caller))
2784 return VOLSERBAD_ACCESS; /*not a super user */
2785 if (GetPartName(partId, pname))
2786 return VOLSERILLEGAL_PARTITION;
2787 dirp = opendir(pname);
2789 return VOLSERILLEGAL_PARTITION;
2790 strcpy(volname, "");
2792 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2793 GetNextVol(dirp, volname, &volid);
2794 if (strcmp(volname, "")) { /* its a volume */
2795 if (volid == volumeId)
2801 (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
2802 (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
2803 fd = open(opath, O_RDONLY);
2805 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2808 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2809 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2814 FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
2816 for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
2819 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2822 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
2823 IH_INIT(ih, dp->device, h.parent, ino);
2825 error = namei_ConvertROtoRWvolume(ih, volumeId);
2829 h.volumeInfo_hi = h.id;
2830 h.smallVnodeIndex_hi = h.id;
2831 h.largeVnodeIndex_hi = h.id;
2832 h.linkTable_hi = h.id;
2833 (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
2834 (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
2835 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
2837 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
2840 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
2841 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
2846 if (unlink(opath) < 0) {
2847 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
2849 FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
2850 FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
2852 #else /* AFS_NAMEI_ENV */
2854 #endif /* AFS_NAMEI_ENV */
2858 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2859 register struct volintSize *size)
2862 register struct volser_trans *tt;
2863 char caller[MAXKTCNAMELEN];
2865 if (!afsconf_SuperUser(tdir, acid, caller))
2866 return VOLSERBAD_ACCESS; /*not a super user */
2867 tt = FindTrans(fromTrans);
2870 if (tt->vflags & VTDeleted) {
2874 strcpy(tt->lastProcName, "GetSize");
2875 tt->rxCallPtr = acid;
2876 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2877 tt->rxCallPtr = (struct rx_call *)0;
2879 return VOLSERTRELE_ERROR;
2881 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2885 /* GetPartName - map partid (a decimal number) into pname (a string)
2886 * Since for NT we actually want to return the drive name, we map through the
2890 GetPartName(afs_int32 partid, char *pname)
2895 strcpy(pname, "/vicep");
2896 pname[6] = 'a' + partid;
2899 } else if (partid < VOLMAXPARTS) {
2900 strcpy(pname, "/vicep");
2902 pname[6] = 'a' + (partid / 26);
2903 pname[7] = 'a' + (partid % 26);