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 tt->rxCallPtr = (struct rx_call *)0;
1072 if (TRELE(tt) && !error)
1073 return VOLSERTRELE_ERROR;
1078 /* dumpS the volume associated with a particular transaction from a particular
1079 * date. Send the dump to a different transaction (destTrans) on the server
1080 * specified by the destServer structure.
1083 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1084 struct destServer *destination, afs_int32 destTrans,
1085 struct restoreCookie *cookie)
1090 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1091 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1092 destination->destHost, AUD_LONG, destTrans, AUD_END);
1097 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1098 struct destServer *destination, afs_int32 destTrans,
1099 struct restoreCookie *cookie)
1101 register struct volser_trans *tt;
1102 register afs_int32 code;
1103 register struct rx_connection *tcon;
1104 struct rx_call *tcall;
1105 register struct Volume *vp;
1106 struct rx_securityClass *securityObject;
1107 afs_int32 securityIndex;
1108 char caller[MAXKTCNAMELEN];
1110 if (!afsconf_SuperUser(tdir, acid, caller))
1111 return VOLSERBAD_ACCESS; /*not a super user */
1112 /* initialize things */
1113 tcon = (struct rx_connection *)0;
1114 tt = (struct volser_trans *)0;
1116 /* find the local transaction */
1117 tt = FindTrans(fromTrans);
1120 if (tt->vflags & VTDeleted) {
1121 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1126 strcpy(tt->lastProcName, "Forward");
1128 /* get auth info for the this connection (uses afs from ticket file) */
1129 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1135 /* make an rpc connection to the other server */
1137 rx_NewConnection(htonl(destination->destHost),
1138 htons(destination->destPort), VOLSERVICE_ID,
1139 securityObject, securityIndex);
1141 tt->rxCallPtr = (struct rx_call *)0;
1145 tcall = rx_NewCall(tcon);
1146 tt->rxCallPtr = tcall;
1147 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1148 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1153 /* these next calls implictly call rx_Write when writing out data */
1154 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1157 EndAFSVolRestore(tcall); /* probably doesn't do much */
1158 tt->rxCallPtr = (struct rx_call *)0;
1159 code = rx_EndCall(tcall, 0);
1160 rx_DestroyConnection(tcon); /* done with the connection */
1165 return VOLSERTRELE_ERROR;
1171 (void)rx_EndCall(tcall, 0);
1172 rx_DestroyConnection(tcon);
1175 tt->rxCallPtr = (struct rx_call *)0;
1181 /* Start a dump and send it to multiple places simultaneously.
1182 * If this returns an error (eg, return ENOENT), it means that
1183 * none of the releases worked. If this returns 0, that means
1184 * that one or more of the releases worked, and the caller has
1185 * to examine the results array to see which one(s).
1186 * This will only do EITHER incremental or full, not both, so it's
1187 * the caller's responsibility to be sure that all the destinations
1188 * need just an incremental (and from the same time), if that's
1192 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1193 fromDate, manyDests *destinations, afs_int32 spare,
1194 struct restoreCookie *cookie, manyResults *results)
1196 afs_int32 securityIndex;
1197 struct rx_securityClass *securityObject;
1198 char caller[MAXKTCNAMELEN];
1199 struct volser_trans *tt;
1200 afs_int32 ec, code, *codes;
1201 struct rx_connection **tcons;
1202 struct rx_call **tcalls;
1204 int i, is_incremental;
1207 memset(results, 0, sizeof(manyResults));
1208 i = results->manyResults_len = destinations->manyDests_len;
1209 results->manyResults_val = codes =
1210 (afs_int32 *) malloc(i * sizeof(afs_int32));
1212 if (!results || !results->manyResults_val)
1215 if (!afsconf_SuperUser(tdir, acid, caller))
1216 return VOLSERBAD_ACCESS; /*not a super user */
1217 tt = FindTrans(fromTrans);
1220 if (tt->vflags & VTDeleted) {
1221 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1226 strcpy(tt->lastProcName, "ForwardMulti");
1228 /* (fromDate == 0) ==> full dump */
1229 is_incremental = (fromDate ? 1 : 0);
1232 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1236 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1242 /* get auth info for this connection (uses afs from ticket file) */
1243 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1245 goto fail; /* in order to audit each failure */
1248 /* make connections to all the other servers */
1249 for (i = 0; i < destinations->manyDests_len; i++) {
1250 struct replica *dest = &(destinations->manyDests_val[i]);
1252 rx_NewConnection(htonl(dest->server.destHost),
1253 htons(dest->server.destPort), VOLSERVICE_ID,
1254 securityObject, securityIndex);
1256 codes[i] = ENOTCONN;
1258 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1259 codes[i] = ENOTCONN;
1262 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1265 (void)rx_EndCall(tcalls[i], 0);
1267 rx_DestroyConnection(tcons[i]);
1274 /* these next calls implictly call rx_Write when writing out data */
1275 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1279 for (i--; i >= 0; i--) {
1280 struct replica *dest = &(destinations->manyDests_val[i]);
1282 if (!code && tcalls[i] && !codes[i]) {
1283 EndAFSVolRestore(tcalls[i]);
1286 ec = rx_EndCall(tcalls[i], 0);
1291 rx_DestroyConnection(tcons[i]); /* done with the connection */
1294 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1295 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1296 dest->trans, AUD_END);
1302 tt->rxCallPtr = (struct rx_call *)0;
1303 if (TRELE(tt) && !code) /* return the first code if it's set */
1304 return VOLSERTRELE_ERROR;
1311 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1315 code = VolDump(acid, fromTrans, fromDate, 0);
1316 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1321 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1325 code = VolDump(acid, fromTrans, fromDate, flags);
1326 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1331 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1334 register struct volser_trans *tt;
1335 char caller[MAXKTCNAMELEN];
1337 if (!afsconf_SuperUser(tdir, acid, caller))
1338 return VOLSERBAD_ACCESS; /*not a super user */
1339 tt = FindTrans(fromTrans);
1342 if (tt->vflags & VTDeleted) {
1343 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1347 strcpy(tt->lastProcName, "Dump");
1348 tt->rxCallPtr = acid;
1349 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1350 ? 0 : 1); /* squirt out the volume's data, too */
1352 tt->rxCallPtr = (struct rx_call *)0;
1356 tt->rxCallPtr = (struct rx_call *)0;
1359 return VOLSERTRELE_ERROR;
1365 * Ha! No more helper process!
1368 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1369 struct restoreCookie *cookie)
1373 code = VolRestore(acid, atrans, aflags, cookie);
1374 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1379 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1380 struct restoreCookie *cookie)
1382 register struct volser_trans *tt;
1383 register afs_int32 code, tcode;
1384 char caller[MAXKTCNAMELEN];
1386 if (!afsconf_SuperUser(tdir, acid, caller))
1387 return VOLSERBAD_ACCESS; /*not a super user */
1388 tt = FindTrans(atrans);
1391 if (tt->vflags & VTDeleted) {
1392 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1396 strcpy(tt->lastProcName, "Restore");
1397 tt->rxCallPtr = acid;
1399 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1401 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1402 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1403 tt->rxCallPtr = (struct rx_call *)0;
1406 return (code ? code : tcode);
1409 /* end a transaction, returning the transaction's final error code in rcode */
1411 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1415 code = VolEndTrans(acid, destTrans, rcode);
1416 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1421 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1423 register struct volser_trans *tt;
1424 char caller[MAXKTCNAMELEN];
1426 if (!afsconf_SuperUser(tdir, acid, caller))
1427 return VOLSERBAD_ACCESS; /*not a super user */
1428 tt = FindTrans(destTrans);
1432 *rcode = tt->returnCode;
1433 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1439 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1443 code = VolSetForwarding(acid, atid, anewsite);
1444 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1450 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1452 register struct volser_trans *tt;
1453 char caller[MAXKTCNAMELEN];
1456 if (!afsconf_SuperUser(tdir, acid, caller))
1457 return VOLSERBAD_ACCESS; /*not a super user */
1458 tt = FindTrans(atid);
1461 if (tt->vflags & VTDeleted) {
1462 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1467 strcpy(tt->lastProcName, "SetForwarding");
1468 tt->rxCallPtr = acid;
1469 if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
1472 FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
1473 tt->rxCallPtr = (struct rx_call *)0;
1475 return VOLSERTRELE_ERROR;
1481 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1482 register struct volser_status *astatus)
1486 code = VolGetStatus(acid, atrans, astatus);
1487 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1492 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1493 register struct volser_status *astatus)
1495 register struct Volume *tv;
1496 register struct VolumeDiskData *td;
1497 struct volser_trans *tt;
1500 tt = FindTrans(atrans);
1503 if (tt->vflags & VTDeleted) {
1504 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1509 strcpy(tt->lastProcName, "GetStatus");
1510 tt->rxCallPtr = acid;
1513 tt->rxCallPtr = (struct rx_call *)0;
1518 td = &tv->header->diskstuff;
1519 astatus->volID = td->id;
1520 astatus->nextUnique = td->uniquifier;
1521 astatus->type = td->type;
1522 astatus->parentID = td->parentId;
1523 astatus->cloneID = td->cloneId;
1524 astatus->backupID = td->backupId;
1525 astatus->restoredFromID = td->restoredFromId;
1526 astatus->maxQuota = td->maxquota;
1527 astatus->minQuota = td->minquota;
1528 astatus->owner = td->owner;
1529 astatus->creationDate = td->creationDate;
1530 astatus->accessDate = td->accessDate;
1531 astatus->updateDate = td->updateDate;
1532 astatus->expirationDate = td->expirationDate;
1533 astatus->backupDate = td->backupDate;
1534 astatus->copyDate = td->copyDate;
1535 tt->rxCallPtr = (struct rx_call *)0;
1537 return VOLSERTRELE_ERROR;
1543 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1544 register struct volintInfo *astatus)
1548 code = VolSetInfo(acid, atrans, astatus);
1549 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1554 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1555 register struct volintInfo *astatus)
1557 register struct Volume *tv;
1558 register struct VolumeDiskData *td;
1559 struct volser_trans *tt;
1560 char caller[MAXKTCNAMELEN];
1563 if (!afsconf_SuperUser(tdir, acid, caller))
1564 return VOLSERBAD_ACCESS; /*not a super user */
1565 tt = FindTrans(atrans);
1568 if (tt->vflags & VTDeleted) {
1569 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1573 strcpy(tt->lastProcName, "SetStatus");
1574 tt->rxCallPtr = acid;
1577 tt->rxCallPtr = (struct rx_call *)0;
1582 td = &tv->header->diskstuff;
1584 * Add more fields as necessary
1586 if (astatus->maxquota != -1)
1587 td->maxquota = astatus->maxquota;
1588 if (astatus->dayUse != -1)
1589 td->dayUse = astatus->dayUse;
1590 if (astatus->creationDate != -1)
1591 td->creationDate = astatus->creationDate;
1592 if (astatus->updateDate != -1)
1593 td->updateDate = astatus->updateDate;
1594 if (astatus->spare2 != -1)
1595 td->volUpdateCounter = (unsigned int)astatus->spare2;
1596 VUpdateVolume(&error, tv);
1597 tt->rxCallPtr = (struct rx_call *)0;
1599 return VOLSERTRELE_ERROR;
1605 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1609 code = VolGetName(acid, atrans, aname);
1610 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1615 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1617 register struct Volume *tv;
1618 register struct VolumeDiskData *td;
1619 struct volser_trans *tt;
1622 /* We need to at least fill it in */
1623 *aname = (char *)malloc(1);
1626 tt = FindTrans(atrans);
1629 if (tt->vflags & VTDeleted) {
1630 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1634 strcpy(tt->lastProcName, "GetName");
1635 tt->rxCallPtr = acid;
1638 tt->rxCallPtr = (struct rx_call *)0;
1643 td = &tv->header->diskstuff;
1644 len = strlen(td->name) + 1; /* don't forget the null */
1646 tt->rxCallPtr = (struct rx_call *)0;
1650 *aname = (char *)realloc(*aname, len);
1651 strcpy(*aname, td->name);
1652 tt->rxCallPtr = (struct rx_call *)0;
1654 return VOLSERTRELE_ERROR;
1659 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1662 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1663 afs_int32 parentId, afs_int32 cloneId)
1669 /*return a list of all partitions on the server. The non mounted
1670 *partitions are returned as -1 in the corresponding slot in partIds*/
1672 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1676 code = VolListPartitions(acid, partIds);
1677 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1682 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1687 strcpy(namehead, "/vicep"); /*7 including null terminator */
1689 /* Just return attached partitions. */
1691 for (i = 0; i < 26; i++) {
1692 namehead[6] = i + 'a';
1693 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1699 /*return a list of all partitions on the server. The non mounted
1700 *partitions are returned as -1 in the corresponding slot in partIds*/
1702 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1706 code = XVolListPartitions(acid, pEntries);
1707 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1712 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1714 struct stat rbuf, pbuf;
1716 struct partList partList;
1717 struct DiskPartition64 *dp;
1720 strcpy(namehead, "/vicep"); /*7 including null terminator */
1722 /* Only report attached partitions */
1723 for (i = 0; i < VOLMAXPARTS; i++) {
1724 #ifdef AFS_DEMAND_ATTACH_FS
1725 dp = VGetPartitionById(i, 0);
1728 namehead[6] = i + 'a';
1732 namehead[6] = 'a' + (k / 26);
1733 namehead[7] = 'a' + (k % 26);
1736 dp = VGetPartition(namehead, 0);
1739 partList.partId[j++] = i;
1741 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1742 if (!pEntries->partEntries_val)
1744 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1746 pEntries->partEntries_len = j;
1751 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1753 ExtractVolId(char vname[])
1756 char name[VOLSER_MAXVOLNAME + 1];
1758 strcpy(name, vname);
1760 while (name[i] == 'V' || name[i] == '0')
1763 name[11] = '\0'; /* smash the "." */
1764 return (atol(&name[i]));
1767 /*return the name of the next volume header in the directory associated with dirp and dp.
1768 *the volume id is returned in volid, and volume header name is returned in volname*/
1770 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1774 dp = readdir(dirp); /*read next entry in the directory */
1776 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1777 *volid = ExtractVolId(dp->d_name);
1778 strcpy(volname, dp->d_name);
1779 return 0; /*return the name of the file representing a volume */
1781 strcpy(volname, "");
1782 return 0; /*volname doesnot represent a volume */
1785 strcpy(volname, "EOD");
1786 return 0; /*end of directory */
1792 * volint vol info structure type.
1795 VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
1796 VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
1797 } volint_info_type_t;
1800 * handle to various on-wire vol info types.
1803 volint_info_type_t volinfo_type;
1809 } volint_info_handle_t;
1812 * store value to a field at the appropriate location in on-wire structure.
1814 #define VOLINT_INFO_STORE(handle, name, val) \
1816 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
1817 (handle)->volinfo_ptr.base->name = (val); \
1819 (handle)->volinfo_ptr.ext->name = (val); \
1824 * get pointer to appropriate offset of field in on-wire structure.
1826 #define VOLINT_INFO_PTR(handle, name) \
1827 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
1828 &((handle)->volinfo_ptr.base->name) : \
1829 &((handle)->volinfo_ptr.ext->name))
1832 * fill in appropriate type of on-wire volume metadata structure.
1834 * @param vp pointer to volume object
1835 * @param handle pointer to wire format handle object
1837 * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
1838 * @pre handle object must have a valid pointer and enumeration value
1840 * @note passing a NULL value for vp means that the fileserver doesn't
1841 * know about this particular volume, thus implying it is offline.
1843 * @return operation status
1848 FillVolInfo(Volume * vp, volint_info_handle_t * handle)
1850 unsigned int numStatBytes, now;
1851 register struct VolumeDiskData *hdr = &vp->header->diskstuff;
1853 /*read in the relevant info */
1854 strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
1855 VOLINT_INFO_STORE(handle, status, VOK); /*its ok */
1856 VOLINT_INFO_STORE(handle, volid, hdr->id);
1857 VOLINT_INFO_STORE(handle, type, hdr->type); /*if ro volume */
1858 VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId); /*if rw volume */
1859 VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
1860 VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
1861 VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
1862 VOLINT_INFO_STORE(handle, size, hdr->diskused);
1863 VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
1864 VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
1865 now = FT_ApproxTime();
1866 if ((now - hdr->dayUseDate) > OneDay) {
1867 VOLINT_INFO_STORE(handle, dayUse, 0);
1869 VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
1871 VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
1872 VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
1873 VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
1874 VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
1876 #ifdef AFS_DEMAND_ATTACH_FS
1878 * for DAFS, we "lie" about volume state --
1879 * instead of returning the raw state from the disk header,
1880 * we compute state based upon the fileserver's internal
1881 * in-core state enumeration value reported to us via fssync,
1882 * along with the blessed and inService flags from the header.
1883 * -- tkeiser 11/27/2007
1886 /* Conditions that offline status is based on:
1887 volume is unattached state
1888 volume state is in (one of several error states)
1889 volume not in service
1890 volume is not marked as blessed (not on hold)
1891 volume in salvage req. state
1892 volume needsSalvaged
1893 next op would set volume offline
1894 next op would not leave volume online (based on several conditions)
1897 (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1898 VIsErrorState(V_attachState(vp)) ||
1901 (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
1902 hdr->needsSalvaged ||
1903 (vp->pending_vol_op &&
1904 (vp->pending_vol_op->com.command == FSYNC_VOL_OFF ||
1905 !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
1908 VOLINT_INFO_STORE(handle, inUse, 0);
1910 VOLINT_INFO_STORE(handle, inUse, 1);
1913 /* offline status based on program type, where != fileServer enum (1) is offline */
1914 if (hdr->inUse == fileServer) {
1915 VOLINT_INFO_STORE(handle, inUse, 1);
1917 VOLINT_INFO_STORE(handle, inUse, 0);
1922 switch(handle->volinfo_type) {
1923 /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
1924 case VOLINT_INFO_TYPE_BASE:
1926 #ifdef AFS_DEMAND_ATTACH_FS
1927 /* see comment above where we set inUse bit */
1928 if (hdr->needsSalvaged ||
1929 (vp && VIsErrorState(V_attachState(vp)))) {
1930 handle->volinfo_ptr.base->needsSalvaged = 1;
1932 handle->volinfo_ptr.base->needsSalvaged = 0;
1935 handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
1937 handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
1938 handle->volinfo_ptr.base->spare0 = hdr->minquota;
1939 handle->volinfo_ptr.base->spare1 =
1940 (long)hdr->weekUse[0] +
1941 (long)hdr->weekUse[1] +
1942 (long)hdr->weekUse[2] +
1943 (long)hdr->weekUse[3] +
1944 (long)hdr->weekUse[4] +
1945 (long)hdr->weekUse[5] +
1946 (long)hdr->weekUse[6];
1947 handle->volinfo_ptr.base->flags = 0;
1948 handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
1949 handle->volinfo_ptr.base->spare3 = 0;
1953 case VOLINT_INFO_TYPE_EXT:
1955 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1956 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1959 * Copy out the stat fields in a single operation.
1961 if ((now - hdr->dayUseDate) > OneDay) {
1962 memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1965 memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1966 (char *)&(hdr->stat_reads[0]),
1976 * get struct Volume out of the fileserver.
1978 * @param[in] volumeId volumeId for which we want state information
1979 * @param[in] pname partition name string
1980 * @param[inout] vp pointer to pointer to Volume object which
1981 * will be populated (see note)
1983 * @return operation status
1985 * @retval non-zero failure
1987 * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
1992 GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
1997 res.hdr.response_len = sizeof(res.hdr);
1998 res.payload.buf = *vp;
1999 res.payload.len = sizeof(Volume);
2001 code = FSYNC_VolOp(volumeId,
2007 if (code != SYNC_OK) {
2008 switch (res.hdr.reason) {
2009 case FSYNC_WRONG_PART:
2010 case FSYNC_UNKNOWN_VOLID:
2021 * mode of volume list operation.
2024 VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
2025 VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
2026 } vol_info_list_mode_t;
2029 * abstract interface to populate wire-format volume metadata structures.
2031 * @param[in] partId partition id
2032 * @param[in] volumeId volume id
2033 * @param[in] pname partition name
2034 * @param[in] volname volume file name
2035 * @param[in] handle handle to on-wire volume metadata object
2036 * @param[in] mode listing mode
2038 * @return operation status
2040 * @retval -2 DESTROY_ME flag is set
2041 * @retval -1 general failure; some data filled in
2042 * @retval -3 couldn't create vtrans; some data filled in
2045 GetVolInfo(afs_uint32 partId,
2046 afs_uint32 volumeId,
2049 volint_info_handle_t * handle,
2050 vol_info_list_mode_t mode)
2055 struct volser_trans *ttc = NULL;
2056 struct Volume *fill_tv, *tv = NULL;
2057 #ifdef AFS_DEMAND_ATTACH_FS
2058 struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
2059 SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
2060 SYNC_response fs_res; /* Response handle for the pending_vol_op */
2061 FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
2063 /* Set up response handle for pending_vol_op */
2064 fs_res.hdr.response_len = sizeof(fs_res.hdr);
2065 fs_res.payload.buf = fs_res_buf;
2066 fs_res.payload.len = SYNC_PROTO_MAX_LEN;
2069 ttc = NewTrans(volumeId, partId);
2072 VOLINT_INFO_STORE(handle, status, VBUSY);
2073 VOLINT_INFO_STORE(handle, volid, volumeId);
2077 /* Get volume from volserver */
2078 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2080 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
2081 volumeId, pname, volname, error);
2086 * please note that destroyMe and needsSalvaged checks used to be ordered
2087 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2088 * more correct to check destroyMe before needsSalvaged.
2089 * -- tkeiser 11/28/2007
2092 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2094 case VOL_INFO_LIST_MULTIPLE:
2098 case VOL_INFO_LIST_SINGLE:
2099 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
2100 volumeId, pname, volname);
2107 if (tv->header->diskstuff.needsSalvaged) {
2108 /*this volume will be salvaged */
2109 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2110 volumeId, pname, volname);
2113 #ifdef AFS_DEMAND_ATTACH_FS
2114 /* If using DAFS, get volume from fsserver */
2115 if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
2119 /* fs_tv is a shallow copy, must populate certain structures before passing along */
2120 if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) {
2121 /* If we if the pending vol op */
2122 memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
2123 fs_tv->pending_vol_op=&pending_vol_op_res;
2125 fs_tv->pending_vol_op=NULL;
2128 /* populate the header from the volserver copy */
2129 fs_tv->header=tv->header;
2131 /* When using DAFS, use the fs volume info, populated with required structures */
2134 /* When not using DAFS, just use the local volume info */
2138 /* ok, we have all the data we need; fill in the on-wire struct */
2139 code = FillVolInfo(fill_tv, handle);
2143 VOLINT_INFO_STORE(handle, status, 0);
2144 strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
2145 VOLINT_INFO_STORE(handle, volid, volumeId);
2148 VDetachVolume(&error, tv);
2151 VOLINT_INFO_STORE(handle, status, 0);
2152 strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
2153 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2154 volumeId, pname, volname);
2158 DeleteTrans(ttc, 1);
2165 /*return the header information about the <volid> */
2167 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2168 volumeId, volEntries *volumeInfo)
2172 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2173 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
2178 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2179 volumeId, volEntries *volumeInfo)
2182 struct DiskPartition64 *partP;
2183 char pname[9], volname[20];
2184 afs_int32 error = 0;
2190 volint_info_handle_t handle;
2192 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2193 if (!volumeInfo->volEntries_val)
2195 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2197 pntr = volumeInfo->volEntries_val;
2198 volumeInfo->volEntries_len = 1;
2199 if (GetPartName(partid, pname))
2200 return VOLSERILLEGAL_PARTITION;
2201 if (!(partP = VGetPartition(pname, 0)))
2202 return VOLSERILLEGAL_PARTITION;
2203 dirp = opendir(VPartitionPath(partP));
2205 return VOLSERILLEGAL_PARTITION;
2207 strcpy(volname, "");
2209 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2211 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2212 GetNextVol(dirp, volname, &volid);
2213 continue; /*back to while loop */
2216 if (volid == volumeId) { /*copy other things too */
2221 GetNextVol(dirp, volname, &volid);
2225 #ifndef AFS_PTHREAD_ENV
2226 IOMGR_Poll(); /*make sure that the client does not time out */
2229 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2230 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2232 code = GetVolInfo(partid,
2237 VOL_INFO_LIST_SINGLE);
2241 return (found) ? 0 : ENODEV;
2244 /*------------------------------------------------------------------------
2245 * EXPORTED SAFSVolXListOneVolume
2248 * Returns extended info on volume a_volID on partition a_partID.
2251 * a_rxCidP : Pointer to the Rx call we're performing.
2252 * a_partID : Partition for which we want the extended list.
2253 * a_volID : Volume ID we wish to know about.
2254 * a_volumeXInfoP : Ptr to the extended info blob.
2257 * 0 Successful operation
2258 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2261 * Nothing interesting.
2265 *------------------------------------------------------------------------*/
2268 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2269 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2273 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2274 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2279 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2280 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2281 { /*SAFSVolXListOneVolume */
2283 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2284 struct DiskPartition64 *partP; /*Ptr to partition */
2285 char pname[9], volname[20]; /*Partition, volume names */
2286 afs_int32 error; /*Error code */
2287 DIR *dirp; /*Partition directory ptr */
2288 afs_int32 currVolID; /*Current volume ID */
2289 int found = 0; /*Did we find the volume we need? */
2292 volint_info_handle_t handle;
2295 * Set up our pointers for action, marking our structure to hold exactly
2296 * one entry. Also, assume we'll fail in our quest.
2298 a_volumeXInfoP->volXEntries_val =
2299 (volintXInfo *) malloc(sizeof(volintXInfo));
2300 if (!a_volumeXInfoP->volXEntries_val)
2302 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2304 xInfoP = a_volumeXInfoP->volXEntries_val;
2305 a_volumeXInfoP->volXEntries_len = 1;
2309 * If the partition name we've been given is bad, bogue out.
2311 if (GetPartName(a_partID, pname))
2312 return (VOLSERILLEGAL_PARTITION);
2315 * Open the directory representing the given AFS parttion. If we can't
2318 if (!(partP = VGetPartition(pname, 0)))
2319 return VOLSERILLEGAL_PARTITION;
2320 dirp = opendir(VPartitionPath(partP));
2322 return (VOLSERILLEGAL_PARTITION);
2324 strcpy(volname, "");
2327 * Sweep through the partition directory, looking for the desired entry.
2328 * First, of course, figure out how many stat bytes to copy out of each
2331 while (strcmp(volname, "EOD") && !found) {
2333 * If this is not a volume, move on to the next entry in the
2334 * partition's directory.
2336 if (!strcmp(volname, "")) {
2337 GetNextVol(dirp, volname, &currVolID);
2341 if (currVolID == a_volID) {
2343 * We found the volume entry we're interested. Pull out the
2344 * extended information, remembering to poll (so that the client
2345 * doesn't time out) and to set up a transaction on the volume.
2349 } /*Found desired volume */
2351 GetNextVol(dirp, volname, &currVolID);
2355 #ifndef AFS_PTHREAD_ENV
2359 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2360 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2362 code = GetVolInfo(a_partID,
2367 VOL_INFO_LIST_SINGLE);
2372 * Clean up before going to dinner: close the partition directory,
2373 * return the proper value.
2376 return (found) ? 0 : ENODEV;
2377 } /*SAFSVolXListOneVolume */
2379 /*returns all the volumes on partition partid. If flags = 1 then all the
2380 * relevant info about the volumes is also returned */
2382 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2383 volEntries *volumeInfo)
2387 code = VolListVolumes(acid, partid, flags, volumeInfo);
2388 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2393 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2394 volEntries *volumeInfo)
2397 struct DiskPartition64 *partP;
2398 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2399 char pname[9], volname[20];
2400 afs_int32 error = 0;
2405 volint_info_handle_t handle;
2407 volumeInfo->volEntries_val =
2408 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2409 if (!volumeInfo->volEntries_val)
2411 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2413 pntr = volumeInfo->volEntries_val;
2414 volumeInfo->volEntries_len = 0;
2415 if (GetPartName(partid, pname))
2416 return VOLSERILLEGAL_PARTITION;
2417 if (!(partP = VGetPartition(pname, 0)))
2418 return VOLSERILLEGAL_PARTITION;
2419 dirp = opendir(VPartitionPath(partP));
2421 return VOLSERILLEGAL_PARTITION;
2422 strcpy(volname, "");
2424 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2426 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2427 GetNextVol(dirp, volname, &volid);
2428 continue; /*back to while loop */
2431 if (flags) { /*copy other things too */
2432 #ifndef AFS_PTHREAD_ENV
2433 IOMGR_Poll(); /*make sure that the client does not time out */
2436 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2437 handle.volinfo_ptr.base = pntr;
2440 code = GetVolInfo(partid,
2445 VOL_INFO_LIST_MULTIPLE);
2446 if (code == -2) { /* DESTROY_ME flag set */
2450 pntr->volid = volid;
2451 /*just volids are needed */
2456 volumeInfo->volEntries_len += 1;
2457 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2458 /*running out of space, allocate more space */
2459 allocSize = (allocSize * 3) / 2;
2461 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2462 allocSize * sizeof(volintInfo));
2465 return VOLSERNO_MEMORY;
2467 volumeInfo->volEntries_val = pntr; /* point to new block */
2468 /* set pntr to the right position */
2469 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2474 GetNextVol(dirp, volname, &volid);
2482 /*------------------------------------------------------------------------
2483 * EXPORTED SAFSVolXListVolumes
2486 * Returns all the volumes on partition a_partID. If a_flags
2487 * is set to 1, then all the relevant extended volume information
2491 * a_rxCidP : Pointer to the Rx call we're performing.
2492 * a_partID : Partition for which we want the extended list.
2493 * a_flags : Various flags.
2494 * a_volumeXInfoP : Ptr to the extended info blob.
2497 * 0 Successful operation
2498 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2499 * VOLSERNO_MEMORY if we ran out of memory allocating
2503 * Nothing interesting.
2507 *------------------------------------------------------------------------*/
2510 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2511 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2515 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2516 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2521 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2522 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2523 { /*SAFSVolXListVolumes */
2525 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2526 struct DiskPartition64 *partP; /*Ptr to partition */
2527 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2528 char pname[9], volname[20]; /*Partition, volume names */
2529 afs_int32 error = 0; /*Return code */
2530 DIR *dirp; /*Partition directory ptr */
2531 afs_int32 volid; /*Current volume ID */
2534 volint_info_handle_t handle;
2537 * Allocate a large array of extended volume info structures, then
2538 * set it up for action.
2540 a_volumeXInfoP->volXEntries_val =
2541 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2542 if (!a_volumeXInfoP->volXEntries_val)
2544 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2546 xInfoP = a_volumeXInfoP->volXEntries_val;
2547 a_volumeXInfoP->volXEntries_len = 0;
2550 * If the partition name we've been given is bad, bogue out.
2552 if (GetPartName(a_partID, pname))
2553 return (VOLSERILLEGAL_PARTITION);
2556 * Open the directory representing the given AFS parttion. If we can't
2559 if (!(partP = VGetPartition(pname, 0)))
2560 return VOLSERILLEGAL_PARTITION;
2561 dirp = opendir(VPartitionPath(partP));
2563 return (VOLSERILLEGAL_PARTITION);
2564 strcpy(volname, "");
2567 * Sweep through the partition directory, acting on each entry. First,
2568 * of course, figure out how many stat bytes to copy out of each volume.
2570 while (strcmp(volname, "EOD")) {
2573 * If this is not a volume, move on to the next entry in the
2574 * partition's directory.
2576 if (!strcmp(volname, "")) {
2577 GetNextVol(dirp, volname, &volid);
2583 * Full info about the volume desired. Poll to make sure the
2584 * client doesn't time out, then start up a new transaction.
2586 #ifndef AFS_PTHREAD_ENV
2590 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2591 handle.volinfo_ptr.ext = xInfoP;
2593 code = GetVolInfo(a_partID,
2598 VOL_INFO_LIST_MULTIPLE);
2599 if (code == -2) { /* DESTROY_ME flag set */
2604 * Just volume IDs are needed.
2606 xInfoP->volid = volid;
2611 * Bump the pointer in the data area we're building, along with
2612 * the count of the number of entries it contains.
2615 (a_volumeXInfoP->volXEntries_len)++;
2616 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2618 * We're running out of space in the area we've built. Grow it.
2620 allocSize = (allocSize * 3) / 2;
2621 xInfoP = (volintXInfo *)
2622 realloc((char *)a_volumeXInfoP->volXEntries_val,
2623 (allocSize * sizeof(volintXInfo)));
2624 if (xInfoP == NULL) {
2626 * Bummer, no memory. Bag it, tell our caller what went wrong.
2629 return (VOLSERNO_MEMORY);
2633 * Memory reallocation worked. Correct our pointers so they
2634 * now point to the new block and the current open position within
2637 a_volumeXInfoP->volXEntries_val = xInfoP;
2639 a_volumeXInfoP->volXEntries_val +
2640 a_volumeXInfoP->volXEntries_len;
2644 GetNextVol(dirp, volname, &volid);
2645 } /*Sweep through the partition directory */
2648 * We've examined all entries in the partition directory. Close it,
2649 * delete our transaction (if any), and go home happy.
2654 } /*SAFSVolXListVolumes */
2656 /*this call is used to monitor the status of volser for debugging purposes.
2657 *information about all the active transactions is returned in transInfo*/
2659 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2663 code = VolMonitor(acid, transInfo);
2664 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2669 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2671 transDebugInfo *pntr;
2672 afs_int32 allocSize = 50;
2673 struct volser_trans *tt, *allTrans;
2675 transInfo->transDebugEntries_val =
2676 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2677 if (!transInfo->transDebugEntries_val)
2679 pntr = transInfo->transDebugEntries_val;
2680 transInfo->transDebugEntries_len = 0;
2681 allTrans = TransList();
2682 if (allTrans == (struct volser_trans *)0)
2683 return 0; /*no active transactions */
2684 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2685 pntr->tid = tt->tid;
2686 pntr->time = tt->time;
2687 pntr->creationTime = tt->creationTime;
2688 pntr->returnCode = tt->returnCode;
2689 pntr->volid = tt->volid;
2690 pntr->partition = tt->partition;
2691 pntr->iflags = tt->iflags;
2692 pntr->vflags = tt->vflags;
2693 pntr->tflags = tt->tflags;
2694 strcpy(pntr->lastProcName, tt->lastProcName);
2695 pntr->callValid = 0;
2696 if (tt->rxCallPtr) { /*record call related info */
2697 pntr->callValid = 1;
2698 pntr->readNext = tt->rxCallPtr->rnext;
2699 pntr->transmitNext = tt->rxCallPtr->tnext;
2700 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2701 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2704 transInfo->transDebugEntries_len += 1;
2705 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2706 allocSize = (allocSize * 3) / 2;
2708 (transDebugInfo *) realloc((char *)transInfo->
2709 transDebugEntries_val,
2711 sizeof(transDebugInfo));
2712 transInfo->transDebugEntries_val = pntr;
2714 transInfo->transDebugEntries_val +
2715 transInfo->transDebugEntries_len;
2716 /*set pntr to right position */
2725 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2729 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2730 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2731 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2737 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2740 afs_int32 error = 0;
2741 register struct volser_trans *tt;
2742 char caller[MAXKTCNAMELEN];
2744 if (strlen(name) > 31)
2745 return VOLSERBADNAME;
2746 if (!afsconf_SuperUser(tdir, acid, caller))
2747 return VOLSERBAD_ACCESS; /*not a super user */
2748 /* find the trans */
2749 tt = FindTrans(atid);
2752 if (tt->vflags & VTDeleted) {
2753 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2757 strcpy(tt->lastProcName, "SetIdsTypes");
2758 tt->rxCallPtr = acid;
2762 V_backupId(tv) = backupId;
2763 V_cloneId(tv) = cloneId;
2764 V_parentId(tv) = pId;
2765 strcpy((&V_disk(tv))->name, name);
2766 VUpdateVolume(&error, tv);
2768 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2772 tt->rxCallPtr = (struct rx_call *)0;
2773 if (TRELE(tt) && !error)
2774 return VOLSERTRELE_ERROR;
2778 tt->rxCallPtr = (struct rx_call *)0;
2779 if (TRELE(tt) && !error)
2780 return VOLSERTRELE_ERROR;
2785 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2789 code = VolSetDate(acid, atid, cdate);
2790 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2796 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2799 afs_int32 error = 0;
2800 register struct volser_trans *tt;
2801 char caller[MAXKTCNAMELEN];
2803 if (!afsconf_SuperUser(tdir, acid, caller))
2804 return VOLSERBAD_ACCESS; /*not a super user */
2805 /* find the trans */
2806 tt = FindTrans(atid);
2809 if (tt->vflags & VTDeleted) {
2810 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2814 strcpy(tt->lastProcName, "SetDate");
2815 tt->rxCallPtr = acid;
2818 V_creationDate(tv) = cdate;
2819 VUpdateVolume(&error, tv);
2821 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2825 tt->rxCallPtr = (struct rx_call *)0;
2826 if (TRELE(tt) && !error)
2827 return VOLSERTRELE_ERROR;
2831 tt->rxCallPtr = (struct rx_call *)0;
2832 if (TRELE(tt) && !error)
2833 return VOLSERTRELE_ERROR;
2838 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2844 char caller[MAXKTCNAMELEN];
2846 register struct volser_trans *ttc;
2847 char pname[16], volname[20];
2848 struct DiskPartition64 *partP;
2849 afs_int32 ret = ENODEV;
2852 if (!afsconf_SuperUser(tdir, acid, caller))
2853 return VOLSERBAD_ACCESS; /*not a super user */
2854 if (GetPartName(partId, pname))
2855 return VOLSERILLEGAL_PARTITION;
2856 if (!(partP = VGetPartition(pname, 0)))
2857 return VOLSERILLEGAL_PARTITION;
2858 dirp = opendir(VPartitionPath(partP));
2860 return VOLSERILLEGAL_PARTITION;
2861 strcpy(volname, "");
2862 ttc = (struct volser_trans *)0;
2864 while (strcmp(volname, "EOD")) {
2865 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2866 GetNextVol(dirp, volname, &volid);
2867 continue; /*back to while loop */
2870 if (volid == volumeId) { /*copy other things too */
2871 #ifndef AFS_PTHREAD_ENV
2872 IOMGR_Poll(); /*make sure that the client doesnot time out */
2874 ttc = NewTrans(volumeId, partId);
2878 #ifdef AFS_NAMEI_ENV
2879 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2881 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2885 GetNextVol(dirp, volname, &volid);
2889 DeleteTrans(ttc, 1);
2890 ttc = (struct volser_trans *)0;
2899 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2900 register struct volintSize *size)
2903 register struct volser_trans *tt;
2904 char caller[MAXKTCNAMELEN];
2906 if (!afsconf_SuperUser(tdir, acid, caller))
2907 return VOLSERBAD_ACCESS; /*not a super user */
2908 tt = FindTrans(fromTrans);
2911 if (tt->vflags & VTDeleted) {
2915 strcpy(tt->lastProcName, "GetSize");
2916 tt->rxCallPtr = acid;
2917 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2918 tt->rxCallPtr = (struct rx_call *)0;
2920 return VOLSERTRELE_ERROR;
2922 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2926 /* GetPartName - map partid (a decimal number) into pname (a string)
2927 * Since for NT we actually want to return the drive name, we map through the
2931 GetPartName(afs_int32 partid, char *pname)
2936 strcpy(pname, "/vicep");
2937 pname[6] = 'a' + partid;
2940 } else if (partid < VOLMAXPARTS) {
2941 strcpy(pname, "/vicep");
2943 pname[6] = 'a' + (partid / 26);
2944 pname[7] = 'a' + (partid % 26);