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>
17 #include <sys/types.h>
26 #include <netinet/in.h>
35 #include <afs/afsint.h>
37 #ifdef AFS_PTHREAD_ENV
39 #else /* AFS_PTHREAD_ENV */
40 #include <afs/assert.h>
41 #endif /* AFS_PTHREAD_ENV */
42 #include <afs/prs_fs.h>
46 #include <afs/cellconfig.h>
49 #include <afs/ihandle.h>
51 #include <afs/ntops.h>
53 #include <afs/vnode.h>
54 #include <afs/volume.h>
55 #include <afs/volume_inline.h>
56 #include <afs/partition.h>
58 #include <afs/daemon_com.h>
59 #include <afs/fssync.h>
61 #include "afs/audit.h"
67 #include "volser_prototypes.h"
70 extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
71 extern struct afsconf_dir *tdir;
73 /* Needed by Irix. Leave, or include a header */
74 extern char *volutil_PartitionName();
76 extern void LogError(afs_int32 errcode);
78 /* Forward declarations */
79 static int GetPartName(afs_int32 partid, char *pname);
81 #define OneDay (24*60*60)
87 afs_int32 localTid = 1;
88 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
89 VolDeleteVolume(), VolClone();
90 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
91 VolForward(), VolDump();
92 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
93 VolSetInfo(), VolGetName();
94 afs_int32 VolListPartitions(), VolListOneVolume(),
95 VolXListOneVolume(), VolXListVolumes();
96 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
97 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
99 /* this call unlocks all of the partition locks we've set */
103 register struct DiskPartition64 *tp;
104 for (tp = DiskPartitionList; tp; tp = tp->next) {
105 if (tp->lock_fd != INVALID_FD) {
106 close(tp->lock_fd); /* releases flock held on this partition */
107 tp->lock_fd = INVALID_FD;
113 /* get partition id from a name */
115 PartitionID(char *aname)
118 register int code = 0;
123 return -1; /* unknown */
125 /* otherwise check for vicepa or /vicepa, or just plain "a" */
127 if (!strncmp(aname, "/vicep", 6)) {
128 strncpy(ascii, aname + 6, 2);
130 return -1; /* bad partition name */
131 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
132 * from 0. Do the appropriate conversion */
134 /* one char name, 0..25 */
135 if (ascii[0] < 'a' || ascii[0] > 'z')
136 return -1; /* wrongo */
137 return ascii[0] - 'a';
139 /* two char name, 26 .. <whatever> */
140 if (ascii[0] < 'a' || ascii[0] > 'z')
141 return -1; /* wrongo */
142 if (ascii[1] < 'a' || ascii[1] > 'z')
143 return -1; /* just as bad */
144 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
145 if (code > VOLMAXPARTS)
152 ConvertVolume(afs_uint32 avol, char *aname, afs_int32 asize)
156 /* 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 */
157 (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
162 ConvertPartition(int apartno, char *aname, int asize)
168 strcpy(aname, "/vicep");
170 aname[6] = 'a' + apartno;
174 aname[6] = 'a' + (apartno / 26);
175 aname[7] = 'a' + (apartno % 26);
181 /* the only attach function that takes a partition is "...ByName", so we use it */
183 XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int amode)
185 char pbuf[30], vbuf[20];
186 register struct Volume *tv;
188 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
192 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
196 tv = VAttachVolumeByName((Error *)error, pbuf, vbuf, amode);
200 /* Adapted from the file server; create a root directory for this volume */
202 ViceCreateRoot(Volume *vp)
205 struct acl_accessList *ACL;
207 Inode inodeNumber, nearInode;
208 struct VnodeDiskObject *vnode;
209 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
215 vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
218 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
220 V_pref(vp, nearInode);
222 IH_CREATE(V_linkHandle(vp), V_device(vp),
223 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
225 assert(VALID_INO(inodeNumber));
227 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
228 did.Volume = V_id(vp);
229 did.Vnode = (VnodeId) 1;
232 assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
233 DFlush(); /* flush all modified dir buffers out */
234 DZap((afs_int32 *)&dir); /* Remove all buffers for this dir */
235 length = Length(&dir); /* Remember size of this directory */
237 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
239 /* build a single entry ACL that gives all rights to system:administrators */
240 /* this section of code assumes that access list format is not going to
243 ACL = VVnodeDiskACL(vnode);
244 ACL->size = sizeof(struct acl_accessList);
245 ACL->version = ACL_ACLVERSION;
249 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
250 ACL->entries[0].rights =
251 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
252 | PRSFS_LOCK | PRSFS_ADMINISTER;
254 vnode->type = vDirectory;
256 vnode->modeBits = 0777;
257 vnode->linkCount = 2;
258 VNDISK_SET_LEN(vnode, length);
259 vnode->uniquifier = 1;
260 V_uniquifier(vp) = vnode->uniquifier + 1;
261 vnode->dataVersion = 1;
262 VNDISK_SET_INO(vnode, inodeNumber);
263 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
267 vnode->vnodeMagic = vcp->magic;
269 IH_INIT(h, vp->device, V_parentId(vp),
270 vp->vnodeIndex[vLarge].handle->ih_ino);
273 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
275 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
276 assert(code == SIZEOF_LARGEDISKVNODE);
277 FDH_REALLYCLOSE(fdP);
279 VNDISK_GET_LEN(length, vnode);
280 V_diskused(vp) = nBlocks(length);
287 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
291 struct diskPartition64 *dp = (struct diskPartition64 *)
292 malloc(sizeof(struct diskPartition64));
294 code = VolPartitionInfo(acid, pname, dp);
296 strncpy(partition->name, dp->name, 32);
297 strncpy(partition->devName, dp->devName, 32);
298 partition->lock_fd = dp->lock_fd;
299 partition->free=RoundInt64ToInt32(dp->free);
300 partition->minFree=RoundInt64ToInt32(dp->minFree);
303 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
308 SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
313 code = VolPartitionInfo(acid, pname, partition);
314 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
319 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
322 register struct DiskPartition64 *dp;
325 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
328 dp = VGetPartition(pname, 0);
330 strncpy(partition->name, dp->name, 32);
331 strncpy(partition->devName, dp->devName, 32);
332 partition->lock_fd = (int)dp->lock_fd;
333 partition->free = dp->free;
334 partition->minFree = dp->totalUsable;
337 return VOLSERILLEGAL_PARTITION;
340 /* obliterate a volume completely, and slowly. */
342 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
346 code = VolNukeVolume(acid, apartID, avolID);
347 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
352 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
356 register afs_int32 code;
358 char caller[MAXKTCNAMELEN];
360 /* check for access */
361 if (!afsconf_SuperUser(tdir, acid, caller))
362 return VOLSERBAD_ACCESS;
364 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
366 if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
368 /* we first try to attach the volume in update mode, so that the file
369 * server doesn't try to use it (and abort) while (or after) we delete it.
370 * If we don't get the volume, that's fine, too. We just won't put it back.
372 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
373 code = nuke(partName, avolID);
375 VDetachVolume(&error, tvp);
379 /* create a new volume, with name aname, on the specified partition (1..n)
380 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
381 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
382 * for the volume id (useful for things like volume restore).
383 * Return the new volume id in *avolid.
386 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
387 afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
393 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
394 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
395 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
401 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
402 afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
407 afs_int32 junk; /* discardable error code */
409 afs_int32 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_uint32 purgeId,
532 afs_int32 newType, char *newName, afs_uint32 *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_uint32 purgeId,
545 afs_int32 newType, char *newName, afs_uint32 *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 */
584 return VOLSERVOLBUSY;
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_uint32 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 */
756 return VOLSERVOLBUSY;
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_uint32 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_uint32 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_uint32 *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_uint32 parentId, afs_uint32 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)
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_uint32 * 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)
2053 struct volser_trans *ttc = NULL;
2054 struct Volume *fill_tv, *tv = NULL;
2055 #ifdef AFS_DEMAND_ATTACH_FS
2056 struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
2057 SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
2058 SYNC_response fs_res; /* Response handle for the pending_vol_op */
2059 FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
2061 /* Set up response handle for pending_vol_op */
2062 fs_res.hdr.response_len = sizeof(fs_res.hdr);
2063 fs_res.payload.buf = fs_res_buf;
2064 fs_res.payload.len = SYNC_PROTO_MAX_LEN;
2067 ttc = NewTrans(volumeId, partId);
2070 VOLINT_INFO_STORE(handle, status, VOLSERVOLBUSY);
2071 VOLINT_INFO_STORE(handle, volid, volumeId);
2075 /* Get volume from volserver */
2076 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2078 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
2079 volumeId, pname, volname, error);
2084 * please note that destroyMe and needsSalvaged checks used to be ordered
2085 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2086 * more correct to check destroyMe before needsSalvaged.
2087 * -- tkeiser 11/28/2007
2090 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2092 case VOL_INFO_LIST_MULTIPLE:
2096 case VOL_INFO_LIST_SINGLE:
2097 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
2098 volumeId, pname, volname);
2105 if (tv->header->diskstuff.needsSalvaged) {
2106 /*this volume will be salvaged */
2107 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2108 volumeId, pname, volname);
2111 #ifdef AFS_DEMAND_ATTACH_FS
2112 /* If using DAFS, get volume from fsserver */
2113 if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
2117 /* fs_tv is a shallow copy, must populate certain structures before passing along */
2118 if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) {
2119 /* If we if the pending vol op */
2120 memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
2121 fs_tv->pending_vol_op=&pending_vol_op_res;
2123 fs_tv->pending_vol_op=NULL;
2126 /* populate the header from the volserver copy */
2127 fs_tv->header=tv->header;
2129 /* When using DAFS, use the fs volume info, populated with required structures */
2132 /* When not using DAFS, just use the local volume info */
2136 /* ok, we have all the data we need; fill in the on-wire struct */
2137 code = FillVolInfo(fill_tv, handle);
2141 VOLINT_INFO_STORE(handle, status, 0);
2142 strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
2143 VOLINT_INFO_STORE(handle, volid, volumeId);
2146 VDetachVolume(&error, tv);
2149 VOLINT_INFO_STORE(handle, status, 0);
2150 strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
2151 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2152 volumeId, pname, volname);
2156 DeleteTrans(ttc, 1);
2163 /*return the header information about the <volid> */
2165 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
2166 afs_uint32 volumeId, volEntries *volumeInfo)
2170 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2171 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
2176 VolListOneVolume(struct rx_call *acid, afs_int32 partid,
2177 afs_uint32 volumeId, volEntries *volumeInfo)
2180 struct DiskPartition64 *partP;
2181 char pname[9], volname[20];
2182 afs_int32 error = 0;
2187 volint_info_handle_t handle;
2189 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2190 if (!volumeInfo->volEntries_val)
2192 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2194 pntr = volumeInfo->volEntries_val;
2195 volumeInfo->volEntries_len = 1;
2196 if (GetPartName(partid, pname))
2197 return VOLSERILLEGAL_PARTITION;
2198 if (!(partP = VGetPartition(pname, 0)))
2199 return VOLSERILLEGAL_PARTITION;
2200 dirp = opendir(VPartitionPath(partP));
2202 return VOLSERILLEGAL_PARTITION;
2204 strcpy(volname, "");
2206 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2208 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2209 GetNextVol(dirp, volname, &volid);
2210 continue; /*back to while loop */
2213 if (volid == volumeId) { /*copy other things too */
2218 GetNextVol(dirp, volname, &volid);
2222 #ifndef AFS_PTHREAD_ENV
2223 IOMGR_Poll(); /*make sure that the client does not time out */
2226 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2227 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2229 code = GetVolInfo(partid,
2234 VOL_INFO_LIST_SINGLE);
2238 return (found) ? 0 : ENODEV;
2241 /*------------------------------------------------------------------------
2242 * EXPORTED SAFSVolXListOneVolume
2245 * Returns extended info on volume a_volID on partition a_partID.
2248 * a_rxCidP : Pointer to the Rx call we're performing.
2249 * a_partID : Partition for which we want the extended list.
2250 * a_volID : Volume ID we wish to know about.
2251 * a_volumeXInfoP : Ptr to the extended info blob.
2254 * 0 Successful operation
2255 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2258 * Nothing interesting.
2262 *------------------------------------------------------------------------*/
2265 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2266 afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
2270 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2271 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2276 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2277 afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
2278 { /*SAFSVolXListOneVolume */
2280 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2281 struct DiskPartition64 *partP; /*Ptr to partition */
2282 char pname[9], volname[20]; /*Partition, volume names */
2283 DIR *dirp; /*Partition directory ptr */
2284 afs_uint32 currVolID; /*Current volume ID */
2285 int found = 0; /*Did we find the volume we need? */
2287 volint_info_handle_t handle;
2290 * Set up our pointers for action, marking our structure to hold exactly
2291 * one entry. Also, assume we'll fail in our quest.
2293 a_volumeXInfoP->volXEntries_val =
2294 (volintXInfo *) malloc(sizeof(volintXInfo));
2295 if (!a_volumeXInfoP->volXEntries_val)
2297 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2299 xInfoP = a_volumeXInfoP->volXEntries_val;
2300 a_volumeXInfoP->volXEntries_len = 1;
2304 * If the partition name we've been given is bad, bogue out.
2306 if (GetPartName(a_partID, pname))
2307 return (VOLSERILLEGAL_PARTITION);
2310 * Open the directory representing the given AFS parttion. If we can't
2313 if (!(partP = VGetPartition(pname, 0)))
2314 return VOLSERILLEGAL_PARTITION;
2315 dirp = opendir(VPartitionPath(partP));
2317 return (VOLSERILLEGAL_PARTITION);
2319 strcpy(volname, "");
2322 * Sweep through the partition directory, looking for the desired entry.
2323 * First, of course, figure out how many stat bytes to copy out of each
2326 while (strcmp(volname, "EOD") && !found) {
2328 * If this is not a volume, move on to the next entry in the
2329 * partition's directory.
2331 if (!strcmp(volname, "")) {
2332 GetNextVol(dirp, volname, &currVolID);
2336 if (currVolID == a_volID) {
2338 * We found the volume entry we're interested. Pull out the
2339 * extended information, remembering to poll (so that the client
2340 * doesn't time out) and to set up a transaction on the volume.
2344 } /*Found desired volume */
2346 GetNextVol(dirp, volname, &currVolID);
2350 #ifndef AFS_PTHREAD_ENV
2354 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2355 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2357 code = GetVolInfo(a_partID,
2362 VOL_INFO_LIST_SINGLE);
2367 * Clean up before going to dinner: close the partition directory,
2368 * return the proper value.
2371 return (found) ? 0 : ENODEV;
2372 } /*SAFSVolXListOneVolume */
2374 /*returns all the volumes on partition partid. If flags = 1 then all the
2375 * relevant info about the volumes is also returned */
2377 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2378 volEntries *volumeInfo)
2382 code = VolListVolumes(acid, partid, flags, volumeInfo);
2383 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2388 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2389 volEntries *volumeInfo)
2392 struct DiskPartition64 *partP;
2393 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2394 char pname[9], volname[20];
2395 afs_int32 error = 0;
2399 volint_info_handle_t handle;
2401 volumeInfo->volEntries_val =
2402 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2403 if (!volumeInfo->volEntries_val)
2405 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2407 pntr = volumeInfo->volEntries_val;
2408 volumeInfo->volEntries_len = 0;
2409 if (GetPartName(partid, pname))
2410 return VOLSERILLEGAL_PARTITION;
2411 if (!(partP = VGetPartition(pname, 0)))
2412 return VOLSERILLEGAL_PARTITION;
2413 dirp = opendir(VPartitionPath(partP));
2415 return VOLSERILLEGAL_PARTITION;
2416 strcpy(volname, "");
2418 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2420 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2421 GetNextVol(dirp, volname, &volid);
2422 continue; /*back to while loop */
2425 if (flags) { /*copy other things too */
2426 #ifndef AFS_PTHREAD_ENV
2427 IOMGR_Poll(); /*make sure that the client does not time out */
2430 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2431 handle.volinfo_ptr.base = pntr;
2434 code = GetVolInfo(partid,
2439 VOL_INFO_LIST_MULTIPLE);
2440 if (code == -2) { /* DESTROY_ME flag set */
2444 pntr->volid = volid;
2445 /*just volids are needed */
2450 volumeInfo->volEntries_len += 1;
2451 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2452 /*running out of space, allocate more space */
2453 allocSize = (allocSize * 3) / 2;
2455 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2456 allocSize * sizeof(volintInfo));
2459 return VOLSERNO_MEMORY;
2461 volumeInfo->volEntries_val = pntr; /* point to new block */
2462 /* set pntr to the right position */
2463 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2468 GetNextVol(dirp, volname, &volid);
2476 /*------------------------------------------------------------------------
2477 * EXPORTED SAFSVolXListVolumes
2480 * Returns all the volumes on partition a_partID. If a_flags
2481 * is set to 1, then all the relevant extended volume information
2485 * a_rxCidP : Pointer to the Rx call we're performing.
2486 * a_partID : Partition for which we want the extended list.
2487 * a_flags : Various flags.
2488 * a_volumeXInfoP : Ptr to the extended info blob.
2491 * 0 Successful operation
2492 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2493 * VOLSERNO_MEMORY if we ran out of memory allocating
2497 * Nothing interesting.
2501 *------------------------------------------------------------------------*/
2504 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2505 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2509 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2510 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2515 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2516 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2517 { /*SAFSVolXListVolumes */
2519 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2520 struct DiskPartition64 *partP; /*Ptr to partition */
2521 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2522 char pname[9], volname[20]; /*Partition, volume names */
2523 afs_int32 error = 0; /*Return code */
2524 DIR *dirp; /*Partition directory ptr */
2525 afs_uint32 volid; /*Current volume ID */
2527 volint_info_handle_t handle;
2530 * Allocate a large array of extended volume info structures, then
2531 * set it up for action.
2533 a_volumeXInfoP->volXEntries_val =
2534 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2535 if (!a_volumeXInfoP->volXEntries_val)
2537 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2539 xInfoP = a_volumeXInfoP->volXEntries_val;
2540 a_volumeXInfoP->volXEntries_len = 0;
2543 * If the partition name we've been given is bad, bogue out.
2545 if (GetPartName(a_partID, pname))
2546 return (VOLSERILLEGAL_PARTITION);
2549 * Open the directory representing the given AFS parttion. If we can't
2552 if (!(partP = VGetPartition(pname, 0)))
2553 return VOLSERILLEGAL_PARTITION;
2554 dirp = opendir(VPartitionPath(partP));
2556 return (VOLSERILLEGAL_PARTITION);
2557 strcpy(volname, "");
2560 * Sweep through the partition directory, acting on each entry. First,
2561 * of course, figure out how many stat bytes to copy out of each volume.
2563 while (strcmp(volname, "EOD")) {
2566 * If this is not a volume, move on to the next entry in the
2567 * partition's directory.
2569 if (!strcmp(volname, "")) {
2570 GetNextVol(dirp, volname, &volid);
2576 * Full info about the volume desired. Poll to make sure the
2577 * client doesn't time out, then start up a new transaction.
2579 #ifndef AFS_PTHREAD_ENV
2583 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2584 handle.volinfo_ptr.ext = xInfoP;
2586 code = GetVolInfo(a_partID,
2591 VOL_INFO_LIST_MULTIPLE);
2592 if (code == -2) { /* DESTROY_ME flag set */
2597 * Just volume IDs are needed.
2599 xInfoP->volid = volid;
2604 * Bump the pointer in the data area we're building, along with
2605 * the count of the number of entries it contains.
2608 (a_volumeXInfoP->volXEntries_len)++;
2609 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2611 * We're running out of space in the area we've built. Grow it.
2613 allocSize = (allocSize * 3) / 2;
2614 xInfoP = (volintXInfo *)
2615 realloc((char *)a_volumeXInfoP->volXEntries_val,
2616 (allocSize * sizeof(volintXInfo)));
2617 if (xInfoP == NULL) {
2619 * Bummer, no memory. Bag it, tell our caller what went wrong.
2622 return (VOLSERNO_MEMORY);
2626 * Memory reallocation worked. Correct our pointers so they
2627 * now point to the new block and the current open position within
2630 a_volumeXInfoP->volXEntries_val = xInfoP;
2632 a_volumeXInfoP->volXEntries_val +
2633 a_volumeXInfoP->volXEntries_len;
2637 GetNextVol(dirp, volname, &volid);
2638 } /*Sweep through the partition directory */
2641 * We've examined all entries in the partition directory. Close it,
2642 * delete our transaction (if any), and go home happy.
2647 } /*SAFSVolXListVolumes */
2649 /*this call is used to monitor the status of volser for debugging purposes.
2650 *information about all the active transactions is returned in transInfo*/
2652 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2656 code = VolMonitor(acid, transInfo);
2657 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2662 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2664 transDebugInfo *pntr;
2665 afs_int32 allocSize = 50;
2666 struct volser_trans *tt, *allTrans;
2668 transInfo->transDebugEntries_val =
2669 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2670 if (!transInfo->transDebugEntries_val)
2672 pntr = transInfo->transDebugEntries_val;
2673 transInfo->transDebugEntries_len = 0;
2674 allTrans = TransList();
2675 if (allTrans == (struct volser_trans *)0)
2676 return 0; /*no active transactions */
2677 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2678 pntr->tid = tt->tid;
2679 pntr->time = tt->time;
2680 pntr->creationTime = tt->creationTime;
2681 pntr->returnCode = tt->returnCode;
2682 pntr->volid = tt->volid;
2683 pntr->partition = tt->partition;
2684 pntr->iflags = tt->iflags;
2685 pntr->vflags = tt->vflags;
2686 pntr->tflags = tt->tflags;
2687 strcpy(pntr->lastProcName, tt->lastProcName);
2688 pntr->callValid = 0;
2689 if (tt->rxCallPtr) { /*record call related info */
2690 pntr->callValid = 1;
2691 pntr->readNext = tt->rxCallPtr->rnext;
2692 pntr->transmitNext = tt->rxCallPtr->tnext;
2693 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2694 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2697 transInfo->transDebugEntries_len += 1;
2698 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2699 allocSize = (allocSize * 3) / 2;
2701 (transDebugInfo *) realloc((char *)transInfo->
2702 transDebugEntries_val,
2704 sizeof(transDebugInfo));
2705 transInfo->transDebugEntries_val = pntr;
2707 transInfo->transDebugEntries_val +
2708 transInfo->transDebugEntries_len;
2709 /*set pntr to right position */
2718 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_uint32 pId, afs_uint32 cloneId, afs_uint32 backupId)
2722 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2723 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2724 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2730 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_uint32 pId, afs_uint32 cloneId, afs_uint32 backupId)
2733 afs_int32 error = 0;
2734 register struct volser_trans *tt;
2735 char caller[MAXKTCNAMELEN];
2737 if (strlen(name) > 31)
2738 return VOLSERBADNAME;
2739 if (!afsconf_SuperUser(tdir, acid, caller))
2740 return VOLSERBAD_ACCESS; /*not a super user */
2741 /* find the trans */
2742 tt = FindTrans(atid);
2745 if (tt->vflags & VTDeleted) {
2746 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2750 strcpy(tt->lastProcName, "SetIdsTypes");
2751 tt->rxCallPtr = acid;
2755 V_backupId(tv) = backupId;
2756 V_cloneId(tv) = cloneId;
2757 V_parentId(tv) = pId;
2758 strcpy((&V_disk(tv))->name, name);
2759 VUpdateVolume(&error, tv);
2761 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2765 tt->rxCallPtr = (struct rx_call *)0;
2766 if (TRELE(tt) && !error)
2767 return VOLSERTRELE_ERROR;
2771 tt->rxCallPtr = (struct rx_call *)0;
2772 if (TRELE(tt) && !error)
2773 return VOLSERTRELE_ERROR;
2778 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2782 code = VolSetDate(acid, atid, cdate);
2783 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2789 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2792 afs_int32 error = 0;
2793 register struct volser_trans *tt;
2794 char caller[MAXKTCNAMELEN];
2796 if (!afsconf_SuperUser(tdir, acid, caller))
2797 return VOLSERBAD_ACCESS; /*not a super user */
2798 /* find the trans */
2799 tt = FindTrans(atid);
2802 if (tt->vflags & VTDeleted) {
2803 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2807 strcpy(tt->lastProcName, "SetDate");
2808 tt->rxCallPtr = acid;
2811 V_creationDate(tv) = cdate;
2812 VUpdateVolume(&error, tv);
2814 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2818 tt->rxCallPtr = (struct rx_call *)0;
2819 if (TRELE(tt) && !error)
2820 return VOLSERTRELE_ERROR;
2824 tt->rxCallPtr = (struct rx_call *)0;
2825 if (TRELE(tt) && !error)
2826 return VOLSERTRELE_ERROR;
2831 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2832 afs_uint32 volumeId)
2837 char caller[MAXKTCNAMELEN];
2839 register struct volser_trans *ttc;
2840 char pname[16], volname[20];
2841 struct DiskPartition64 *partP;
2842 afs_int32 ret = ENODEV;
2845 if (!afsconf_SuperUser(tdir, acid, caller))
2846 return VOLSERBAD_ACCESS; /*not a super user */
2847 if (GetPartName(partId, pname))
2848 return VOLSERILLEGAL_PARTITION;
2849 if (!(partP = VGetPartition(pname, 0)))
2850 return VOLSERILLEGAL_PARTITION;
2851 dirp = opendir(VPartitionPath(partP));
2853 return VOLSERILLEGAL_PARTITION;
2854 strcpy(volname, "");
2855 ttc = (struct volser_trans *)0;
2857 while (strcmp(volname, "EOD")) {
2858 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2859 GetNextVol(dirp, volname, &volid);
2860 continue; /*back to while loop */
2863 if (volid == volumeId) { /*copy other things too */
2864 #ifndef AFS_PTHREAD_ENV
2865 IOMGR_Poll(); /*make sure that the client doesnot time out */
2867 ttc = NewTrans(volumeId, partId);
2869 return VOLSERVOLBUSY;
2871 #ifdef AFS_NAMEI_ENV
2872 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2874 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2878 GetNextVol(dirp, volname, &volid);
2882 DeleteTrans(ttc, 1);
2883 ttc = (struct volser_trans *)0;
2892 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2893 register struct volintSize *size)
2896 register struct volser_trans *tt;
2897 char caller[MAXKTCNAMELEN];
2899 if (!afsconf_SuperUser(tdir, acid, caller))
2900 return VOLSERBAD_ACCESS; /*not a super user */
2901 tt = FindTrans(fromTrans);
2904 if (tt->vflags & VTDeleted) {
2908 strcpy(tt->lastProcName, "GetSize");
2909 tt->rxCallPtr = acid;
2910 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2911 tt->rxCallPtr = (struct rx_call *)0;
2913 return VOLSERTRELE_ERROR;
2915 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2920 SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
2921 afs_uint32 where, afs_int32 verbose)
2923 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2924 afs_int32 code, code2;
2925 Volume *vol=0, *newvol=0;
2926 struct volser_trans *tt = 0, *tt2 = 0;
2927 char caller[MAXKTCNAMELEN];
2930 if (!afsconf_SuperUser(tdir, acall, caller))
2933 vol = VAttachVolume(&code, vid, V_VOLUPD);
2939 newvol = VAttachVolume(&code, new, V_VOLUPD);
2941 VDetachVolume(&code2, vol);
2946 if (V_device(vol) != V_device(newvol)
2947 || V_uniquifier(newvol) != 2) {
2948 if (V_device(vol) != V_device(newvol)) {
2949 sprintf(line, "Volumes %u and %u are not in the same partition, aborted.\n",
2951 rx_Write(acall, line, strlen(line));
2953 if (V_uniquifier(newvol) != 2) {
2954 sprintf(line, "Volume %u is not freshly created, aborted.\n", new);
2955 rx_Write(acall, line, strlen(line));
2958 rx_Write(acall, line, 1);
2959 VDetachVolume(&code2, vol);
2960 VDetachVolume(&code2, newvol);
2963 tt = NewTrans(vid, V_device(vol));
2965 sprintf(line, "Couldn't create transaction for %u, aborted.\n", vid);
2966 rx_Write(acall, line, strlen(line));
2968 rx_Write(acall, line, 1);
2969 VDetachVolume(&code2, vol);
2970 VDetachVolume(&code2, newvol);
2971 return VOLSERVOLBUSY;
2973 tt->iflags = ITBusy;
2975 strcpy(tt->lastProcName, "SplitVolume");
2977 tt2 = NewTrans(new, V_device(newvol));
2979 sprintf(line, "Couldn't create transaction for %u, aborted.\n", new);
2980 rx_Write(acall, line, strlen(line));
2982 rx_Write(acall, line, 1);
2984 VDetachVolume(&code2, vol);
2985 VDetachVolume(&code2, newvol);
2986 return VOLSERVOLBUSY;
2988 tt2->iflags = ITBusy;
2990 strcpy(tt2->lastProcName, "SplitVolume");
2992 code = split_volume(acall, vol, newvol, where, verbose);
2994 VDetachVolume(&code2, vol);
2996 VDetachVolume(&code2, newvol);
2997 DeleteTrans(tt2, 1);
3004 /* GetPartName - map partid (a decimal number) into pname (a string)
3005 * Since for NT we actually want to return the drive name, we map through the
3009 GetPartName(afs_int32 partid, char *pname)
3014 strcpy(pname, "/vicep");
3015 pname[6] = 'a' + partid;
3018 } else if (partid < VOLMAXPARTS) {
3019 strcpy(pname, "/vicep");
3021 pname[6] = 'a' + (partid / 26);
3022 pname[7] = 'a' + (partid % 26);