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 #include <afs/assert.h>
44 #include <afs/prs_fs.h>
49 #include <afs/cellconfig.h>
52 #include <afs/ihandle.h>
54 #include <afs/ntops.h>
56 #include <afs/vnode.h>
57 #include <afs/volume.h>
58 #include <afs/partition.h>
60 #include <afs/fssync.h>
62 #include "afs/audit.h"
68 #include <volser_prototypes.h>
71 extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
72 extern struct afsconf_dir *tdir;
73 extern char *volutil_PartitionName();
75 extern void LogError(afs_int32 errcode);
77 /* Forward declarations */
78 static int GetPartName(afs_int32 partid, char *pname);
80 #define OneDay (24*60*60)
86 afs_int32 localTid = 1;
87 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
88 VolDeleteVolume(), VolClone();
89 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
90 VolForward(), VolDump();
91 afs_int32 VolForwardMultiple();
92 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
93 VolSetInfo(), VolGetName();
94 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(),
95 VolXListOneVolume(), VolXListVolumes();
96 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
97 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
99 /* this call unlocks all of the partition locks we've set */
102 register struct DiskPartition *tp;
103 for (tp = DiskPartitionList; tp; tp = tp->next) {
104 if (tp->lock_fd != -1) {
105 close(tp->lock_fd); /* releases flock held on this partition */
112 /* get partition id from a name */
118 register int code = 0;
123 return -1; /* unknown */
125 /* otherwise check for vicepa or /vicepa, or just plain "a" */
127 if (!strncmp(aname, "/vicep", 6)) {
128 strncpy(ascii, aname + 6, 2);
130 return -1; /* bad partition name */
131 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
132 * from 0. Do the appropriate conversion */
134 /* one char name, 0..25 */
135 if (ascii[0] < 'a' || ascii[0] > 'z')
136 return -1; /* wrongo */
137 return ascii[0] - 'a';
139 /* two char name, 26 .. <whatever> */
140 if (ascii[0] < 'a' || ascii[0] > 'z')
141 return -1; /* wrongo */
142 if (ascii[1] < 'a' || ascii[1] > 'z')
143 return -1; /* just as bad */
144 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
145 if (code > VOLMAXPARTS)
152 ConvertVolume(avol, aname, asize)
159 /* 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 */
160 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
165 ConvertPartition(apartno, aname, 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(error, avolid, apartid, amode)
195 char pbuf[30], vbuf[20];
196 register struct Volume *tv;
198 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
202 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
206 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
210 /* Adapted from the file server; create a root directory for this volume */
216 struct acl_accessList *ACL;
218 Inode inodeNumber, nearInode;
219 char buf[SIZEOF_LARGEDISKVNODE];
220 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
221 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
227 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
229 V_pref(vp, nearInode);
231 IH_CREATE(V_linkHandle(vp), V_device(vp),
232 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
234 assert(VALID_INO(inodeNumber));
236 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
237 did.Volume = V_id(vp);
238 did.Vnode = (VnodeId) 1;
241 assert(!(MakeDir(&dir, &did, &did)));
242 DFlush(); /* flush all modified dir buffers out */
243 DZap(&dir); /* Remove all buffers for this dir */
244 length = Length(&dir); /* Remember size of this directory */
246 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
248 /* build a single entry ACL that gives all rights to system:administrators */
249 /* this section of code assumes that access list format is not going to
252 ACL = VVnodeDiskACL(vnode);
253 ACL->size = sizeof(struct acl_accessList);
254 ACL->version = ACL_ACLVERSION;
258 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
259 ACL->entries[0].rights =
260 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
261 | PRSFS_LOCK | PRSFS_ADMINISTER;
263 vnode->type = vDirectory;
265 vnode->modeBits = 0777;
266 vnode->linkCount = 2;
267 VNDISK_SET_LEN(vnode, length);
268 vnode->uniquifier = 1;
269 V_uniquifier(vp) = vnode->uniquifier + 1;
270 vnode->dataVersion = 1;
271 VNDISK_SET_INO(vnode, inodeNumber);
272 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
276 vnode->vnodeMagic = vcp->magic;
278 IH_INIT(h, vp->device, V_parentId(vp),
279 vp->vnodeIndex[vLarge].handle->ih_ino);
282 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
284 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
285 assert(code == SIZEOF_LARGEDISKVNODE);
286 FDH_REALLYCLOSE(fdP);
288 VNDISK_GET_LEN(length, vnode);
289 V_diskused(vp) = nBlocks(length);
295 SAFSVolPartitionInfo(acid, pname, partition)
296 struct rx_call *acid;
298 struct diskPartition *partition;
302 code = VolPartitionInfo(acid, pname, partition);
303 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
308 VolPartitionInfo(acid, pname, partition)
309 struct rx_call *acid;
311 struct diskPartition *partition;
313 register struct DiskPartition *dp;
316 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
319 dp = VGetPartition(pname, 0);
321 strncpy(partition->name, dp->name, 32);
322 strncpy(partition->devName, dp->devName, 32);
323 partition->lock_fd = dp->lock_fd;
324 partition->free = dp->free;
325 partition->minFree = dp->totalUsable;
328 return VOLSERILLEGAL_PARTITION;
331 /* obliterate a volume completely, and slowly. */
333 SAFSVolNukeVolume(acid, apartID, avolID)
334 struct rx_call *acid;
335 afs_int32 apartID, avolID;
339 code = VolNukeVolume(acid, apartID, avolID);
340 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
345 VolNukeVolume(acid, apartID, avolID)
346 struct rx_call *acid;
347 afs_int32 apartID, avolID;
352 register afs_int32 code;
354 char caller[MAXKTCNAMELEN];
356 /* check for access */
357 if (!afsconf_SuperUser(tdir, acid, caller))
358 return VOLSERBAD_ACCESS;
360 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
362 tp = volutil_PartitionName(apartID);
365 strcpy(partName, tp); /* remember it for later */
366 /* we first try to attach the volume in update mode, so that the file
367 * server doesn't try to use it (and abort) while (or after) we delete it.
368 * If we don't get the volume, that's fine, too. We just won't put it back.
370 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
371 code = nuke(partName, avolID);
373 VDetachVolume(&error, tvp);
377 /* create a new volume, with name aname, on the specified partition (1..n)
378 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
379 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
380 * for the volume id (useful for things like volume restore).
381 * Return the new volume id in *avolid.
384 SAFSVolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans)
385 struct rx_call *acid;
396 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
397 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
398 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
404 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans)
405 struct rx_call *acid;
415 afs_int32 junk; /* discardable error code */
416 register afs_int32 volumeID, doCreateRoot = 1;
417 register struct volser_trans *tt;
419 char caller[MAXKTCNAMELEN];
421 if (strlen(aname) > 31)
422 return VOLSERBADNAME;
423 if (!afsconf_SuperUser(tdir, acid, caller))
424 return VOLSERBAD_ACCESS;
426 Log("%s is executing CreateVolume '%s'\n", caller, aname);
427 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
428 return error; /*a standard unix error */
429 if (atype != readwriteVolume && atype != readonlyVolume
430 && atype != backupVolume)
432 if ((volumeID = *avolid) == 0) {
434 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
438 if ((aparent == volumeID) && (atype == readwriteVolume)) {
443 tt = NewTrans(volumeID, apart);
445 Log("1 createvolume: failed to create trans\n");
446 return VOLSERVOLBUSY; /* volume already busy! */
448 vp = VCreateVolume(&error, ppath, volumeID, aparent);
450 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
455 V_uniquifier(vp) = 1;
456 V_creationDate(vp) = V_copyDate(vp);
457 V_inService(vp) = V_blessed(vp) = 1;
459 AssignVolumeName(&V_disk(vp), aname, 0);
462 V_destroyMe(vp) = DESTROY_ME;
464 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
465 VUpdateVolume(&error, vp);
467 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
470 VDetachVolume(&junk, vp); /* rather return the real error code */
475 strcpy(tt->lastProcName, "CreateVolume");
476 tt->rxCallPtr = acid;
477 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
478 tt->rxCallPtr = (struct rx_call *)0;
480 return VOLSERTRELE_ERROR;
484 /* delete the volume associated with this transaction */
486 SAFSVolDeleteVolume(acid, atrans)
488 struct rx_call *acid;
492 code = VolDeleteVolume(acid, atrans);
493 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
498 VolDeleteVolume(acid, atrans)
500 struct rx_call *acid;
502 register struct volser_trans *tt;
504 char caller[MAXKTCNAMELEN];
506 if (!afsconf_SuperUser(tdir, acid, caller))
507 return VOLSERBAD_ACCESS;
508 tt = FindTrans(atrans);
511 if (tt->vflags & VTDeleted) {
512 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
517 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
518 strcpy(tt->lastProcName, "DeleteVolume");
519 tt->rxCallPtr = acid;
520 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
521 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
522 tt->rxCallPtr = (struct rx_call *)0;
524 return VOLSERTRELE_ERROR;
526 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
527 return 0; /* vpurgevolume doesn't set an error code */
530 /* make a clone of the volume associated with atrans, possibly giving it a new
531 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
532 * for the clone's id). The new clone is given the name newName. Finally, due to
533 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
534 * the clone operation. This may be useful when making new backup volumes, for instance
535 * since the net result of a clone and a purge generally leaves many inode ref counts
536 * the same, while doing them separately would result in far more iincs and idecs being
537 * peformed (and they are slow operations).
540 SAFSVolClone(acid, atrans, purgeId, newType, newName, newNumber)
541 struct rx_call *acid;
544 afs_int32 *newNumber;
545 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
550 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
551 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
552 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
558 VolClone(acid, atrans, purgeId, newType, newName, newNumber)
559 struct rx_call *acid;
562 afs_int32 *newNumber;
563 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
567 register struct Volume *originalvp, *purgevp, *newvp;
569 register struct volser_trans *tt, *ttc;
570 char caller[MAXKTCNAMELEN];
572 if (strlen(newName) > 31)
573 return VOLSERBADNAME;
574 if (!afsconf_SuperUser(tdir, acid, caller))
575 return VOLSERBAD_ACCESS; /*not a super user */
577 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
579 originalvp = (Volume *) 0;
580 purgevp = (Volume *) 0;
581 newvp = (Volume *) 0;
582 tt = ttc = (struct volser_trans *)0;
584 if (!newNumber || !*newNumber) {
585 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
590 if (newType != readonlyVolume && newType != backupVolume)
592 tt = FindTrans(atrans);
595 if (tt->vflags & VTDeleted) {
596 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
600 ttc = NewTrans(newId, tt->partition);
601 if (!ttc) { /* someone is messing with the clone already */
605 strcpy(tt->lastProcName, "Clone");
606 tt->rxCallPtr = acid;
610 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
612 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
618 originalvp = tt->volume;
619 if ((V_type(originalvp) == backupVolume)
620 || (V_type(originalvp) == readonlyVolume)) {
621 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
625 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
626 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
632 if (originalvp->device != purgevp->device) {
633 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
637 if (V_type(purgevp) != readonlyVolume) {
638 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
642 if (V_type(originalvp) == readonlyVolume
643 && V_parentId(originalvp) != V_parentId(purgevp)) {
644 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
648 if (V_type(originalvp) == readwriteVolume
649 && tt->volid != V_parentId(purgevp)) {
650 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
659 VCreateVolume(&error, originalvp->partition->name, newId,
660 V_parentId(originalvp));
662 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
663 newvp = (Volume *) 0;
666 if (newType == readonlyVolume)
667 V_cloneId(originalvp) = newId;
668 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
671 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
672 CloneVolume(&error, originalvp, newvp, purgevp);
673 purgevp = NULL; /* clone releases it, maybe even if error */
675 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
679 if (newType == readonlyVolume) {
680 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
681 V_type(newvp) = readonlyVolume;
682 } else if (newType == backupVolume) {
683 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
684 V_type(newvp) = backupVolume;
685 V_backupId(originalvp) = newId;
687 strcpy(newvp->header->diskstuff.name, newName);
688 V_creationDate(newvp) = V_copyDate(newvp);
689 ClearVolumeStats(&V_disk(newvp));
690 V_destroyMe(newvp) = DESTROY_ME;
691 V_inService(newvp) = 0;
692 if (newType == backupVolume) {
693 V_backupDate(originalvp) = V_copyDate(newvp);
694 V_backupDate(newvp) = V_copyDate(newvp);
697 VUpdateVolume(&error, newvp);
699 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
703 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
705 VUpdateVolume(&error, originalvp);
707 Log("1 Volser: Clone: original update %u\n", error);
711 tt->rxCallPtr = (struct rx_call *)0;
713 tt = (struct volser_trans *)0;
714 error = VOLSERTRELE_ERROR;
722 VDetachVolume(&code, purgevp);
724 VDetachVolume(&code, newvp);
726 tt->rxCallPtr = (struct rx_call *)0;
734 /* reclone this volume into the specified id */
736 SAFSVolReClone(acid, atrans, cloneId)
737 struct rx_call *acid;
743 code = VolReClone(acid, atrans, cloneId);
744 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
750 VolReClone(acid, atrans, cloneId)
751 struct rx_call *acid;
755 register struct Volume *originalvp, *clonevp;
758 register struct volser_trans *tt, *ttc;
759 char caller[MAXKTCNAMELEN];
761 /*not a super user */
762 if (!afsconf_SuperUser(tdir, acid, caller))
763 return VOLSERBAD_ACCESS;
765 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
767 clonevp = originalvp = (Volume *) 0;
768 tt = (struct volser_trans *)0;
770 tt = FindTrans(atrans);
773 if (tt->vflags & VTDeleted) {
774 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
778 ttc = NewTrans(cloneId, tt->partition);
779 if (!ttc) { /* someone is messing with the clone already */
783 strcpy(tt->lastProcName, "ReClone");
784 tt->rxCallPtr = acid;
786 originalvp = tt->volume;
787 if ((V_type(originalvp) == backupVolume)
788 || (V_type(originalvp) == readonlyVolume)) {
789 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
793 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
794 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
800 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
802 Log("1 Volser: can't attach clone %d\n", cloneId);
806 newType = V_type(clonevp); /* type of the new volume */
808 if (originalvp->device != clonevp->device) {
809 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
814 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
815 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
819 if (V_type(originalvp) == readonlyVolume
820 && V_parentId(originalvp) != V_parentId(clonevp)) {
821 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
825 if (V_type(originalvp) == readwriteVolume
826 && tt->volid != V_parentId(clonevp)) {
827 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
833 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
835 CloneVolume(&error, originalvp, clonevp, clonevp);
837 Log("1 Volser: Clone: reclone operation failed with code %d\n",
843 /* fix up volume name and type, CloneVolume just propagated RW's */
844 if (newType == readonlyVolume) {
845 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
846 V_type(clonevp) = readonlyVolume;
847 } else if (newType == backupVolume) {
848 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
849 V_type(clonevp) = backupVolume;
850 V_backupId(originalvp) = cloneId;
852 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
854 /* pretend recloned volume is a totally new instance */
855 V_copyDate(clonevp) = time(0);
856 V_creationDate(clonevp) = V_copyDate(clonevp);
857 ClearVolumeStats(&V_disk(clonevp));
858 V_destroyMe(clonevp) = 0;
859 V_inService(clonevp) = 0;
860 if (newType == backupVolume) {
861 V_backupDate(originalvp) = V_copyDate(clonevp);
862 V_backupDate(clonevp) = V_copyDate(clonevp);
864 V_inUse(clonevp) = 0;
865 VUpdateVolume(&error, clonevp);
867 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
871 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
873 VUpdateVolume(&error, originalvp);
875 Log("1 Volser: Clone: original update %u\n", error);
879 tt->rxCallPtr = (struct rx_call *)0;
881 tt = (struct volser_trans *)0;
882 error = VOLSERTRELE_ERROR;
889 struct DiskPartition *tpartp = originalvp->partition;
890 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
896 VDetachVolume(&code, clonevp);
898 tt->rxCallPtr = (struct rx_call *)0;
906 /* create a new transaction, associated with volume and partition. Type of
907 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
908 * See volser.h for definition of iflags (the constants are named IT*).
911 SAFSVolTransCreate(acid, volume, partition, iflags, ttid)
912 struct rx_call *acid;
920 code = VolTransCreate(acid, volume, partition, iflags, ttid);
921 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
927 VolTransCreate(acid, volume, partition, iflags, ttid)
928 struct rx_call *acid;
934 register struct volser_trans *tt;
936 afs_int32 error, code;
938 char caller[MAXKTCNAMELEN];
940 if (!afsconf_SuperUser(tdir, acid, caller))
941 return VOLSERBAD_ACCESS; /*not a super user */
942 if (iflags & ITCreate)
944 else if (iflags & ITBusy)
946 else if (iflags & ITReadOnly)
948 else if (iflags & ITOffline)
951 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
956 tt = NewTrans(volume, partition);
958 /* can't create a transaction? put the volume back */
959 Log("1 transcreate: can't create transaction\n");
960 return VOLSERVOLBUSY;
962 tv = XAttachVolume(&error, volume, partition, mode);
966 VDetachVolume(&code, tv);
974 strcpy(tt->lastProcName, "TransCreate");
976 return VOLSERTRELE_ERROR;
981 /* using aindex as a 0-based index, return the aindex'th volume on this server
982 * Both the volume number and partition number (one-based) are returned.
985 SAFSVolGetNthVolume(acid, aindex, avolume, apart)
986 struct rx_call *acid;
993 code = VolGetNthVolume(acid, aindex, avolume, apart);
994 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
999 VolGetNthVolume(acid, aindex, avolume, apart)
1000 struct rx_call *acid;
1005 Log("1 Volser: GetNthVolume: Not yet implemented\n");
1009 /* return the volume flags (VT* constants in volser.h) associated with this
1013 SAFSVolGetFlags(acid, atid, aflags)
1014 struct rx_call *acid;
1020 code = VolGetFlags(acid, atid, aflags);
1021 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
1026 VolGetFlags(acid, atid, aflags)
1027 struct rx_call *acid;
1031 register struct volser_trans *tt;
1033 tt = FindTrans(atid);
1036 if (tt->vflags & VTDeleted) {
1037 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
1042 strcpy(tt->lastProcName, "GetFlags");
1043 tt->rxCallPtr = acid;
1044 *aflags = tt->vflags;
1045 tt->rxCallPtr = (struct rx_call *)0;
1047 return VOLSERTRELE_ERROR;
1052 /* Change the volume flags (VT* constants in volser.h) associated with this
1053 * transaction. Effects take place immediately on volume, although volume
1054 * remains attached as usual by the transaction.
1057 SAFSVolSetFlags(acid, atid, aflags)
1058 struct rx_call *acid;
1064 code = VolSetFlags(acid, atid, aflags);
1065 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1071 VolSetFlags(acid, atid, aflags)
1072 struct rx_call *acid;
1076 register struct volser_trans *tt;
1077 register struct Volume *vp;
1079 char caller[MAXKTCNAMELEN];
1081 if (!afsconf_SuperUser(tdir, acid, caller))
1082 return VOLSERBAD_ACCESS; /*not a super user */
1083 /* find the trans */
1084 tt = FindTrans(atid);
1087 if (tt->vflags & VTDeleted) {
1088 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1093 strcpy(tt->lastProcName, "SetFlags");
1094 tt->rxCallPtr = acid;
1095 vp = tt->volume; /* pull volume out of transaction */
1097 /* check if we're allowed to make any updates */
1098 if (tt->iflags & ITReadOnly) {
1103 /* handle delete-on-salvage flag */
1104 if (aflags & VTDeleteOnSalvage) {
1105 V_destroyMe(tt->volume) = DESTROY_ME;
1107 V_destroyMe(tt->volume) = 0;
1110 if (aflags & VTOutOfService) {
1111 V_inService(vp) = 0;
1113 V_inService(vp) = 1;
1115 VUpdateVolume(&error, vp);
1116 tt->vflags = aflags;
1117 tt->rxCallPtr = (struct rx_call *)0;
1118 if (TRELE(tt) && !error)
1119 return VOLSERTRELE_ERROR;
1124 /* dumpS the volume associated with a particular transaction from a particular
1125 * date. Send the dump to a different transaction (destTrans) on the server
1126 * specified by the destServer structure.
1129 SAFSVolForward(acid, fromTrans, fromDate, destination, destTrans, cookie)
1130 struct rx_call *acid;
1131 afs_int32 fromTrans;
1133 struct destServer *destination;
1134 struct restoreCookie *cookie;
1135 afs_int32 destTrans;
1140 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1141 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1142 destination->destHost, AUD_LONG, destTrans, AUD_END);
1147 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie)
1148 struct rx_call *acid;
1149 afs_int32 fromTrans;
1151 struct destServer *destination;
1152 struct restoreCookie *cookie;
1153 afs_int32 destTrans;
1155 register struct volser_trans *tt;
1156 register afs_int32 code;
1157 register struct rx_connection *tcon;
1158 struct rx_call *tcall;
1159 register struct Volume *vp;
1160 struct rx_securityClass *securityObject;
1161 afs_int32 securityIndex;
1162 char caller[MAXKTCNAMELEN];
1164 if (!afsconf_SuperUser(tdir, acid, caller))
1165 return VOLSERBAD_ACCESS; /*not a super user */
1166 /* initialize things */
1167 tcon = (struct rx_connection *)0;
1168 tt = (struct volser_trans *)0;
1170 /* find the local transaction */
1171 tt = FindTrans(fromTrans);
1174 if (tt->vflags & VTDeleted) {
1175 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1180 strcpy(tt->lastProcName, "Forward");
1182 /* get auth info for the this connection (uses afs from ticket file) */
1183 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1189 /* make an rpc connection to the other server */
1191 rx_NewConnection(htonl(destination->destHost),
1192 htons(destination->destPort), VOLSERVICE_ID,
1193 securityObject, securityIndex);
1195 tt->rxCallPtr = (struct rx_call *)0;
1199 tcall = rx_NewCall(tcon);
1200 tt->rxCallPtr = tcall;
1201 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1202 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1207 /* these next calls implictly call rx_Write when writing out data */
1208 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1211 EndAFSVolRestore(tcall); /* probably doesn't do much */
1212 tt->rxCallPtr = (struct rx_call *)0;
1213 code = rx_EndCall(tcall, 0);
1214 rx_DestroyConnection(tcon); /* done with the connection */
1219 return VOLSERTRELE_ERROR;
1225 (void)rx_EndCall(tcall, 0);
1226 rx_DestroyConnection(tcon);
1229 tt->rxCallPtr = (struct rx_call *)0;
1235 /* Start a dump and send it to multiple places simultaneously.
1236 * If this returns an error (eg, return ENOENT), it means that
1237 * none of the releases worked. If this returns 0, that means
1238 * that one or more of the releases worked, and the caller has
1239 * to examine the results array to see which one(s).
1240 * This will only do EITHER incremental or full, not both, so it's
1241 * the caller's responsibility to be sure that all the destinations
1242 * need just an incremental (and from the same time), if that's
1246 SAFSVolForwardMultiple(acid, fromTrans, fromDate, destinations, spare, cookie,
1248 struct rx_call *acid;
1249 afs_int32 fromTrans;
1252 manyDests *destinations;
1253 struct restoreCookie *cookie;
1254 manyResults *results;
1256 afs_int32 securityIndex;
1257 struct rx_securityClass *securityObject;
1258 char caller[MAXKTCNAMELEN];
1259 struct volser_trans *tt;
1260 afs_int32 ec, code, *codes;
1261 struct rx_connection **tcons;
1262 struct rx_call **tcalls;
1264 int i, nconns, is_incremental;
1267 memset(results, 0, sizeof(manyResults));
1269 if (!afsconf_SuperUser(tdir, acid, caller))
1270 return VOLSERBAD_ACCESS; /*not a super user */
1271 tt = FindTrans(fromTrans);
1274 if (tt->vflags & VTDeleted) {
1275 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1280 strcpy(tt->lastProcName, "ForwardMulti");
1282 /* (fromDate == 0) ==> incremental dump */
1283 is_incremental = (fromDate ? 1 : 0);
1285 i = results->manyResults_len = destinations->manyDests_len;
1286 results->manyResults_val = codes =
1287 (afs_int32 *) malloc(i * sizeof(afs_int32));
1289 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1290 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1292 /* get auth info for this connection (uses afs from ticket file) */
1293 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1295 goto fail; /* in order to audit each failure */
1298 /* make connections to all the other servers */
1299 for (i = 0; i < destinations->manyDests_len; i++) {
1300 struct replica *dest = &(destinations->manyDests_val[i]);
1302 rx_NewConnection(htonl(dest->server.destHost),
1303 htons(dest->server.destPort), VOLSERVICE_ID,
1304 securityObject, securityIndex);
1306 codes[i] = ENOTCONN;
1308 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1309 codes[i] = ENOTCONN;
1312 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1315 (void)rx_EndCall(tcalls[i], 0);
1317 rx_DestroyConnection(tcons[i]);
1324 /* these next calls implictly call rx_Write when writing out data */
1325 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1329 for (i--; i >= 0; i--) {
1330 struct replica *dest = &(destinations->manyDests_val[i]);
1332 if (!code && tcalls[i] && !codes[i]) {
1333 EndAFSVolRestore(tcalls[i]);
1336 ec = rx_EndCall(tcalls[i], 0);
1341 rx_DestroyConnection(tcons[i]); /* done with the connection */
1344 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1345 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1346 dest->trans, AUD_END);
1352 tt->rxCallPtr = (struct rx_call *)0;
1353 if (TRELE(tt) && !code) /* return the first code if it's set */
1354 return VOLSERTRELE_ERROR;
1361 SAFSVolDump(acid, fromTrans, fromDate)
1362 struct rx_call *acid;
1363 afs_int32 fromTrans;
1368 code = VolDump(acid, fromTrans, fromDate);
1369 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1374 VolDump(acid, fromTrans, fromDate)
1375 struct rx_call *acid;
1376 afs_int32 fromTrans;
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(fromTrans);
1388 if (tt->vflags & VTDeleted) {
1389 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1393 strcpy(tt->lastProcName, "Dump");
1394 tt->rxCallPtr = acid;
1395 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1397 tt->rxCallPtr = (struct rx_call *)0;
1401 tt->rxCallPtr = (struct rx_call *)0;
1404 return VOLSERTRELE_ERROR;
1410 * Ha! No more helper process!
1413 SAFSVolRestore(acid, atrans, aflags, cookie)
1414 struct rx_call *acid;
1417 struct restoreCookie *cookie;
1421 code = VolRestore(acid, atrans, aflags, cookie);
1422 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1427 VolRestore(acid, atrans, aflags, cookie)
1428 struct rx_call *acid;
1431 struct restoreCookie *cookie;
1433 register struct volser_trans *tt;
1434 register afs_int32 code, tcode;
1435 char caller[MAXKTCNAMELEN];
1437 if (!afsconf_SuperUser(tdir, acid, caller))
1438 return VOLSERBAD_ACCESS; /*not a super user */
1439 tt = FindTrans(atrans);
1442 if (tt->vflags & VTDeleted) {
1443 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1447 strcpy(tt->lastProcName, "Restore");
1448 tt->rxCallPtr = acid;
1450 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1452 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1453 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l); /*break call backs on the
1454 * restored volume */
1455 tt->rxCallPtr = (struct rx_call *)0;
1458 return (code ? code : tcode);
1461 /* end a transaction, returning the transaction's final error code in rcode */
1463 SAFSVolEndTrans(acid, destTrans, rcode)
1464 struct rx_call *acid;
1465 afs_int32 destTrans;
1470 code = VolEndTrans(acid, destTrans, rcode);
1471 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1476 VolEndTrans(acid, destTrans, rcode)
1477 struct rx_call *acid;
1478 afs_int32 destTrans;
1481 register struct volser_trans *tt;
1482 char caller[MAXKTCNAMELEN];
1484 if (!afsconf_SuperUser(tdir, acid, caller))
1485 return VOLSERBAD_ACCESS; /*not a super user */
1486 tt = FindTrans(destTrans);
1490 *rcode = tt->returnCode;
1491 DeleteTrans(tt); /* this does an implicit TRELE */
1497 SAFSVolSetForwarding(acid, atid, anewsite)
1498 struct rx_call *acid;
1504 code = VolSetForwarding(acid, atid, anewsite);
1505 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1511 VolSetForwarding(acid, atid, anewsite)
1512 struct rx_call *acid;
1517 register struct volser_trans *tt;
1518 char caller[MAXKTCNAMELEN];
1520 if (!afsconf_SuperUser(tdir, acid, caller))
1521 return VOLSERBAD_ACCESS; /*not a super user */
1522 tt = FindTrans(atid);
1525 if (tt->vflags & VTDeleted) {
1526 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1531 strcpy(tt->lastProcName, "SetForwarding");
1532 tt->rxCallPtr = acid;
1533 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1534 tt->rxCallPtr = (struct rx_call *)0;
1536 return VOLSERTRELE_ERROR;
1542 SAFSVolGetStatus(acid, atrans, astatus)
1543 struct rx_call *acid;
1545 register struct volser_status *astatus;
1549 code = VolGetStatus(acid, atrans, astatus);
1550 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1555 VolGetStatus(acid, atrans, astatus)
1556 struct rx_call *acid;
1558 register struct volser_status *astatus;
1560 register struct Volume *tv;
1561 register struct VolumeDiskData *td;
1562 struct volser_trans *tt;
1565 tt = FindTrans(atrans);
1568 if (tt->vflags & VTDeleted) {
1569 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1574 strcpy(tt->lastProcName, "GetStatus");
1575 tt->rxCallPtr = acid;
1578 tt->rxCallPtr = (struct rx_call *)0;
1583 td = &tv->header->diskstuff;
1584 astatus->volID = td->id;
1585 astatus->nextUnique = td->uniquifier;
1586 astatus->type = td->type;
1587 astatus->parentID = td->parentId;
1588 astatus->cloneID = td->cloneId;
1589 astatus->backupID = td->backupId;
1590 astatus->restoredFromID = td->restoredFromId;
1591 astatus->maxQuota = td->maxquota;
1592 astatus->minQuota = td->minquota;
1593 astatus->owner = td->owner;
1594 astatus->creationDate = td->creationDate;
1595 astatus->accessDate = td->accessDate;
1596 astatus->updateDate = td->updateDate;
1597 astatus->expirationDate = td->expirationDate;
1598 astatus->backupDate = td->backupDate;
1599 astatus->copyDate = td->copyDate;
1600 tt->rxCallPtr = (struct rx_call *)0;
1602 return VOLSERTRELE_ERROR;
1608 SAFSVolSetInfo(acid, atrans, astatus)
1609 struct rx_call *acid;
1611 register struct volintInfo *astatus;
1615 code = VolSetInfo(acid, atrans, astatus);
1616 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1621 VolSetInfo(acid, atrans, astatus)
1622 struct rx_call *acid;
1624 register struct volintInfo *astatus;
1626 register struct Volume *tv;
1627 register struct VolumeDiskData *td;
1628 struct volser_trans *tt;
1629 char caller[MAXKTCNAMELEN];
1632 if (!afsconf_SuperUser(tdir, acid, caller))
1633 return VOLSERBAD_ACCESS; /*not a super user */
1634 tt = FindTrans(atrans);
1637 if (tt->vflags & VTDeleted) {
1638 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1642 strcpy(tt->lastProcName, "SetStatus");
1643 tt->rxCallPtr = acid;
1646 tt->rxCallPtr = (struct rx_call *)0;
1651 td = &tv->header->diskstuff;
1653 * Add more fields as necessary
1655 if (astatus->maxquota != -1)
1656 td->maxquota = astatus->maxquota;
1657 if (astatus->dayUse != -1)
1658 td->dayUse = astatus->dayUse;
1659 VUpdateVolume(&error, tv);
1660 tt->rxCallPtr = (struct rx_call *)0;
1662 return VOLSERTRELE_ERROR;
1668 SAFSVolGetName(acid, atrans, aname)
1669 struct rx_call *acid;
1675 code = VolGetName(acid, atrans, aname);
1676 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1681 VolGetName(acid, atrans, aname)
1682 struct rx_call *acid;
1686 register struct Volume *tv;
1687 register struct VolumeDiskData *td;
1688 struct volser_trans *tt;
1692 tt = FindTrans(atrans);
1695 if (tt->vflags & VTDeleted) {
1696 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1700 strcpy(tt->lastProcName, "GetName");
1701 tt->rxCallPtr = acid;
1704 tt->rxCallPtr = (struct rx_call *)0;
1709 td = &tv->header->diskstuff;
1710 len = strlen(td->name) + 1; /* don't forget the null */
1712 tt->rxCallPtr = (struct rx_call *)0;
1716 *aname = (char *)malloc(len);
1717 strcpy(*aname, td->name);
1718 tt->rxCallPtr = (struct rx_call *)0;
1720 return VOLSERTRELE_ERROR;
1725 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1728 SAFSVolSignalRestore(acid, volname, volType, parentId, cloneId)
1729 struct rx_call *acid;
1731 afs_int32 parentId, cloneId;
1738 /*return a list of all partitions on the server. The non mounted
1739 *partitions are returned as -1 in the corresponding slot in partIds*/
1741 SAFSVolListPartitions(acid, partIds)
1742 struct rx_call *acid;
1743 struct pIDs *partIds;
1747 code = VolListPartitions(acid, partIds);
1748 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1753 VolListPartitions(acid, partIds)
1754 struct rx_call *acid;
1755 struct pIDs *partIds;
1761 strcpy(namehead, "/vicep"); /*7 including null terminator */
1763 /* Just return attached partitions. */
1765 for (i = 0; i < 26; i++) {
1766 namehead[6] = i + 'a';
1767 if (VGetPartition(namehead, 0))
1768 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1774 /*return a list of all partitions on the server. The non mounted
1775 *partitions are returned as -1 in the corresponding slot in partIds*/
1777 SAFSVolXListPartitions(acid, pEntries)
1778 struct rx_call *acid;
1779 struct partEntries *pEntries;
1783 code = XVolListPartitions(acid, pEntries);
1784 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1789 XVolListPartitions(acid, pEntries)
1790 struct rx_call *acid;
1791 struct partEntries *pEntries;
1793 struct stat rbuf, pbuf;
1795 struct partList partList;
1796 struct DiskPartition *dp;
1799 strcpy(namehead, "/vicep"); /*7 including null terminator */
1801 /* Only report attached partitions */
1802 for (i = 0; i < VOLMAXPARTS; i++) {
1804 namehead[6] = i + 'a';
1808 namehead[6] = 'a' + (k / 26);
1809 namehead[7] = 'a' + (k % 26);
1812 dp = VGetPartition(namehead, 0);
1814 partList.partId[j++] = i;
1816 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1817 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1819 pEntries->partEntries_len = j;
1824 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1830 char name[VOLSER_MAXVOLNAME + 1];
1832 strcpy(name, vname);
1834 while (name[i] == 'V' || name[i] == '0')
1837 name[11] = '\0'; /* smash the "." */
1838 return (atol(&name[i]));
1841 /*return the name of the next volume header in the directory associated with dirp and dp.
1842 *the volume id is returned in volid, and volume header name is returned in volname*/
1843 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1847 dp = readdir(dirp); /*read next entry in the directory */
1850 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1851 *volid = ExtractVolId(dp->d_name);
1852 strcpy(volname, dp->d_name);
1853 return 0; /*return the name of the file representing a volume */
1855 strcpy(volname, "");
1856 return 0; /*volname doesnot represent a volume */
1859 strcpy(volname, "EOD");
1860 return 0; /*end of directory */
1865 /*return the header information about the <volid> */
1867 SAFSVolListOneVolume(acid, partid, volumeId, volumeInfo)
1868 struct rx_call *acid;
1869 afs_int32 volumeId, partid;
1870 volEntries *volumeInfo;
1874 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
1875 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1880 VolListOneVolume(acid, partid, volumeId, volumeInfo)
1881 struct rx_call *acid;
1882 afs_int32 volumeId, partid;
1883 volEntries *volumeInfo;
1886 register struct Volume *tv;
1887 struct DiskPartition *partP;
1888 struct volser_trans *ttc;
1889 char pname[9], volname[20];
1890 afs_int32 error = 0;
1896 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
1897 pntr = volumeInfo->volEntries_val;
1898 volumeInfo->volEntries_len = 1;
1899 if (GetPartName(partid, pname))
1900 return VOLSERILLEGAL_PARTITION;
1901 if (!(partP = VGetPartition(pname, 0)))
1902 return VOLSERILLEGAL_PARTITION;
1903 dirp = opendir(VPartitionPath(partP));
1905 return VOLSERILLEGAL_PARTITION;
1906 strcpy(volname, "");
1907 ttc = (struct volser_trans *)0;
1908 tv = (Volume *) 0; /* volume not attached */
1910 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
1912 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
1913 GetNextVol(dirp, volname, &volid);
1914 continue; /*back to while loop */
1917 if (volid == volumeId) { /*copy other things too */
1919 IOMGR_Poll(); /*make sure that the client doesnot time out */
1920 ttc = NewTrans(volid, partid);
1922 pntr->status = VBUSY;
1923 pntr->volid = volid;
1926 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1928 pntr->status = 0; /*things are messed up */
1929 strcpy(pntr->name, volname);
1930 pntr->volid = volid;
1931 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
1934 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1935 /*this volume will be salvaged */
1937 strcpy(pntr->name, volname);
1938 pntr->volid = volid;
1939 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
1943 if (tv->header->diskstuff.needsSalvaged) {
1944 /*this volume will be salvaged */
1946 strcpy(pntr->name, volname);
1947 pntr->volid = volid;
1948 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
1952 /*read in the relevant info */
1953 pntr->status = VOK; /*its ok */
1954 pntr->volid = tv->header->diskstuff.id;
1955 strcpy(pntr->name, tv->header->diskstuff.name);
1956 pntr->type = tv->header->diskstuff.type; /*if ro volume */
1957 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
1958 pntr->backupID = tv->header->diskstuff.backupId;
1959 pntr->parentID = tv->header->diskstuff.parentId;
1960 pntr->copyDate = tv->header->diskstuff.copyDate;
1961 pntr->inUse = tv->header->diskstuff.inUse;
1962 pntr->size = tv->header->diskstuff.diskused;
1963 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1964 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1965 pntr->maxquota = tv->header->diskstuff.maxquota;
1966 pntr->filecount = tv->header->diskstuff.filecount;
1967 now = FT_ApproxTime();
1968 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1971 pntr->dayUse = tv->header->diskstuff.dayUse;
1972 pntr->creationDate = tv->header->diskstuff.creationDate;
1973 pntr->accessDate = tv->header->diskstuff.accessDate;
1974 pntr->updateDate = tv->header->diskstuff.updateDate;
1975 pntr->backupDate = tv->header->diskstuff.backupDate;
1976 pntr->spare0 = tv->header->diskstuff.minquota;
1978 (long)tv->header->diskstuff.weekUse[0] +
1979 (long)tv->header->diskstuff.weekUse[1] +
1980 (long)tv->header->diskstuff.weekUse[2] +
1981 (long)tv->header->diskstuff.weekUse[3] +
1982 (long)tv->header->diskstuff.weekUse[4] +
1983 (long)tv->header->diskstuff.weekUse[5] +
1984 (long)tv->header->diskstuff.weekUse[6];
1985 pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
1986 VDetachVolume(&error, tv); /*free the volume */
1989 pntr->status = 0; /*things are messed up */
1990 strcpy(pntr->name, volname);
1991 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
1996 GetNextVol(dirp, volname, &volid);
2000 VDetachVolume(&error, tv);
2005 ttc = (struct volser_trans *)0;
2015 /*------------------------------------------------------------------------
2016 * EXPORTED SAFSVolXListOneVolume
2019 * Returns extended info on volume a_volID on partition a_partID.
2022 * a_rxCidP : Pointer to the Rx call we're performing.
2023 * a_partID : Partition for which we want the extended list.
2024 * a_volID : Volume ID we wish to know about.
2025 * a_volumeXInfoP : Ptr to the extended info blob.
2028 * 0 Successful operation
2029 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2032 * Nothing interesting.
2036 *------------------------------------------------------------------------*/
2039 SAFSVolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
2040 struct rx_call *a_rxCidP;
2043 volXEntries *a_volumeXInfoP;
2047 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2048 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2053 VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
2054 struct rx_call *a_rxCidP;
2057 volXEntries *a_volumeXInfoP;
2059 { /*SAFSVolXListOneVolume */
2061 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2062 register struct Volume *tv; /*Volume ptr */
2063 struct volser_trans *ttc; /*Volume transaction ptr */
2064 struct DiskPartition *partP; /*Ptr to partition */
2065 char pname[9], volname[20]; /*Partition, volume names */
2066 afs_int32 error; /*Error code */
2067 afs_int32 code; /*Return code */
2068 DIR *dirp; /*Partition directory ptr */
2069 afs_int32 currVolID; /*Current volume ID */
2070 int found = 0; /*Did we find the volume we need? */
2071 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2072 int numStatBytes; /*Num stat bytes to copy per volume */
2076 * Set up our pointers for action, marking our structure to hold exactly
2077 * one entry. Also, assume we'll fail in our quest.
2079 a_volumeXInfoP->volXEntries_val =
2080 (volintXInfo *) malloc(sizeof(volintXInfo));
2081 xInfoP = a_volumeXInfoP->volXEntries_val;
2082 a_volumeXInfoP->volXEntries_len = 1;
2086 * If the partition name we've been given is bad, bogue out.
2088 if (GetPartName(a_partID, pname))
2089 return (VOLSERILLEGAL_PARTITION);
2092 * Open the directory representing the given AFS parttion. If we can't
2095 if (!(partP = VGetPartition(pname, 0)))
2096 return VOLSERILLEGAL_PARTITION;
2097 dirp = opendir(VPartitionPath(partP));
2099 return (VOLSERILLEGAL_PARTITION);
2102 * Sweep through the partition directory, looking for the desired entry.
2103 * First, of course, figure out how many stat bytes to copy out of each
2107 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2108 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2109 strcpy(volname, "");
2110 ttc = (struct volser_trans *)0; /*No transaction yet */
2111 tv = (Volume *) 0; /*Volume not yet attached */
2113 while (strcmp(volname, "EOD") && !found) {
2115 * If this is not a volume, move on to the next entry in the
2116 * partition's directory.
2118 if (!strcmp(volname, "")) {
2119 GetNextVol(dirp, volname, &currVolID);
2123 if (currVolID == a_volID) {
2125 * We found the volume entry we're interested. Pull out the
2126 * extended information, remembering to poll (so that the client
2127 * doesn't time out) and to set up a transaction on the volume.
2131 ttc = NewTrans(currVolID, a_partID);
2134 * Couldn't get a transaction on this volume; let our caller
2137 xInfoP->status = VBUSY;
2138 xInfoP->volid = currVolID;
2143 * Attach the volume, give up on the volume if we can't.
2145 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2147 xInfoP->status = 0; /*things are messed up */
2148 strcpy(xInfoP->name, volname);
2149 xInfoP->volid = currVolID;
2150 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
2156 * Also bag out on this volume if it's been marked as needing a
2157 * salvage or to-be-destroyed.
2159 volDiskDataP = &(tv->header->diskstuff);
2160 if (volDiskDataP->destroyMe == DESTROY_ME) {
2162 strcpy(xInfoP->name, volname);
2163 xInfoP->volid = currVolID;
2164 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2168 if (volDiskDataP->needsSalvaged) {
2170 strcpy(xInfoP->name, volname);
2171 xInfoP->volid = currVolID;
2172 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
2177 * Pull out the desired info and stuff it into the area we'll be
2178 * returning to our caller.
2180 strcpy(xInfoP->name, volDiskDataP->name);
2181 xInfoP->volid = volDiskDataP->id;
2182 xInfoP->type = volDiskDataP->type;
2183 xInfoP->backupID = volDiskDataP->backupId;
2184 xInfoP->parentID = volDiskDataP->parentId;
2185 xInfoP->cloneID = volDiskDataP->cloneId;
2186 xInfoP->status = VOK;
2187 xInfoP->copyDate = volDiskDataP->copyDate;
2188 xInfoP->inUse = volDiskDataP->inUse;
2189 xInfoP->creationDate = volDiskDataP->creationDate;
2190 xInfoP->accessDate = volDiskDataP->accessDate;
2191 xInfoP->updateDate = volDiskDataP->updateDate;
2192 xInfoP->backupDate = volDiskDataP->backupDate;
2193 now = FT_ApproxTime();
2194 if (now - volDiskDataP->dayUseDate > OneDay)
2197 xInfoP->dayUse = volDiskDataP->dayUse;
2198 xInfoP->filecount = volDiskDataP->filecount;
2199 xInfoP->maxquota = volDiskDataP->maxquota;
2200 xInfoP->size = volDiskDataP->diskused;
2203 * Copy out the stat fields in a single operation.
2205 memcpy((char *)&(xInfoP->stat_reads[0]),
2206 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2209 * We're done copying. Detach the volume and iterate (at this
2210 * point, since we found our volume, we'll then drop out of the
2213 VDetachVolume(&error, tv);
2217 strcpy(xInfoP->name, volname);
2218 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2224 * At this point, we're golden.
2227 } /*Found desired volume */
2228 GetNextVol(dirp, volname, &currVolID);
2232 * Drop the transaction we have for this volume.
2236 VDetachVolume(&error, tv);
2241 ttc = (struct volser_trans *)0;
2245 * Clean up before going to dinner: close the partition directory,
2246 * return the proper value.
2251 } /*SAFSVolXListOneVolume */
2253 /*returns all the volumes on partition partid. If flags = 1 then all the
2254 * relevant info about the volumes is also returned */
2256 SAFSVolListVolumes(acid, partid, flags, volumeInfo)
2257 struct rx_call *acid;
2258 afs_int32 flags, partid;
2259 volEntries *volumeInfo;
2263 code = VolListVolumes(acid, partid, flags, volumeInfo);
2264 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2269 VolListVolumes(acid, partid, flags, volumeInfo)
2270 struct rx_call *acid;
2271 afs_int32 flags, partid;
2272 volEntries *volumeInfo;
2275 register struct Volume *tv;
2276 struct DiskPartition *partP;
2277 struct volser_trans *ttc;
2278 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2279 char pname[9], volname[20];
2280 afs_int32 error = 0;
2285 volumeInfo->volEntries_val =
2286 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2287 pntr = volumeInfo->volEntries_val;
2288 volumeInfo->volEntries_len = 0;
2289 if (GetPartName(partid, pname))
2290 return VOLSERILLEGAL_PARTITION;
2291 if (!(partP = VGetPartition(pname, 0)))
2292 return VOLSERILLEGAL_PARTITION;
2293 dirp = opendir(VPartitionPath(partP));
2295 return VOLSERILLEGAL_PARTITION;
2296 strcpy(volname, "");
2297 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2298 ttc = (struct volser_trans *)0; /* new one for each pass */
2299 tv = (Volume *) 0; /* volume not attached */
2301 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2302 GetNextVol(dirp, volname, &volid);
2303 continue; /*back to while loop */
2306 if (flags) { /*copy other things too */
2307 IOMGR_Poll(); /*make sure that the client doesnot time out */
2308 ttc = NewTrans(volid, partid);
2310 pntr->status = VBUSY;
2311 pntr->volid = volid;
2314 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2316 pntr->status = 0; /*things are messed up */
2317 strcpy(pntr->name, volname);
2318 pntr->volid = volid;
2319 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
2322 if (tv->header->diskstuff.needsSalvaged) {
2323 /*this volume will be salvaged */
2325 strcpy(pntr->name, volname);
2326 pntr->volid = volid;
2327 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
2331 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2332 /*this volume will be salvaged */
2335 /*read in the relevant info */
2336 pntr->status = VOK; /*its ok */
2337 pntr->volid = tv->header->diskstuff.id;
2338 strcpy(pntr->name, tv->header->diskstuff.name);
2339 pntr->type = tv->header->diskstuff.type; /*if ro volume */
2340 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
2341 pntr->backupID = tv->header->diskstuff.backupId;
2342 pntr->parentID = tv->header->diskstuff.parentId;
2343 pntr->copyDate = tv->header->diskstuff.copyDate;
2344 pntr->inUse = tv->header->diskstuff.inUse;
2345 pntr->size = tv->header->diskstuff.diskused;
2346 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2347 pntr->maxquota = tv->header->diskstuff.maxquota;
2348 pntr->filecount = tv->header->diskstuff.filecount;
2349 now = FT_ApproxTime();
2350 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2353 pntr->dayUse = tv->header->diskstuff.dayUse;
2354 pntr->creationDate = tv->header->diskstuff.creationDate;
2355 pntr->accessDate = tv->header->diskstuff.accessDate;
2356 pntr->updateDate = tv->header->diskstuff.updateDate;
2357 pntr->backupDate = tv->header->diskstuff.backupDate;
2358 pntr->spare0 = tv->header->diskstuff.minquota;
2360 (long)tv->header->diskstuff.weekUse[0] +
2361 (long)tv->header->diskstuff.weekUse[1] +
2362 (long)tv->header->diskstuff.weekUse[2] +
2363 (long)tv->header->diskstuff.weekUse[3] +
2364 (long)tv->header->diskstuff.weekUse[4] +
2365 (long)tv->header->diskstuff.weekUse[5] +
2366 (long)tv->header->diskstuff.weekUse[6];
2367 pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
2368 VDetachVolume(&error, tv); /*free the volume */
2371 pntr->status = 0; /*things are messed up */
2372 strcpy(pntr->name, volname);
2373 Log("1 Volser: ListVolumes: Could not detach volume %s\n",
2378 pntr->volid = volid;
2379 /*just volids are needed */
2385 ttc = (struct volser_trans *)0;
2388 volumeInfo->volEntries_len += 1;
2389 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2390 /*running out of space, allocate more space */
2391 allocSize = (allocSize * 3) / 2;
2393 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2394 allocSize * sizeof(volintInfo));
2397 VDetachVolume(&error, tv);
2402 ttc = (struct volser_trans *)0;
2405 return VOLSERNO_MEMORY;
2407 volumeInfo->volEntries_val = pntr; /* point to new block */
2408 /* set pntr to the right position */
2409 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2415 VDetachVolume(&error, tv);
2420 ttc = (struct volser_trans *)0;
2422 GetNextVol(dirp, volname, &volid);
2432 /*------------------------------------------------------------------------
2433 * EXPORTED SAFSVolXListVolumes
2436 * Returns all the volumes on partition a_partID. If a_flags
2437 * is set to 1, then all the relevant extended volume information
2441 * a_rxCidP : Pointer to the Rx call we're performing.
2442 * a_partID : Partition for which we want the extended list.
2443 * a_flags : Various flags.
2444 * a_volumeXInfoP : Ptr to the extended info blob.
2447 * 0 Successful operation
2448 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2449 * VOLSERNO_MEMORY if we ran out of memory allocating
2453 * Nothing interesting.
2457 *------------------------------------------------------------------------*/
2460 SAFSVolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2461 struct rx_call *a_rxCidP;
2464 volXEntries *a_volumeXInfoP;
2468 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2469 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2474 VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2475 struct rx_call *a_rxCidP;
2478 volXEntries *a_volumeXInfoP;
2480 { /*SAFSVolXListVolumes */
2482 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2483 register struct Volume *tv; /*Volume ptr */
2484 struct DiskPartition *partP; /*Ptr to partition */
2485 struct volser_trans *ttc; /*Volume transaction ptr */
2486 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2487 char pname[9], volname[20]; /*Partition, volume names */
2488 afs_int32 error = 0; /*Return code */
2489 DIR *dirp; /*Partition directory ptr */
2490 afs_int32 volid; /*Current volume ID */
2491 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
2492 int numStatBytes; /*Num stat bytes to copy per volume */
2496 * Allocate a large array of extended volume info structures, then
2497 * set it up for action.
2499 a_volumeXInfoP->volXEntries_val =
2500 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2501 xInfoP = a_volumeXInfoP->volXEntries_val;
2502 a_volumeXInfoP->volXEntries_len = 0;
2505 * If the partition name we've been given is bad, bogue out.
2507 if (GetPartName(a_partID, pname))
2508 return (VOLSERILLEGAL_PARTITION);
2511 * Open the directory representing the given AFS parttion. If we can't
2514 if (!(partP = VGetPartition(pname, 0)))
2515 return VOLSERILLEGAL_PARTITION;
2516 dirp = opendir(VPartitionPath(partP));
2518 return (VOLSERILLEGAL_PARTITION);
2521 * Sweep through the partition directory, acting on each entry. First,
2522 * of course, figure out how many stat bytes to copy out of each volume.
2525 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
2526 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
2527 strcpy(volname, "");
2528 while (strcmp(volname, "EOD")) {
2529 ttc = (struct volser_trans *)0; /*New one for each pass */
2530 tv = (Volume *) 0; /*Volume not yet attached */
2533 * If this is not a volume, move on to the next entry in the
2534 * partition's directory.
2536 if (!strcmp(volname, "")) {
2537 GetNextVol(dirp, volname, &volid);
2543 * Full info about the volume desired. Poll to make sure the
2544 * client doesn't time out, then start up a new transaction.
2547 ttc = NewTrans(volid, a_partID);
2550 * Couldn't get a transaction on this volume; let our caller
2553 xInfoP->status = VBUSY;
2554 xInfoP->volid = volid;
2559 * Attach the volume, give up on this volume if we can't.
2561 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2563 xInfoP->status = 0; /*things are messed up */
2564 strcpy(xInfoP->name, volname);
2565 xInfoP->volid = volid;
2566 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2572 * Also bag out on this volume if it's been marked as needing a
2573 * salvage or to-be-destroyed.
2575 volDiskDataP = &(tv->header->diskstuff);
2576 if (volDiskDataP->needsSalvaged) {
2578 strcpy(xInfoP->name, volname);
2579 xInfoP->volid = volid;
2580 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
2584 if (volDiskDataP->destroyMe == DESTROY_ME)
2588 * Pull out the desired info and stuff it into the area we'll be
2589 * returning to our caller.
2591 strcpy(xInfoP->name, volDiskDataP->name);
2592 xInfoP->volid = volDiskDataP->id;
2593 xInfoP->type = volDiskDataP->type;
2594 xInfoP->backupID = volDiskDataP->backupId;
2595 xInfoP->parentID = volDiskDataP->parentId;
2596 xInfoP->cloneID = volDiskDataP->cloneId;
2597 xInfoP->status = VOK;
2598 xInfoP->copyDate = volDiskDataP->copyDate;
2599 xInfoP->inUse = volDiskDataP->inUse;
2600 xInfoP->creationDate = volDiskDataP->creationDate;
2601 xInfoP->accessDate = volDiskDataP->accessDate;
2602 xInfoP->updateDate = volDiskDataP->updateDate;
2603 xInfoP->backupDate = volDiskDataP->backupDate;
2604 now = FT_ApproxTime();
2605 if (now - volDiskDataP->dayUseDate > OneDay)
2608 xInfoP->dayUse = volDiskDataP->dayUse;
2609 xInfoP->filecount = volDiskDataP->filecount;
2610 xInfoP->maxquota = volDiskDataP->maxquota;
2611 xInfoP->size = volDiskDataP->diskused;
2614 * Copy out the stat fields in a single operation.
2616 memcpy((char *)&(xInfoP->stat_reads[0]),
2617 (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2620 * We're done copying. Detach the volume and iterate.
2622 VDetachVolume(&error, tv);
2626 strcpy(xInfoP->name, volname);
2627 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2631 } /*Full contents desired */
2634 * Just volume IDs are needed.
2636 xInfoP->volid = volid;
2640 * Drop the transaction we have for this volume.
2644 ttc = (struct volser_trans *)0;
2648 * Bump the pointer in the data area we're building, along with
2649 * the count of the number of entries it contains.
2652 (a_volumeXInfoP->volXEntries_len)++;
2653 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2655 * We're running out of space in the area we've built. Grow it.
2657 allocSize = (allocSize * 3) / 2;
2658 xInfoP = (volintXInfo *)
2659 realloc((char *)a_volumeXInfoP->volXEntries_val,
2660 (allocSize * sizeof(volintXInfo)));
2661 if (xInfoP == NULL) {
2663 * Bummer, no memory. Bag it, tell our caller what went wrong.
2666 VDetachVolume(&error, tv);
2671 ttc = (struct volser_trans *)0;
2674 return (VOLSERNO_MEMORY);
2678 * Memory reallocation worked. Correct our pointers so they
2679 * now point to the new block and the current open position within
2682 a_volumeXInfoP->volXEntries_val = xInfoP;
2684 a_volumeXInfoP->volXEntries_val +
2685 a_volumeXInfoP->volXEntries_len;
2687 /*Need more space */
2690 * Detach our current volume and the transaction on it, then move on
2691 * to the next volume in the partition directory.
2694 VDetachVolume(&error, tv);
2699 ttc = (struct volser_trans *)0;
2701 GetNextVol(dirp, volname, &volid);
2702 } /*Sweep through the partition directory */
2705 * We've examined all entries in the partition directory. Close it,
2706 * delete our transaction (if any), and go home happy.
2713 } /*SAFSVolXListVolumes */
2715 /*this call is used to monitor the status of volser for debugging purposes.
2716 *information about all the active transactions is returned in transInfo*/
2718 SAFSVolMonitor(acid, transInfo)
2719 struct rx_call *acid;
2720 transDebugEntries *transInfo;
2724 code = VolMonitor(acid, transInfo);
2725 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2730 VolMonitor(acid, transInfo)
2731 struct rx_call *acid;
2732 transDebugEntries *transInfo;
2734 transDebugInfo *pntr;
2735 afs_int32 allocSize = 50;
2736 struct volser_trans *tt, *allTrans;
2738 transInfo->transDebugEntries_val =
2739 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2740 pntr = transInfo->transDebugEntries_val;
2741 transInfo->transDebugEntries_len = 0;
2742 allTrans = TransList();
2743 if (allTrans == (struct volser_trans *)0)
2744 return 0; /*no active transactions */
2745 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2746 pntr->tid = tt->tid;
2747 pntr->time = tt->time;
2748 pntr->creationTime = tt->creationTime;
2749 pntr->returnCode = tt->returnCode;
2750 pntr->volid = tt->volid;
2751 pntr->partition = tt->partition;
2752 pntr->iflags = tt->iflags;
2753 pntr->vflags = tt->vflags;
2754 pntr->tflags = tt->tflags;
2755 strcpy(pntr->lastProcName, tt->lastProcName);
2756 pntr->callValid = 0;
2757 if (tt->rxCallPtr) { /*record call related info */
2758 pntr->callValid = 1;
2759 pntr->readNext = tt->rxCallPtr->rnext;
2760 pntr->transmitNext = tt->rxCallPtr->tnext;
2761 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2762 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2765 transInfo->transDebugEntries_len += 1;
2766 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2767 allocSize = (allocSize * 3) / 2;
2769 (transDebugInfo *) realloc((char *)transInfo->
2770 transDebugEntries_val,
2772 sizeof(transDebugInfo));
2773 transInfo->transDebugEntries_val = pntr;
2775 transInfo->transDebugEntries_val +
2776 transInfo->transDebugEntries_len;
2777 /*set pntr to right position */
2786 SAFSVolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId)
2787 struct rx_call *acid;
2788 afs_int32 type, pId, cloneId, backupId, atid;
2793 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2794 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2795 AUD_STR, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2801 VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId)
2802 struct rx_call *acid;
2803 afs_int32 type, pId, cloneId, backupId, atid;
2807 afs_int32 error = 0;
2808 register struct volser_trans *tt;
2809 char caller[MAXKTCNAMELEN];
2811 if (strlen(name) > 31)
2812 return VOLSERBADNAME;
2813 if (!afsconf_SuperUser(tdir, acid, caller))
2814 return VOLSERBAD_ACCESS; /*not a super user */
2815 /* find the trans */
2816 tt = FindTrans(atid);
2819 if (tt->vflags & VTDeleted) {
2820 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2824 strcpy(tt->lastProcName, "SetIdsTypes");
2825 tt->rxCallPtr = acid;
2829 V_backupId(tv) = backupId;
2830 V_cloneId(tv) = cloneId;
2831 V_parentId(tv) = pId;
2832 strcpy((&V_disk(tv))->name, name);
2833 VUpdateVolume(&error, tv);
2835 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2839 tt->rxCallPtr = (struct rx_call *)0;
2840 if (TRELE(tt) && !error)
2841 return VOLSERTRELE_ERROR;
2845 tt->rxCallPtr = (struct rx_call *)0;
2846 if (TRELE(tt) && !error)
2847 return VOLSERTRELE_ERROR;
2852 SAFSVolSetDate(acid, atid, cdate)
2853 struct rx_call *acid;
2854 afs_int32 atid, cdate;
2858 code = VolSetDate(acid, atid, cdate);
2859 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2865 VolSetDate(acid, atid, cdate)
2866 struct rx_call *acid;
2867 afs_int32 atid, cdate;
2870 afs_int32 error = 0;
2871 register struct volser_trans *tt;
2872 char caller[MAXKTCNAMELEN];
2874 if (!afsconf_SuperUser(tdir, acid, caller))
2875 return VOLSERBAD_ACCESS; /*not a super user */
2876 /* find the trans */
2877 tt = FindTrans(atid);
2880 if (tt->vflags & VTDeleted) {
2881 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2885 strcpy(tt->lastProcName, "SetDate");
2886 tt->rxCallPtr = acid;
2889 V_creationDate(tv) = cdate;
2890 VUpdateVolume(&error, tv);
2892 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2896 tt->rxCallPtr = (struct rx_call *)0;
2897 if (TRELE(tt) && !error)
2898 return VOLSERTRELE_ERROR;
2902 tt->rxCallPtr = (struct rx_call *)0;
2903 if (TRELE(tt) && !error)
2904 return VOLSERTRELE_ERROR;
2908 #ifdef AFS_NAMEI_ENV
2910 * Inode number format (from namei_ops.c):
2911 * low 26 bits - vnode number - all 1's if volume special file.
2913 * next 3 bits spare (0's)
2914 * high 32 bits - uniquifier (regular) or type if spare
2916 #define NAMEI_VNODEMASK 0x003ffffff
2917 #define NAMEI_TAGMASK 0x7
2918 #define NAMEI_TAGSHIFT 26
2919 #define NAMEI_UNIQMASK 0xffffffff
2920 #define NAMEI_UNIQSHIFT 32
2921 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2922 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2923 #endif /* AFS_NAMEI_ENV */
2926 SAFSVolConvertROtoRWvolume(acid, partId, volumeId)
2927 struct rx_call *acid;
2931 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2935 afs_int32 error = 0;
2938 char caller[MAXKTCNAMELEN];
2939 char headername[16];
2942 struct VolumeDiskHeader h;
2946 struct DiskPartition *dp;
2948 if (!afsconf_SuperUser(tdir, acid, caller))
2949 return VOLSERBAD_ACCESS; /*not a super user */
2950 if (GetPartName(partId, pname))
2951 return VOLSERILLEGAL_PARTITION;
2952 dirp = opendir(pname);
2954 return VOLSERILLEGAL_PARTITION;
2955 strcpy(volname, "");
2957 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2958 GetNextVol(dirp, volname, &volid);
2959 if (strcmp(volname, "")) { /* its a volume */
2960 if (volid == volumeId)
2966 (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
2967 (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
2968 fd = open(opath, O_RDONLY);
2970 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2973 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2974 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2979 FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
2981 for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
2984 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2987 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
2988 IH_INIT(ih, dp->device, h.parent, ino);
2990 error = namei_ConvertROtoRWvolume(ih, volumeId);
2994 h.volumeInfo_hi = h.id;
2995 h.smallVnodeIndex_hi = h.id;
2996 h.largeVnodeIndex_hi = h.id;
2997 h.linkTable_hi = h.id;
2998 (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
2999 (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
3000 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
3002 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
3005 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
3006 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
3011 if (unlink(opath) < 0) {
3012 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
3014 FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
3015 FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
3017 #else /* AFS_NAMEI_ENV */
3019 #endif /* AFS_NAMEI_ENV */
3023 SAFSVolGetSize(acid, fromTrans, fromDate, size)
3024 struct rx_call *acid;
3025 afs_int32 fromTrans;
3027 register struct volintSize *size;
3030 register struct volser_trans *tt;
3031 char caller[MAXKTCNAMELEN];
3033 if (!afsconf_SuperUser(tdir, acid, caller))
3034 return VOLSERBAD_ACCESS; /*not a super user */
3035 tt = FindTrans(fromTrans);
3038 if (tt->vflags & VTDeleted) {
3042 strcpy(tt->lastProcName, "GetSize");
3043 tt->rxCallPtr = acid;
3044 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
3045 tt->rxCallPtr = (struct rx_call *)0;
3047 return VOLSERTRELE_ERROR;
3049 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
3053 /* GetPartName - map partid (a decimal number) into pname (a string)
3054 * Since for NT we actually want to return the drive name, we map through the
3058 GetPartName(afs_int32 partid, char *pname)
3063 strcpy(pname, "/vicep");
3064 pname[6] = 'a' + partid;
3067 } else if (partid < VOLMAXPARTS) {
3068 strcpy(pname, "/vicep");
3070 pname[6] = 'a' + (partid / 26);
3071 pname[7] = 'a' + (partid % 26);