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
9 * Portions Copyright (c) 2007-2008 Sine Nomine Associates
12 #include <afsconfig.h>
13 #include <afs/param.h>
19 #include <sys/types.h>
27 #include <netinet/in.h>
36 #include <afs/afsint.h>
38 #ifdef AFS_PTHREAD_ENV
40 #else /* AFS_PTHREAD_ENV */
41 #include <afs/assert.h>
42 #endif /* AFS_PTHREAD_ENV */
43 #include <afs/prs_fs.h>
47 #include <afs/cellconfig.h>
50 #include <afs/ihandle.h>
52 #include <afs/ntops.h>
54 #include <afs/vnode.h>
55 #include <afs/volume.h>
56 #include <afs/volume_inline.h>
57 #include <afs/partition.h>
59 #include <afs/daemon_com.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;
74 /* Needed by Irix. Leave, or include a header */
75 extern char *volutil_PartitionName();
77 extern void LogError(afs_int32 errcode);
79 /* Forward declarations */
80 static int GetPartName(afs_int32 partid, char *pname);
82 #define OneDay (24*60*60)
88 afs_int32 localTid = 1;
89 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
90 VolDeleteVolume(), VolClone();
91 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
92 VolForward(), VolDump();
93 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
94 VolSetInfo(), VolGetName();
95 afs_int32 VolListPartitions(), VolListOneVolume(),
96 VolXListOneVolume(), VolXListVolumes();
97 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
98 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
100 /* this call unlocks all of the partition locks we've set */
104 register struct DiskPartition64 *tp;
105 for (tp = DiskPartitionList; tp; tp = tp->next) {
106 if (tp->lock_fd != -1) {
107 close(tp->lock_fd); /* releases flock held on this partition */
114 /* get partition id from a name */
116 PartitionID(char *aname)
119 register int code = 0;
124 return -1; /* unknown */
126 /* otherwise check for vicepa or /vicepa, or just plain "a" */
128 if (!strncmp(aname, "/vicep", 6)) {
129 strncpy(ascii, aname + 6, 2);
131 return -1; /* bad partition name */
132 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
133 * from 0. Do the appropriate conversion */
135 /* one char name, 0..25 */
136 if (ascii[0] < 'a' || ascii[0] > 'z')
137 return -1; /* wrongo */
138 return ascii[0] - 'a';
140 /* two char name, 26 .. <whatever> */
141 if (ascii[0] < 'a' || ascii[0] > 'z')
142 return -1; /* wrongo */
143 if (ascii[1] < 'a' || ascii[1] > 'z')
144 return -1; /* just as bad */
145 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
146 if (code > VOLMAXPARTS)
153 ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
157 /* 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 */
158 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
163 ConvertPartition(int apartno, char *aname, int asize)
169 strcpy(aname, "/vicep");
171 aname[6] = 'a' + apartno;
175 aname[6] = 'a' + (apartno / 26);
176 aname[7] = 'a' + (apartno % 26);
182 /* the only attach function that takes a partition is "...ByName", so we use it */
184 XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
186 char pbuf[30], vbuf[20];
187 register struct Volume *tv;
189 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
193 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
197 tv = VAttachVolumeByName((Error *)error, pbuf, vbuf, amode);
201 /* Adapted from the file server; create a root directory for this volume */
203 ViceCreateRoot(Volume *vp)
206 struct acl_accessList *ACL;
208 Inode inodeNumber, nearInode;
209 struct VnodeDiskObject *vnode;
210 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
216 vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
219 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
221 V_pref(vp, nearInode);
223 IH_CREATE(V_linkHandle(vp), V_device(vp),
224 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
226 assert(VALID_INO(inodeNumber));
228 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
229 did.Volume = V_id(vp);
230 did.Vnode = (VnodeId) 1;
233 assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
234 DFlush(); /* flush all modified dir buffers out */
235 DZap((afs_int32 *)&dir); /* Remove all buffers for this dir */
236 length = Length(&dir); /* Remember size of this directory */
238 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
240 /* build a single entry ACL that gives all rights to system:administrators */
241 /* this section of code assumes that access list format is not going to
244 ACL = VVnodeDiskACL(vnode);
245 ACL->size = sizeof(struct acl_accessList);
246 ACL->version = ACL_ACLVERSION;
250 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
251 ACL->entries[0].rights =
252 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
253 | PRSFS_LOCK | PRSFS_ADMINISTER;
255 vnode->type = vDirectory;
257 vnode->modeBits = 0777;
258 vnode->linkCount = 2;
259 VNDISK_SET_LEN(vnode, length);
260 vnode->uniquifier = 1;
261 V_uniquifier(vp) = vnode->uniquifier + 1;
262 vnode->dataVersion = 1;
263 VNDISK_SET_INO(vnode, inodeNumber);
264 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
268 vnode->vnodeMagic = vcp->magic;
270 IH_INIT(h, vp->device, V_parentId(vp),
271 vp->vnodeIndex[vLarge].handle->ih_ino);
274 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
276 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
277 assert(code == SIZEOF_LARGEDISKVNODE);
278 FDH_REALLYCLOSE(fdP);
280 VNDISK_GET_LEN(length, vnode);
281 V_diskused(vp) = nBlocks(length);
288 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
292 struct diskPartition64 *dp = (struct diskPartition64 *)
293 malloc(sizeof(struct diskPartition64));
295 code = VolPartitionInfo(acid, pname, dp);
297 strncpy(partition->name, dp->name, 32);
298 strncpy(partition->devName, dp->devName, 32);
299 partition->lock_fd = dp->lock_fd;
300 partition->free=RoundInt64ToInt32(dp->free);
301 partition->minFree=RoundInt64ToInt32(dp->minFree);
304 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
309 SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
314 code = VolPartitionInfo(acid, pname, partition);
315 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
320 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
323 register struct DiskPartition64 *dp;
326 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
329 dp = VGetPartition(pname, 0);
331 strncpy(partition->name, dp->name, 32);
332 strncpy(partition->devName, dp->devName, 32);
333 partition->lock_fd = dp->lock_fd;
334 partition->free = dp->free;
335 partition->minFree = dp->totalUsable;
338 return VOLSERILLEGAL_PARTITION;
341 /* obliterate a volume completely, and slowly. */
343 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
347 code = VolNukeVolume(acid, apartID, avolID);
348 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
353 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
357 register afs_int32 code;
359 char caller[MAXKTCNAMELEN];
361 /* check for access */
362 if (!afsconf_SuperUser(tdir, acid, caller))
363 return VOLSERBAD_ACCESS;
365 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
367 if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
369 /* we first try to attach the volume in update mode, so that the file
370 * server doesn't try to use it (and abort) while (or after) we delete it.
371 * If we don't get the volume, that's fine, too. We just won't put it back.
373 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
374 code = nuke(partName, avolID);
376 VDetachVolume(&error, tvp);
380 /* create a new volume, with name aname, on the specified partition (1..n)
381 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
382 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
383 * for the volume id (useful for things like volume restore).
384 * Return the new volume id in *avolid.
387 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
388 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
394 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
395 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
396 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
402 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
403 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
408 afs_int32 junk; /* discardable error code */
409 register afs_int32 volumeID, doCreateRoot = 1;
410 register struct volser_trans *tt;
412 char caller[MAXKTCNAMELEN];
414 if (strlen(aname) > 31)
415 return VOLSERBADNAME;
416 if (!afsconf_SuperUser(tdir, acid, caller))
417 return VOLSERBAD_ACCESS;
419 Log("%s is executing CreateVolume '%s'\n", caller, aname);
420 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
421 return error; /*a standard unix error */
422 if (atype != readwriteVolume && atype != readonlyVolume
423 && atype != backupVolume)
425 if ((volumeID = *avolid) == 0) {
427 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
431 if ((aparent == volumeID) && (atype == readwriteVolume)) {
436 tt = NewTrans(volumeID, apart);
438 Log("1 createvolume: failed to create trans\n");
439 return VOLSERVOLBUSY; /* volume already busy! */
441 vp = VCreateVolume(&error, ppath, volumeID, aparent);
443 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
448 V_uniquifier(vp) = 1;
449 V_updateDate(vp) = V_creationDate(vp) = V_copyDate(vp);
450 V_inService(vp) = V_blessed(vp) = 1;
452 AssignVolumeName(&V_disk(vp), aname, 0);
455 V_destroyMe(vp) = DESTROY_ME;
457 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
458 VUpdateVolume(&error, vp);
460 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
463 VDetachVolume(&junk, vp); /* rather return the real error code */
468 strcpy(tt->lastProcName, "CreateVolume");
469 tt->rxCallPtr = acid;
470 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
471 tt->rxCallPtr = (struct rx_call *)0;
473 return VOLSERTRELE_ERROR;
477 /* delete the volume associated with this transaction */
479 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
483 code = VolDeleteVolume(acid, atrans);
484 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
489 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
491 register struct volser_trans *tt;
493 char caller[MAXKTCNAMELEN];
495 if (!afsconf_SuperUser(tdir, acid, caller))
496 return VOLSERBAD_ACCESS;
497 tt = FindTrans(atrans);
500 if (tt->vflags & VTDeleted) {
501 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
506 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
507 strcpy(tt->lastProcName, "DeleteVolume");
508 tt->rxCallPtr = acid;
509 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
510 V_destroyMe(tt->volume) = DESTROY_ME; /* so endtrans does the right fssync opcode */
511 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
512 tt->rxCallPtr = (struct rx_call *)0;
514 return VOLSERTRELE_ERROR;
516 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
517 return 0; /* vpurgevolume doesn't set an error code */
520 /* make a clone of the volume associated with atrans, possibly giving it a new
521 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
522 * for the clone's id). The new clone is given the name newName. Finally, due to
523 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
524 * the clone operation. This may be useful when making new backup volumes, for instance
525 * since the net result of a clone and a purge generally leaves many inode ref counts
526 * the same, while doing them separately would result in far more iincs and idecs being
527 * peformed (and they are slow operations).
529 /* for efficiency reasons, sometimes faster to piggyback a purge here */
531 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
532 afs_int32 newType, char *newName, afs_int32 *newNumber)
536 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
537 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
538 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
544 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
545 afs_int32 newType, char *newName, afs_int32 *newNumber)
548 register struct Volume *originalvp, *purgevp, *newvp;
550 register struct volser_trans *tt, *ttc;
551 char caller[MAXKTCNAMELEN];
553 if (strlen(newName) > 31)
554 return VOLSERBADNAME;
555 if (!afsconf_SuperUser(tdir, acid, caller))
556 return VOLSERBAD_ACCESS; /*not a super user */
558 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
560 originalvp = (Volume *) 0;
561 purgevp = (Volume *) 0;
562 newvp = (Volume *) 0;
563 tt = ttc = (struct volser_trans *)0;
565 if (!newNumber || !*newNumber) {
566 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
571 if (newType != readonlyVolume && newType != backupVolume)
573 tt = FindTrans(atrans);
576 if (tt->vflags & VTDeleted) {
577 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
581 ttc = NewTrans(newId, tt->partition);
582 if (!ttc) { /* someone is messing with the clone already */
586 strcpy(tt->lastProcName, "Clone");
587 tt->rxCallPtr = acid;
591 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
593 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
599 originalvp = tt->volume;
600 if ((V_type(originalvp) == backupVolume)
601 || (V_type(originalvp) == readonlyVolume)) {
602 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
606 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
607 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
613 if (originalvp->device != purgevp->device) {
614 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
618 if (V_type(purgevp) != readonlyVolume) {
619 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
623 if (V_type(originalvp) == readonlyVolume
624 && V_parentId(originalvp) != V_parentId(purgevp)) {
625 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
629 if (V_type(originalvp) == readwriteVolume
630 && tt->volid != V_parentId(purgevp)) {
631 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
640 VCreateVolume(&error, originalvp->partition->name, newId,
641 V_parentId(originalvp));
643 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
644 newvp = (Volume *) 0;
647 if (newType == readonlyVolume)
648 V_cloneId(originalvp) = newId;
649 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
652 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
653 CloneVolume(&error, originalvp, newvp, purgevp);
654 purgevp = NULL; /* clone releases it, maybe even if error */
656 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
660 if (newType == readonlyVolume) {
661 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
662 V_type(newvp) = readonlyVolume;
663 } else if (newType == backupVolume) {
664 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
665 V_type(newvp) = backupVolume;
666 V_backupId(originalvp) = newId;
668 strcpy(newvp->header->diskstuff.name, newName);
669 V_creationDate(newvp) = V_copyDate(newvp);
670 ClearVolumeStats(&V_disk(newvp));
671 V_destroyMe(newvp) = DESTROY_ME;
672 V_inService(newvp) = 0;
673 if (newType == backupVolume) {
674 V_backupDate(originalvp) = V_copyDate(newvp);
675 V_backupDate(newvp) = V_copyDate(newvp);
678 VUpdateVolume(&error, newvp);
680 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
684 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
686 VUpdateVolume(&error, originalvp);
688 Log("1 Volser: Clone: original update %u\n", error);
692 tt->rxCallPtr = (struct rx_call *)0;
694 tt = (struct volser_trans *)0;
695 error = VOLSERTRELE_ERROR;
703 VDetachVolume(&code, purgevp);
705 VDetachVolume(&code, newvp);
707 tt->rxCallPtr = (struct rx_call *)0;
715 /* reclone this volume into the specified id */
717 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
721 code = VolReClone(acid, atrans, cloneId);
722 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
728 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
730 register struct Volume *originalvp, *clonevp;
733 register struct volser_trans *tt, *ttc;
734 char caller[MAXKTCNAMELEN];
736 /*not a super user */
737 if (!afsconf_SuperUser(tdir, acid, caller))
738 return VOLSERBAD_ACCESS;
740 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
742 clonevp = originalvp = (Volume *) 0;
743 tt = (struct volser_trans *)0;
745 tt = FindTrans(atrans);
748 if (tt->vflags & VTDeleted) {
749 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
753 ttc = NewTrans(cloneId, tt->partition);
754 if (!ttc) { /* someone is messing with the clone already */
758 strcpy(tt->lastProcName, "ReClone");
759 tt->rxCallPtr = acid;
761 originalvp = tt->volume;
762 if ((V_type(originalvp) == backupVolume)
763 || (V_type(originalvp) == readonlyVolume)) {
764 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
768 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
769 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
775 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
777 Log("1 Volser: can't attach clone %d\n", cloneId);
781 newType = V_type(clonevp); /* type of the new volume */
783 if (originalvp->device != clonevp->device) {
784 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
789 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
790 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
794 if (V_type(originalvp) == readonlyVolume
795 && V_parentId(originalvp) != V_parentId(clonevp)) {
796 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
800 if (V_type(originalvp) == readwriteVolume
801 && tt->volid != V_parentId(clonevp)) {
802 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
808 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
810 CloneVolume(&error, originalvp, clonevp, clonevp);
812 Log("1 Volser: Clone: reclone operation failed with code %d\n",
818 /* fix up volume name and type, CloneVolume just propagated RW's */
819 if (newType == readonlyVolume) {
820 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
821 V_type(clonevp) = readonlyVolume;
822 } else if (newType == backupVolume) {
823 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
824 V_type(clonevp) = backupVolume;
825 V_backupId(originalvp) = cloneId;
827 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
829 /* pretend recloned volume is a totally new instance */
830 V_copyDate(clonevp) = time(0);
831 V_creationDate(clonevp) = V_copyDate(clonevp);
832 ClearVolumeStats(&V_disk(clonevp));
833 V_destroyMe(clonevp) = 0;
834 V_inService(clonevp) = 0;
835 if (newType == backupVolume) {
836 V_backupDate(originalvp) = V_copyDate(clonevp);
837 V_backupDate(clonevp) = V_copyDate(clonevp);
839 V_inUse(clonevp) = 0;
840 VUpdateVolume(&error, clonevp);
842 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
846 /* VUpdateVolume succeeded. Mark it in service so there's no window
847 * between FSYNC_VOL_ON and VolSetFlags where it's offline with no
848 * specialStatus; this is a reclone and this volume started online
850 V_inService(clonevp) = 1;
851 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
853 VUpdateVolume(&error, originalvp);
855 Log("1 Volser: Clone: original update %u\n", error);
859 tt->rxCallPtr = (struct rx_call *)0;
861 tt = (struct volser_trans *)0;
862 error = VOLSERTRELE_ERROR;
869 struct DiskPartition64 *tpartp = originalvp->partition;
870 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
876 VDetachVolume(&code, clonevp);
878 tt->rxCallPtr = (struct rx_call *)0;
886 /* create a new transaction, associated with volume and partition. Type of
887 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
888 * See volser.h for definition of iflags (the constants are named IT*).
891 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
892 afs_int32 iflags, afs_int32 *ttid)
896 code = VolTransCreate(acid, volume, partition, iflags, ttid);
897 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
903 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
904 afs_int32 iflags, afs_int32 *ttid)
906 register struct volser_trans *tt;
908 afs_int32 error, code;
910 char caller[MAXKTCNAMELEN];
912 if (!afsconf_SuperUser(tdir, acid, caller))
913 return VOLSERBAD_ACCESS; /*not a super user */
914 if (iflags & ITCreate)
916 else if (iflags & ITBusy)
918 else if (iflags & ITReadOnly)
920 else if (iflags & ITOffline)
923 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
928 tt = NewTrans(volume, partition);
930 /* can't create a transaction? put the volume back */
931 Log("1 transcreate: can't create transaction\n");
932 return VOLSERVOLBUSY;
934 tv = XAttachVolume(&error, volume, partition, mode);
938 VDetachVolume(&code, tv);
946 strcpy(tt->lastProcName, "TransCreate");
948 return VOLSERTRELE_ERROR;
953 /* using aindex as a 0-based index, return the aindex'th volume on this server
954 * Both the volume number and partition number (one-based) are returned.
957 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
962 code = VolGetNthVolume(acid, aindex, avolume, apart);
963 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
968 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
971 Log("1 Volser: GetNthVolume: Not yet implemented\n");
975 /* return the volume flags (VT* constants in volser.h) associated with this
979 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
983 code = VolGetFlags(acid, atid, aflags);
984 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
989 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
991 register struct volser_trans *tt;
993 tt = FindTrans(atid);
996 if (tt->vflags & VTDeleted) {
997 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
1002 strcpy(tt->lastProcName, "GetFlags");
1003 tt->rxCallPtr = acid;
1004 *aflags = tt->vflags;
1005 tt->rxCallPtr = (struct rx_call *)0;
1007 return VOLSERTRELE_ERROR;
1012 /* Change the volume flags (VT* constants in volser.h) associated with this
1013 * transaction. Effects take place immediately on volume, although volume
1014 * remains attached as usual by the transaction.
1017 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1021 code = VolSetFlags(acid, atid, aflags);
1022 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1028 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1030 register struct volser_trans *tt;
1031 register struct Volume *vp;
1033 char caller[MAXKTCNAMELEN];
1035 if (!afsconf_SuperUser(tdir, acid, caller))
1036 return VOLSERBAD_ACCESS; /*not a super user */
1037 /* find the trans */
1038 tt = FindTrans(atid);
1041 if (tt->vflags & VTDeleted) {
1042 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1047 strcpy(tt->lastProcName, "SetFlags");
1048 tt->rxCallPtr = acid;
1049 vp = tt->volume; /* pull volume out of transaction */
1051 /* check if we're allowed to make any updates */
1052 if (tt->iflags & ITReadOnly) {
1057 /* handle delete-on-salvage flag */
1058 if (aflags & VTDeleteOnSalvage) {
1059 V_destroyMe(tt->volume) = DESTROY_ME;
1061 V_destroyMe(tt->volume) = 0;
1064 if (aflags & VTOutOfService) {
1065 V_inService(vp) = 0;
1067 V_inService(vp) = 1;
1069 VUpdateVolume(&error, vp);
1070 tt->vflags = aflags;
1071 if (TRELE(tt) && !error)
1072 return VOLSERTRELE_ERROR;
1077 /* dumpS the volume associated with a particular transaction from a particular
1078 * date. Send the dump to a different transaction (destTrans) on the server
1079 * specified by the destServer structure.
1082 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1083 struct destServer *destination, afs_int32 destTrans,
1084 struct restoreCookie *cookie)
1089 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1090 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1091 destination->destHost, AUD_LONG, destTrans, AUD_END);
1096 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1097 struct destServer *destination, afs_int32 destTrans,
1098 struct restoreCookie *cookie)
1100 register struct volser_trans *tt;
1101 register afs_int32 code;
1102 register struct rx_connection *tcon;
1103 struct rx_call *tcall;
1104 register struct Volume *vp;
1105 struct rx_securityClass *securityObject;
1106 afs_int32 securityIndex;
1107 char caller[MAXKTCNAMELEN];
1109 if (!afsconf_SuperUser(tdir, acid, caller))
1110 return VOLSERBAD_ACCESS; /*not a super user */
1111 /* initialize things */
1112 tcon = (struct rx_connection *)0;
1113 tt = (struct volser_trans *)0;
1115 /* find the local transaction */
1116 tt = FindTrans(fromTrans);
1119 if (tt->vflags & VTDeleted) {
1120 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1125 strcpy(tt->lastProcName, "Forward");
1127 /* get auth info for the this connection (uses afs from ticket file) */
1128 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1134 /* make an rpc connection to the other server */
1136 rx_NewConnection(htonl(destination->destHost),
1137 htons(destination->destPort), VOLSERVICE_ID,
1138 securityObject, securityIndex);
1140 tt->rxCallPtr = (struct rx_call *)0;
1144 tcall = rx_NewCall(tcon);
1145 tt->rxCallPtr = tcall;
1146 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1147 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1152 /* these next calls implictly call rx_Write when writing out data */
1153 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1156 EndAFSVolRestore(tcall); /* probably doesn't do much */
1157 tt->rxCallPtr = (struct rx_call *)0;
1158 code = rx_EndCall(tcall, 0);
1159 rx_DestroyConnection(tcon); /* done with the connection */
1164 return VOLSERTRELE_ERROR;
1170 (void)rx_EndCall(tcall, 0);
1171 rx_DestroyConnection(tcon);
1174 tt->rxCallPtr = (struct rx_call *)0;
1180 /* Start a dump and send it to multiple places simultaneously.
1181 * If this returns an error (eg, return ENOENT), it means that
1182 * none of the releases worked. If this returns 0, that means
1183 * that one or more of the releases worked, and the caller has
1184 * to examine the results array to see which one(s).
1185 * This will only do EITHER incremental or full, not both, so it's
1186 * the caller's responsibility to be sure that all the destinations
1187 * need just an incremental (and from the same time), if that's
1191 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1192 fromDate, manyDests *destinations, afs_int32 spare,
1193 struct restoreCookie *cookie, manyResults *results)
1195 afs_int32 securityIndex;
1196 struct rx_securityClass *securityObject;
1197 char caller[MAXKTCNAMELEN];
1198 struct volser_trans *tt;
1199 afs_int32 ec, code, *codes;
1200 struct rx_connection **tcons;
1201 struct rx_call **tcalls;
1203 int i, is_incremental;
1206 memset(results, 0, sizeof(manyResults));
1207 i = results->manyResults_len = destinations->manyDests_len;
1208 results->manyResults_val = codes =
1209 (afs_int32 *) malloc(i * sizeof(afs_int32));
1211 if (!results || !results->manyResults_val)
1214 if (!afsconf_SuperUser(tdir, acid, caller))
1215 return VOLSERBAD_ACCESS; /*not a super user */
1216 tt = FindTrans(fromTrans);
1219 if (tt->vflags & VTDeleted) {
1220 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1225 strcpy(tt->lastProcName, "ForwardMulti");
1227 /* (fromDate == 0) ==> full dump */
1228 is_incremental = (fromDate ? 1 : 0);
1231 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1235 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1241 /* get auth info for this connection (uses afs from ticket file) */
1242 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1244 goto fail; /* in order to audit each failure */
1247 /* make connections to all the other servers */
1248 for (i = 0; i < destinations->manyDests_len; i++) {
1249 struct replica *dest = &(destinations->manyDests_val[i]);
1251 rx_NewConnection(htonl(dest->server.destHost),
1252 htons(dest->server.destPort), VOLSERVICE_ID,
1253 securityObject, securityIndex);
1255 codes[i] = ENOTCONN;
1257 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1258 codes[i] = ENOTCONN;
1261 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1264 (void)rx_EndCall(tcalls[i], 0);
1266 rx_DestroyConnection(tcons[i]);
1273 /* these next calls implictly call rx_Write when writing out data */
1274 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1278 for (i--; i >= 0; i--) {
1279 struct replica *dest = &(destinations->manyDests_val[i]);
1281 if (!code && tcalls[i] && !codes[i]) {
1282 EndAFSVolRestore(tcalls[i]);
1285 ec = rx_EndCall(tcalls[i], 0);
1290 rx_DestroyConnection(tcons[i]); /* done with the connection */
1293 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1294 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1295 dest->trans, AUD_END);
1301 tt->rxCallPtr = (struct rx_call *)0;
1302 if (TRELE(tt) && !code) /* return the first code if it's set */
1303 return VOLSERTRELE_ERROR;
1310 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1314 code = VolDump(acid, fromTrans, fromDate, 0);
1315 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1320 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1324 code = VolDump(acid, fromTrans, fromDate, flags);
1325 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1330 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1333 register struct volser_trans *tt;
1334 char caller[MAXKTCNAMELEN];
1336 if (!afsconf_SuperUser(tdir, acid, caller))
1337 return VOLSERBAD_ACCESS; /*not a super user */
1338 tt = FindTrans(fromTrans);
1341 if (tt->vflags & VTDeleted) {
1342 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1346 strcpy(tt->lastProcName, "Dump");
1347 tt->rxCallPtr = acid;
1348 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1349 ? 0 : 1); /* squirt out the volume's data, too */
1351 tt->rxCallPtr = (struct rx_call *)0;
1355 tt->rxCallPtr = (struct rx_call *)0;
1358 return VOLSERTRELE_ERROR;
1364 * Ha! No more helper process!
1367 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1368 struct restoreCookie *cookie)
1372 code = VolRestore(acid, atrans, aflags, cookie);
1373 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1378 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1379 struct restoreCookie *cookie)
1381 register struct volser_trans *tt;
1382 register afs_int32 code, tcode;
1383 char caller[MAXKTCNAMELEN];
1385 if (!afsconf_SuperUser(tdir, acid, caller))
1386 return VOLSERBAD_ACCESS; /*not a super user */
1387 tt = FindTrans(atrans);
1390 if (tt->vflags & VTDeleted) {
1391 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1395 strcpy(tt->lastProcName, "Restore");
1396 tt->rxCallPtr = acid;
1398 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1400 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1401 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1402 tt->rxCallPtr = (struct rx_call *)0;
1405 return (code ? code : tcode);
1408 /* end a transaction, returning the transaction's final error code in rcode */
1410 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1414 code = VolEndTrans(acid, destTrans, rcode);
1415 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1420 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1422 register struct volser_trans *tt;
1423 char caller[MAXKTCNAMELEN];
1425 if (!afsconf_SuperUser(tdir, acid, caller))
1426 return VOLSERBAD_ACCESS; /*not a super user */
1427 tt = FindTrans(destTrans);
1431 *rcode = tt->returnCode;
1432 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1438 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1442 code = VolSetForwarding(acid, atid, anewsite);
1443 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1449 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1451 register struct volser_trans *tt;
1452 char caller[MAXKTCNAMELEN];
1455 if (!afsconf_SuperUser(tdir, acid, caller))
1456 return VOLSERBAD_ACCESS; /*not a super user */
1457 tt = FindTrans(atid);
1460 if (tt->vflags & VTDeleted) {
1461 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1466 strcpy(tt->lastProcName, "SetForwarding");
1467 tt->rxCallPtr = acid;
1468 if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
1471 FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
1472 tt->rxCallPtr = (struct rx_call *)0;
1474 return VOLSERTRELE_ERROR;
1480 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1481 register struct volser_status *astatus)
1485 code = VolGetStatus(acid, atrans, astatus);
1486 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1491 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1492 register struct volser_status *astatus)
1494 register struct Volume *tv;
1495 register struct VolumeDiskData *td;
1496 struct volser_trans *tt;
1499 tt = FindTrans(atrans);
1502 if (tt->vflags & VTDeleted) {
1503 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1508 strcpy(tt->lastProcName, "GetStatus");
1509 tt->rxCallPtr = acid;
1512 tt->rxCallPtr = (struct rx_call *)0;
1517 td = &tv->header->diskstuff;
1518 astatus->volID = td->id;
1519 astatus->nextUnique = td->uniquifier;
1520 astatus->type = td->type;
1521 astatus->parentID = td->parentId;
1522 astatus->cloneID = td->cloneId;
1523 astatus->backupID = td->backupId;
1524 astatus->restoredFromID = td->restoredFromId;
1525 astatus->maxQuota = td->maxquota;
1526 astatus->minQuota = td->minquota;
1527 astatus->owner = td->owner;
1528 astatus->creationDate = td->creationDate;
1529 astatus->accessDate = td->accessDate;
1530 astatus->updateDate = td->updateDate;
1531 astatus->expirationDate = td->expirationDate;
1532 astatus->backupDate = td->backupDate;
1533 astatus->copyDate = td->copyDate;
1534 tt->rxCallPtr = (struct rx_call *)0;
1536 return VOLSERTRELE_ERROR;
1542 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1543 register struct volintInfo *astatus)
1547 code = VolSetInfo(acid, atrans, astatus);
1548 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1553 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1554 register struct volintInfo *astatus)
1556 register struct Volume *tv;
1557 register struct VolumeDiskData *td;
1558 struct volser_trans *tt;
1559 char caller[MAXKTCNAMELEN];
1562 if (!afsconf_SuperUser(tdir, acid, caller))
1563 return VOLSERBAD_ACCESS; /*not a super user */
1564 tt = FindTrans(atrans);
1567 if (tt->vflags & VTDeleted) {
1568 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1572 strcpy(tt->lastProcName, "SetStatus");
1573 tt->rxCallPtr = acid;
1576 tt->rxCallPtr = (struct rx_call *)0;
1581 td = &tv->header->diskstuff;
1583 * Add more fields as necessary
1585 if (astatus->maxquota != -1)
1586 td->maxquota = astatus->maxquota;
1587 if (astatus->dayUse != -1)
1588 td->dayUse = astatus->dayUse;
1589 if (astatus->creationDate != -1)
1590 td->creationDate = astatus->creationDate;
1591 if (astatus->updateDate != -1)
1592 td->updateDate = astatus->updateDate;
1593 if (astatus->spare2 != -1)
1594 td->volUpdateCounter = (unsigned int)astatus->spare2;
1595 VUpdateVolume(&error, tv);
1596 tt->rxCallPtr = (struct rx_call *)0;
1598 return VOLSERTRELE_ERROR;
1604 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1608 code = VolGetName(acid, atrans, aname);
1609 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1614 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1616 register struct Volume *tv;
1617 register struct VolumeDiskData *td;
1618 struct volser_trans *tt;
1621 /* We need to at least fill it in */
1622 *aname = (char *)malloc(1);
1625 tt = FindTrans(atrans);
1628 if (tt->vflags & VTDeleted) {
1629 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1633 strcpy(tt->lastProcName, "GetName");
1634 tt->rxCallPtr = acid;
1637 tt->rxCallPtr = (struct rx_call *)0;
1642 td = &tv->header->diskstuff;
1643 len = strlen(td->name) + 1; /* don't forget the null */
1645 tt->rxCallPtr = (struct rx_call *)0;
1649 *aname = (char *)realloc(*aname, len);
1650 strcpy(*aname, td->name);
1651 tt->rxCallPtr = (struct rx_call *)0;
1653 return VOLSERTRELE_ERROR;
1658 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1661 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1662 afs_int32 parentId, afs_int32 cloneId)
1668 /*return a list of all partitions on the server. The non mounted
1669 *partitions are returned as -1 in the corresponding slot in partIds*/
1671 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1675 code = VolListPartitions(acid, partIds);
1676 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1681 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1686 strcpy(namehead, "/vicep"); /*7 including null terminator */
1688 /* Just return attached partitions. */
1690 for (i = 0; i < 26; i++) {
1691 namehead[6] = i + 'a';
1692 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1698 /*return a list of all partitions on the server. The non mounted
1699 *partitions are returned as -1 in the corresponding slot in partIds*/
1701 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1705 code = XVolListPartitions(acid, pEntries);
1706 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1711 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1713 struct stat rbuf, pbuf;
1715 struct partList partList;
1716 struct DiskPartition64 *dp;
1719 strcpy(namehead, "/vicep"); /*7 including null terminator */
1721 /* Only report attached partitions */
1722 for (i = 0; i < VOLMAXPARTS; i++) {
1723 #ifdef AFS_DEMAND_ATTACH_FS
1724 dp = VGetPartitionById(i, 0);
1727 namehead[6] = i + 'a';
1731 namehead[6] = 'a' + (k / 26);
1732 namehead[7] = 'a' + (k % 26);
1735 dp = VGetPartition(namehead, 0);
1738 partList.partId[j++] = i;
1740 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1741 if (!pEntries->partEntries_val)
1743 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1745 pEntries->partEntries_len = j;
1750 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1752 ExtractVolId(char vname[])
1755 char name[VOLSER_MAXVOLNAME + 1];
1757 strcpy(name, vname);
1759 while (name[i] == 'V' || name[i] == '0')
1762 name[11] = '\0'; /* smash the "." */
1763 return (atol(&name[i]));
1766 /*return the name of the next volume header in the directory associated with dirp and dp.
1767 *the volume id is returned in volid, and volume header name is returned in volname*/
1769 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1773 dp = readdir(dirp); /*read next entry in the directory */
1775 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1776 *volid = ExtractVolId(dp->d_name);
1777 strcpy(volname, dp->d_name);
1778 return 0; /*return the name of the file representing a volume */
1780 strcpy(volname, "");
1781 return 0; /*volname doesnot represent a volume */
1784 strcpy(volname, "EOD");
1785 return 0; /*end of directory */
1791 * volint vol info structure type.
1794 VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
1795 VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
1796 } volint_info_type_t;
1799 * handle to various on-wire vol info types.
1802 volint_info_type_t volinfo_type;
1808 } volint_info_handle_t;
1811 * store value to a field at the appropriate location in on-wire structure.
1813 #define VOLINT_INFO_STORE(handle, name, val) \
1815 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
1816 (handle)->volinfo_ptr.base->name = (val); \
1818 (handle)->volinfo_ptr.ext->name = (val); \
1823 * get pointer to appropriate offset of field in on-wire structure.
1825 #define VOLINT_INFO_PTR(handle, name) \
1826 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
1827 &((handle)->volinfo_ptr.base->name) : \
1828 &((handle)->volinfo_ptr.ext->name))
1831 * fill in appropriate type of on-wire volume metadata structure.
1833 * @param vp pointer to volume object
1834 * @param handle pointer to wire format handle object
1836 * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
1837 * @pre handle object must have a valid pointer and enumeration value
1839 * @note passing a NULL value for vp means that the fileserver doesn't
1840 * know about this particular volume, thus implying it is offline.
1842 * @return operation status
1847 FillVolInfo(Volume * vp, volint_info_handle_t * handle)
1849 unsigned int numStatBytes, now;
1850 register struct VolumeDiskData *hdr = &vp->header->diskstuff;
1852 /*read in the relevant info */
1853 strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
1854 VOLINT_INFO_STORE(handle, status, VOK); /*its ok */
1855 VOLINT_INFO_STORE(handle, volid, hdr->id);
1856 VOLINT_INFO_STORE(handle, type, hdr->type); /*if ro volume */
1857 VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId); /*if rw volume */
1858 VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
1859 VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
1860 VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
1861 VOLINT_INFO_STORE(handle, size, hdr->diskused);
1862 VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
1863 VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
1864 now = FT_ApproxTime();
1865 if ((now - hdr->dayUseDate) > OneDay) {
1866 VOLINT_INFO_STORE(handle, dayUse, 0);
1868 VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
1870 VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
1871 VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
1872 VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
1873 VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
1875 #ifdef AFS_DEMAND_ATTACH_FS
1877 * for DAFS, we "lie" about volume state --
1878 * instead of returning the raw state from the disk header,
1879 * we compute state based upon the fileserver's internal
1880 * in-core state enumeration value reported to us via fssync,
1881 * along with the blessed and inService flags from the header.
1882 * -- tkeiser 11/27/2007
1885 /* Conditions that offline status is based on:
1886 volume is unattached state
1887 volume state is in (one of several error states)
1888 volume not in service
1889 volume is not marked as blessed (not on hold)
1890 volume in salvage req. state
1891 volume needsSalvaged
1892 next op would set volume offline
1893 next op would not leave volume online (based on several conditions)
1896 (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1897 VIsErrorState(V_attachState(vp)) ||
1900 (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
1901 hdr->needsSalvaged ||
1902 (vp->pending_vol_op &&
1903 (vp->pending_vol_op->com.command == FSYNC_VOL_OFF ||
1904 !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
1907 VOLINT_INFO_STORE(handle, inUse, 0);
1909 VOLINT_INFO_STORE(handle, inUse, 1);
1912 /* offline status based on program type, where != fileServer enum (1) is offline */
1913 if (hdr->inUse == fileServer) {
1914 VOLINT_INFO_STORE(handle, inUse, 1);
1916 VOLINT_INFO_STORE(handle, inUse, 0);
1921 switch(handle->volinfo_type) {
1922 /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
1923 case VOLINT_INFO_TYPE_BASE:
1925 #ifdef AFS_DEMAND_ATTACH_FS
1926 /* see comment above where we set inUse bit */
1927 if (hdr->needsSalvaged ||
1928 (vp && VIsErrorState(V_attachState(vp)))) {
1929 handle->volinfo_ptr.base->needsSalvaged = 1;
1931 handle->volinfo_ptr.base->needsSalvaged = 0;
1934 handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
1936 handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
1937 handle->volinfo_ptr.base->spare0 = hdr->minquota;
1938 handle->volinfo_ptr.base->spare1 =
1939 (long)hdr->weekUse[0] +
1940 (long)hdr->weekUse[1] +
1941 (long)hdr->weekUse[2] +
1942 (long)hdr->weekUse[3] +
1943 (long)hdr->weekUse[4] +
1944 (long)hdr->weekUse[5] +
1945 (long)hdr->weekUse[6];
1946 handle->volinfo_ptr.base->flags = 0;
1947 handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
1948 handle->volinfo_ptr.base->spare3 = 0;
1952 case VOLINT_INFO_TYPE_EXT:
1954 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1955 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1958 * Copy out the stat fields in a single operation.
1960 if ((now - hdr->dayUseDate) > OneDay) {
1961 memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1964 memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1965 (char *)&(hdr->stat_reads[0]),
1975 * get struct Volume out of the fileserver.
1977 * @param[in] volumeId volumeId for which we want state information
1978 * @param[in] pname partition name string
1979 * @param[inout] vp pointer to pointer to Volume object which
1980 * will be populated (see note)
1982 * @return operation status
1984 * @retval non-zero failure
1986 * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
1991 GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
1996 res.hdr.response_len = sizeof(res.hdr);
1997 res.payload.buf = *vp;
1998 res.payload.len = sizeof(Volume);
2000 code = FSYNC_VolOp(volumeId,
2006 if (code != SYNC_OK) {
2007 switch (res.hdr.reason) {
2008 case FSYNC_WRONG_PART:
2009 case FSYNC_UNKNOWN_VOLID:
2020 * mode of volume list operation.
2023 VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
2024 VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
2025 } vol_info_list_mode_t;
2028 * abstract interface to populate wire-format volume metadata structures.
2030 * @param[in] partId partition id
2031 * @param[in] volumeId volume id
2032 * @param[in] pname partition name
2033 * @param[in] volname volume file name
2034 * @param[in] handle handle to on-wire volume metadata object
2035 * @param[in] mode listing mode
2037 * @return operation status
2039 * @retval -2 DESTROY_ME flag is set
2040 * @retval -1 general failure; some data filled in
2041 * @retval -3 couldn't create vtrans; some data filled in
2044 GetVolInfo(afs_uint32 partId,
2045 afs_uint32 volumeId,
2048 volint_info_handle_t * handle,
2049 vol_info_list_mode_t mode)
2054 struct volser_trans *ttc = NULL;
2055 struct Volume *fill_tv, *tv = NULL;
2056 #ifdef AFS_DEMAND_ATTACH_FS
2057 struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
2058 SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
2059 SYNC_response fs_res; /* Response handle for the pending_vol_op */
2060 FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
2062 /* Set up response handle for pending_vol_op */
2063 fs_res.hdr.response_len = sizeof(fs_res.hdr);
2064 fs_res.payload.buf = fs_res_buf;
2065 fs_res.payload.len = SYNC_PROTO_MAX_LEN;
2068 ttc = NewTrans(volumeId, partId);
2071 VOLINT_INFO_STORE(handle, status, VBUSY);
2072 VOLINT_INFO_STORE(handle, volid, volumeId);
2076 /* Get volume from volserver */
2077 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2079 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
2080 volumeId, pname, volname, error);
2085 * please note that destroyMe and needsSalvaged checks used to be ordered
2086 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2087 * more correct to check destroyMe before needsSalvaged.
2088 * -- tkeiser 11/28/2007
2091 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2093 case VOL_INFO_LIST_MULTIPLE:
2097 case VOL_INFO_LIST_SINGLE:
2098 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
2099 volumeId, pname, volname);
2106 if (tv->header->diskstuff.needsSalvaged) {
2107 /*this volume will be salvaged */
2108 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2109 volumeId, pname, volname);
2112 #ifdef AFS_DEMAND_ATTACH_FS
2113 /* If using DAFS, get volume from fsserver */
2114 if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
2118 /* fs_tv is a shallow copy, must populate certain structures before passing along */
2119 if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) {
2120 /* If we if the pending vol op */
2121 memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
2122 fs_tv->pending_vol_op=&pending_vol_op_res;
2124 fs_tv->pending_vol_op=NULL;
2127 /* populate the header from the volserver copy */
2128 fs_tv->header=tv->header;
2130 /* When using DAFS, use the fs volume info, populated with required structures */
2133 /* When not using DAFS, just use the local volume info */
2137 /* ok, we have all the data we need; fill in the on-wire struct */
2138 code = FillVolInfo(fill_tv, handle);
2142 VOLINT_INFO_STORE(handle, status, 0);
2143 strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
2144 VOLINT_INFO_STORE(handle, volid, volumeId);
2147 VDetachVolume(&error, tv);
2150 VOLINT_INFO_STORE(handle, status, 0);
2151 strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
2152 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2153 volumeId, pname, volname);
2157 DeleteTrans(ttc, 1);
2164 /*return the header information about the <volid> */
2166 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2167 volumeId, volEntries *volumeInfo)
2171 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2172 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
2177 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2178 volumeId, volEntries *volumeInfo)
2181 struct DiskPartition64 *partP;
2182 char pname[9], volname[20];
2183 afs_int32 error = 0;
2189 volint_info_handle_t handle;
2191 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2192 if (!volumeInfo->volEntries_val)
2194 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2196 pntr = volumeInfo->volEntries_val;
2197 volumeInfo->volEntries_len = 1;
2198 if (GetPartName(partid, pname))
2199 return VOLSERILLEGAL_PARTITION;
2200 if (!(partP = VGetPartition(pname, 0)))
2201 return VOLSERILLEGAL_PARTITION;
2202 dirp = opendir(VPartitionPath(partP));
2204 return VOLSERILLEGAL_PARTITION;
2206 strcpy(volname, "");
2208 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2210 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2211 GetNextVol(dirp, volname, &volid);
2212 continue; /*back to while loop */
2215 if (volid == volumeId) { /*copy other things too */
2220 GetNextVol(dirp, volname, &volid);
2224 #ifndef AFS_PTHREAD_ENV
2225 IOMGR_Poll(); /*make sure that the client does not time out */
2228 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2229 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2231 code = GetVolInfo(partid,
2236 VOL_INFO_LIST_SINGLE);
2240 return (found) ? 0 : ENODEV;
2243 /*------------------------------------------------------------------------
2244 * EXPORTED SAFSVolXListOneVolume
2247 * Returns extended info on volume a_volID on partition a_partID.
2250 * a_rxCidP : Pointer to the Rx call we're performing.
2251 * a_partID : Partition for which we want the extended list.
2252 * a_volID : Volume ID we wish to know about.
2253 * a_volumeXInfoP : Ptr to the extended info blob.
2256 * 0 Successful operation
2257 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2260 * Nothing interesting.
2264 *------------------------------------------------------------------------*/
2267 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2268 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2272 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2273 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2278 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2279 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2280 { /*SAFSVolXListOneVolume */
2282 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2283 struct DiskPartition64 *partP; /*Ptr to partition */
2284 char pname[9], volname[20]; /*Partition, volume names */
2285 afs_int32 error; /*Error code */
2286 DIR *dirp; /*Partition directory ptr */
2287 afs_int32 currVolID; /*Current volume ID */
2288 int found = 0; /*Did we find the volume we need? */
2291 volint_info_handle_t handle;
2294 * Set up our pointers for action, marking our structure to hold exactly
2295 * one entry. Also, assume we'll fail in our quest.
2297 a_volumeXInfoP->volXEntries_val =
2298 (volintXInfo *) malloc(sizeof(volintXInfo));
2299 if (!a_volumeXInfoP->volXEntries_val)
2301 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2303 xInfoP = a_volumeXInfoP->volXEntries_val;
2304 a_volumeXInfoP->volXEntries_len = 1;
2308 * If the partition name we've been given is bad, bogue out.
2310 if (GetPartName(a_partID, pname))
2311 return (VOLSERILLEGAL_PARTITION);
2314 * Open the directory representing the given AFS parttion. If we can't
2317 if (!(partP = VGetPartition(pname, 0)))
2318 return VOLSERILLEGAL_PARTITION;
2319 dirp = opendir(VPartitionPath(partP));
2321 return (VOLSERILLEGAL_PARTITION);
2323 strcpy(volname, "");
2326 * Sweep through the partition directory, looking for the desired entry.
2327 * First, of course, figure out how many stat bytes to copy out of each
2330 while (strcmp(volname, "EOD") && !found) {
2332 * If this is not a volume, move on to the next entry in the
2333 * partition's directory.
2335 if (!strcmp(volname, "")) {
2336 GetNextVol(dirp, volname, &currVolID);
2340 if (currVolID == a_volID) {
2342 * We found the volume entry we're interested. Pull out the
2343 * extended information, remembering to poll (so that the client
2344 * doesn't time out) and to set up a transaction on the volume.
2348 } /*Found desired volume */
2350 GetNextVol(dirp, volname, &currVolID);
2354 #ifndef AFS_PTHREAD_ENV
2358 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2359 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2361 code = GetVolInfo(a_partID,
2366 VOL_INFO_LIST_SINGLE);
2371 * Clean up before going to dinner: close the partition directory,
2372 * return the proper value.
2375 return (found) ? 0 : ENODEV;
2376 } /*SAFSVolXListOneVolume */
2378 /*returns all the volumes on partition partid. If flags = 1 then all the
2379 * relevant info about the volumes is also returned */
2381 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2382 volEntries *volumeInfo)
2386 code = VolListVolumes(acid, partid, flags, volumeInfo);
2387 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2392 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2393 volEntries *volumeInfo)
2396 struct DiskPartition64 *partP;
2397 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2398 char pname[9], volname[20];
2399 afs_int32 error = 0;
2404 volint_info_handle_t handle;
2406 volumeInfo->volEntries_val =
2407 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2408 if (!volumeInfo->volEntries_val)
2410 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2412 pntr = volumeInfo->volEntries_val;
2413 volumeInfo->volEntries_len = 0;
2414 if (GetPartName(partid, pname))
2415 return VOLSERILLEGAL_PARTITION;
2416 if (!(partP = VGetPartition(pname, 0)))
2417 return VOLSERILLEGAL_PARTITION;
2418 dirp = opendir(VPartitionPath(partP));
2420 return VOLSERILLEGAL_PARTITION;
2421 strcpy(volname, "");
2423 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2425 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2426 GetNextVol(dirp, volname, &volid);
2427 continue; /*back to while loop */
2430 if (flags) { /*copy other things too */
2431 #ifndef AFS_PTHREAD_ENV
2432 IOMGR_Poll(); /*make sure that the client does not time out */
2435 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2436 handle.volinfo_ptr.base = pntr;
2439 code = GetVolInfo(partid,
2444 VOL_INFO_LIST_MULTIPLE);
2445 if (code == -2) { /* DESTROY_ME flag set */
2449 pntr->volid = volid;
2450 /*just volids are needed */
2455 volumeInfo->volEntries_len += 1;
2456 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2457 /*running out of space, allocate more space */
2458 allocSize = (allocSize * 3) / 2;
2460 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2461 allocSize * sizeof(volintInfo));
2464 return VOLSERNO_MEMORY;
2466 volumeInfo->volEntries_val = pntr; /* point to new block */
2467 /* set pntr to the right position */
2468 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2473 GetNextVol(dirp, volname, &volid);
2481 /*------------------------------------------------------------------------
2482 * EXPORTED SAFSVolXListVolumes
2485 * Returns all the volumes on partition a_partID. If a_flags
2486 * is set to 1, then all the relevant extended volume information
2490 * a_rxCidP : Pointer to the Rx call we're performing.
2491 * a_partID : Partition for which we want the extended list.
2492 * a_flags : Various flags.
2493 * a_volumeXInfoP : Ptr to the extended info blob.
2496 * 0 Successful operation
2497 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2498 * VOLSERNO_MEMORY if we ran out of memory allocating
2502 * Nothing interesting.
2506 *------------------------------------------------------------------------*/
2509 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2510 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2514 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2515 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2520 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2521 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2522 { /*SAFSVolXListVolumes */
2524 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2525 struct DiskPartition64 *partP; /*Ptr to partition */
2526 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2527 char pname[9], volname[20]; /*Partition, volume names */
2528 afs_int32 error = 0; /*Return code */
2529 DIR *dirp; /*Partition directory ptr */
2530 afs_int32 volid; /*Current volume ID */
2533 volint_info_handle_t handle;
2536 * Allocate a large array of extended volume info structures, then
2537 * set it up for action.
2539 a_volumeXInfoP->volXEntries_val =
2540 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2541 if (!a_volumeXInfoP->volXEntries_val)
2543 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2545 xInfoP = a_volumeXInfoP->volXEntries_val;
2546 a_volumeXInfoP->volXEntries_len = 0;
2549 * If the partition name we've been given is bad, bogue out.
2551 if (GetPartName(a_partID, pname))
2552 return (VOLSERILLEGAL_PARTITION);
2555 * Open the directory representing the given AFS parttion. If we can't
2558 if (!(partP = VGetPartition(pname, 0)))
2559 return VOLSERILLEGAL_PARTITION;
2560 dirp = opendir(VPartitionPath(partP));
2562 return (VOLSERILLEGAL_PARTITION);
2563 strcpy(volname, "");
2566 * Sweep through the partition directory, acting on each entry. First,
2567 * of course, figure out how many stat bytes to copy out of each volume.
2569 while (strcmp(volname, "EOD")) {
2572 * If this is not a volume, move on to the next entry in the
2573 * partition's directory.
2575 if (!strcmp(volname, "")) {
2576 GetNextVol(dirp, volname, &volid);
2582 * Full info about the volume desired. Poll to make sure the
2583 * client doesn't time out, then start up a new transaction.
2585 #ifndef AFS_PTHREAD_ENV
2589 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2590 handle.volinfo_ptr.ext = xInfoP;
2592 code = GetVolInfo(a_partID,
2597 VOL_INFO_LIST_MULTIPLE);
2598 if (code == -2) { /* DESTROY_ME flag set */
2603 * Just volume IDs are needed.
2605 xInfoP->volid = volid;
2610 * Bump the pointer in the data area we're building, along with
2611 * the count of the number of entries it contains.
2614 (a_volumeXInfoP->volXEntries_len)++;
2615 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2617 * We're running out of space in the area we've built. Grow it.
2619 allocSize = (allocSize * 3) / 2;
2620 xInfoP = (volintXInfo *)
2621 realloc((char *)a_volumeXInfoP->volXEntries_val,
2622 (allocSize * sizeof(volintXInfo)));
2623 if (xInfoP == NULL) {
2625 * Bummer, no memory. Bag it, tell our caller what went wrong.
2628 return (VOLSERNO_MEMORY);
2632 * Memory reallocation worked. Correct our pointers so they
2633 * now point to the new block and the current open position within
2636 a_volumeXInfoP->volXEntries_val = xInfoP;
2638 a_volumeXInfoP->volXEntries_val +
2639 a_volumeXInfoP->volXEntries_len;
2643 GetNextVol(dirp, volname, &volid);
2644 } /*Sweep through the partition directory */
2647 * We've examined all entries in the partition directory. Close it,
2648 * delete our transaction (if any), and go home happy.
2653 } /*SAFSVolXListVolumes */
2655 /*this call is used to monitor the status of volser for debugging purposes.
2656 *information about all the active transactions is returned in transInfo*/
2658 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2662 code = VolMonitor(acid, transInfo);
2663 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2668 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2670 transDebugInfo *pntr;
2671 afs_int32 allocSize = 50;
2672 struct volser_trans *tt, *allTrans;
2674 transInfo->transDebugEntries_val =
2675 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2676 if (!transInfo->transDebugEntries_val)
2678 pntr = transInfo->transDebugEntries_val;
2679 transInfo->transDebugEntries_len = 0;
2680 allTrans = TransList();
2681 if (allTrans == (struct volser_trans *)0)
2682 return 0; /*no active transactions */
2683 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2684 pntr->tid = tt->tid;
2685 pntr->time = tt->time;
2686 pntr->creationTime = tt->creationTime;
2687 pntr->returnCode = tt->returnCode;
2688 pntr->volid = tt->volid;
2689 pntr->partition = tt->partition;
2690 pntr->iflags = tt->iflags;
2691 pntr->vflags = tt->vflags;
2692 pntr->tflags = tt->tflags;
2693 strcpy(pntr->lastProcName, tt->lastProcName);
2694 pntr->callValid = 0;
2695 if (tt->rxCallPtr) { /*record call related info */
2696 pntr->callValid = 1;
2697 pntr->readNext = tt->rxCallPtr->rnext;
2698 pntr->transmitNext = tt->rxCallPtr->tnext;
2699 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2700 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2703 transInfo->transDebugEntries_len += 1;
2704 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2705 allocSize = (allocSize * 3) / 2;
2707 (transDebugInfo *) realloc((char *)transInfo->
2708 transDebugEntries_val,
2710 sizeof(transDebugInfo));
2711 transInfo->transDebugEntries_val = pntr;
2713 transInfo->transDebugEntries_val +
2714 transInfo->transDebugEntries_len;
2715 /*set pntr to right position */
2724 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2728 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2729 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2730 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2736 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2739 afs_int32 error = 0;
2740 register struct volser_trans *tt;
2741 char caller[MAXKTCNAMELEN];
2743 if (strlen(name) > 31)
2744 return VOLSERBADNAME;
2745 if (!afsconf_SuperUser(tdir, acid, caller))
2746 return VOLSERBAD_ACCESS; /*not a super user */
2747 /* find the trans */
2748 tt = FindTrans(atid);
2751 if (tt->vflags & VTDeleted) {
2752 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2756 strcpy(tt->lastProcName, "SetIdsTypes");
2757 tt->rxCallPtr = acid;
2761 V_backupId(tv) = backupId;
2762 V_cloneId(tv) = cloneId;
2763 V_parentId(tv) = pId;
2764 strcpy((&V_disk(tv))->name, name);
2765 VUpdateVolume(&error, tv);
2767 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2771 tt->rxCallPtr = (struct rx_call *)0;
2772 if (TRELE(tt) && !error)
2773 return VOLSERTRELE_ERROR;
2777 tt->rxCallPtr = (struct rx_call *)0;
2778 if (TRELE(tt) && !error)
2779 return VOLSERTRELE_ERROR;
2784 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2788 code = VolSetDate(acid, atid, cdate);
2789 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2795 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2798 afs_int32 error = 0;
2799 register struct volser_trans *tt;
2800 char caller[MAXKTCNAMELEN];
2802 if (!afsconf_SuperUser(tdir, acid, caller))
2803 return VOLSERBAD_ACCESS; /*not a super user */
2804 /* find the trans */
2805 tt = FindTrans(atid);
2808 if (tt->vflags & VTDeleted) {
2809 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2813 strcpy(tt->lastProcName, "SetDate");
2814 tt->rxCallPtr = acid;
2817 V_creationDate(tv) = cdate;
2818 VUpdateVolume(&error, tv);
2820 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2824 tt->rxCallPtr = (struct rx_call *)0;
2825 if (TRELE(tt) && !error)
2826 return VOLSERTRELE_ERROR;
2830 tt->rxCallPtr = (struct rx_call *)0;
2831 if (TRELE(tt) && !error)
2832 return VOLSERTRELE_ERROR;
2837 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2843 char caller[MAXKTCNAMELEN];
2845 register struct volser_trans *ttc;
2846 char pname[16], volname[20];
2847 struct DiskPartition64 *partP;
2848 afs_int32 ret = ENODEV;
2851 if (!afsconf_SuperUser(tdir, acid, caller))
2852 return VOLSERBAD_ACCESS; /*not a super user */
2853 if (GetPartName(partId, pname))
2854 return VOLSERILLEGAL_PARTITION;
2855 if (!(partP = VGetPartition(pname, 0)))
2856 return VOLSERILLEGAL_PARTITION;
2857 dirp = opendir(VPartitionPath(partP));
2859 return VOLSERILLEGAL_PARTITION;
2860 strcpy(volname, "");
2861 ttc = (struct volser_trans *)0;
2863 while (strcmp(volname, "EOD")) {
2864 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2865 GetNextVol(dirp, volname, &volid);
2866 continue; /*back to while loop */
2869 if (volid == volumeId) { /*copy other things too */
2870 #ifndef AFS_PTHREAD_ENV
2871 IOMGR_Poll(); /*make sure that the client doesnot time out */
2873 ttc = NewTrans(volumeId, partId);
2877 #ifdef AFS_NAMEI_ENV
2878 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2880 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2884 GetNextVol(dirp, volname, &volid);
2888 DeleteTrans(ttc, 1);
2889 ttc = (struct volser_trans *)0;
2898 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2899 register struct volintSize *size)
2902 register struct volser_trans *tt;
2903 char caller[MAXKTCNAMELEN];
2905 if (!afsconf_SuperUser(tdir, acid, caller))
2906 return VOLSERBAD_ACCESS; /*not a super user */
2907 tt = FindTrans(fromTrans);
2910 if (tt->vflags & VTDeleted) {
2914 strcpy(tt->lastProcName, "GetSize");
2915 tt->rxCallPtr = acid;
2916 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2917 tt->rxCallPtr = (struct rx_call *)0;
2919 return VOLSERTRELE_ERROR;
2921 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2925 /* GetPartName - map partid (a decimal number) into pname (a string)
2926 * Since for NT we actually want to return the drive name, we map through the
2930 GetPartName(afs_int32 partid, char *pname)
2935 strcpy(pname, "/vicep");
2936 pname[6] = 'a' + partid;
2939 } else if (partid < VOLMAXPARTS) {
2940 strcpy(pname, "/vicep");
2942 pname[6] = 'a' + (partid / 26);
2943 pname[7] = 'a' + (partid % 26);