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, &did, &did)));
234 DFlush(); /* flush all modified dir buffers out */
235 DZap(&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_creationDate(vp) = V_copyDate(vp);
450 V_inService(vp) = V_blessed(vp) = 1;
452 AssignVolumeName(&V_disk(vp), aname, 0);
455 V_destroyMe(vp) = DESTROY_ME;
457 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
458 VUpdateVolume(&error, vp);
460 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
463 VDetachVolume(&junk, vp); /* rather return the real error code */
468 strcpy(tt->lastProcName, "CreateVolume");
469 tt->rxCallPtr = acid;
470 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
471 tt->rxCallPtr = (struct rx_call *)0;
473 return VOLSERTRELE_ERROR;
477 /* delete the volume associated with this transaction */
479 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
483 code = VolDeleteVolume(acid, atrans);
484 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
489 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
491 register struct volser_trans *tt;
493 char caller[MAXKTCNAMELEN];
495 if (!afsconf_SuperUser(tdir, acid, caller))
496 return VOLSERBAD_ACCESS;
497 tt = FindTrans(atrans);
500 if (tt->vflags & VTDeleted) {
501 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
506 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
507 strcpy(tt->lastProcName, "DeleteVolume");
508 tt->rxCallPtr = acid;
509 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
510 V_destroyMe(tt->volume) = DESTROY_ME; /* so endtrans does the right fssync opcode */
511 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
512 tt->rxCallPtr = (struct rx_call *)0;
514 return VOLSERTRELE_ERROR;
516 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
517 return 0; /* vpurgevolume doesn't set an error code */
520 /* make a clone of the volume associated with atrans, possibly giving it a new
521 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
522 * for the clone's id). The new clone is given the name newName. Finally, due to
523 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
524 * the clone operation. This may be useful when making new backup volumes, for instance
525 * since the net result of a clone and a purge generally leaves many inode ref counts
526 * the same, while doing them separately would result in far more iincs and idecs being
527 * peformed (and they are slow operations).
529 /* for efficiency reasons, sometimes faster to piggyback a purge here */
531 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
532 afs_int32 newType, char *newName, afs_int32 *newNumber)
536 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
537 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
538 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
544 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
545 afs_int32 newType, char *newName, afs_int32 *newNumber)
548 register struct Volume *originalvp, *purgevp, *newvp;
550 register struct volser_trans *tt, *ttc;
551 char caller[MAXKTCNAMELEN];
553 if (strlen(newName) > 31)
554 return VOLSERBADNAME;
555 if (!afsconf_SuperUser(tdir, acid, caller))
556 return VOLSERBAD_ACCESS; /*not a super user */
558 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
560 originalvp = (Volume *) 0;
561 purgevp = (Volume *) 0;
562 newvp = (Volume *) 0;
563 tt = ttc = (struct volser_trans *)0;
565 if (!newNumber || !*newNumber) {
566 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
571 if (newType != readonlyVolume && newType != backupVolume)
573 tt = FindTrans(atrans);
576 if (tt->vflags & VTDeleted) {
577 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
581 ttc = NewTrans(newId, tt->partition);
582 if (!ttc) { /* someone is messing with the clone already */
586 strcpy(tt->lastProcName, "Clone");
587 tt->rxCallPtr = acid;
591 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
593 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
599 originalvp = tt->volume;
600 if ((V_type(originalvp) == backupVolume)
601 || (V_type(originalvp) == readonlyVolume)) {
602 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
606 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
607 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
613 if (originalvp->device != purgevp->device) {
614 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
618 if (V_type(purgevp) != readonlyVolume) {
619 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
623 if (V_type(originalvp) == readonlyVolume
624 && V_parentId(originalvp) != V_parentId(purgevp)) {
625 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
629 if (V_type(originalvp) == readwriteVolume
630 && tt->volid != V_parentId(purgevp)) {
631 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
640 VCreateVolume(&error, originalvp->partition->name, newId,
641 V_parentId(originalvp));
643 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
644 newvp = (Volume *) 0;
647 if (newType == readonlyVolume)
648 V_cloneId(originalvp) = newId;
649 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
652 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
653 CloneVolume(&error, originalvp, newvp, purgevp);
654 purgevp = NULL; /* clone releases it, maybe even if error */
656 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
660 if (newType == readonlyVolume) {
661 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
662 V_type(newvp) = readonlyVolume;
663 } else if (newType == backupVolume) {
664 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
665 V_type(newvp) = backupVolume;
666 V_backupId(originalvp) = newId;
668 strcpy(newvp->header->diskstuff.name, newName);
669 V_creationDate(newvp) = V_copyDate(newvp);
670 ClearVolumeStats(&V_disk(newvp));
671 V_destroyMe(newvp) = DESTROY_ME;
672 V_inService(newvp) = 0;
673 if (newType == backupVolume) {
674 V_backupDate(originalvp) = V_copyDate(newvp);
675 V_backupDate(newvp) = V_copyDate(newvp);
678 VUpdateVolume(&error, newvp);
680 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
684 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
686 VUpdateVolume(&error, originalvp);
688 Log("1 Volser: Clone: original update %u\n", error);
692 tt->rxCallPtr = (struct rx_call *)0;
694 tt = (struct volser_trans *)0;
695 error = VOLSERTRELE_ERROR;
703 VDetachVolume(&code, purgevp);
705 VDetachVolume(&code, newvp);
707 tt->rxCallPtr = (struct rx_call *)0;
715 /* reclone this volume into the specified id */
717 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
721 code = VolReClone(acid, atrans, cloneId);
722 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
728 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
730 register struct Volume *originalvp, *clonevp;
733 register struct volser_trans *tt, *ttc;
734 char caller[MAXKTCNAMELEN];
736 /*not a super user */
737 if (!afsconf_SuperUser(tdir, acid, caller))
738 return VOLSERBAD_ACCESS;
740 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
742 clonevp = originalvp = (Volume *) 0;
743 tt = (struct volser_trans *)0;
745 tt = FindTrans(atrans);
748 if (tt->vflags & VTDeleted) {
749 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
753 ttc = NewTrans(cloneId, tt->partition);
754 if (!ttc) { /* someone is messing with the clone already */
758 strcpy(tt->lastProcName, "ReClone");
759 tt->rxCallPtr = acid;
761 originalvp = tt->volume;
762 if ((V_type(originalvp) == backupVolume)
763 || (V_type(originalvp) == readonlyVolume)) {
764 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
768 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
769 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
775 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
777 Log("1 Volser: can't attach clone %d\n", cloneId);
781 newType = V_type(clonevp); /* type of the new volume */
783 if (originalvp->device != clonevp->device) {
784 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
789 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
790 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
794 if (V_type(originalvp) == readonlyVolume
795 && V_parentId(originalvp) != V_parentId(clonevp)) {
796 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
800 if (V_type(originalvp) == readwriteVolume
801 && tt->volid != V_parentId(clonevp)) {
802 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
808 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
810 CloneVolume(&error, originalvp, clonevp, clonevp);
812 Log("1 Volser: Clone: reclone operation failed with code %d\n",
818 /* fix up volume name and type, CloneVolume just propagated RW's */
819 if (newType == readonlyVolume) {
820 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
821 V_type(clonevp) = readonlyVolume;
822 } else if (newType == backupVolume) {
823 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
824 V_type(clonevp) = backupVolume;
825 V_backupId(originalvp) = cloneId;
827 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
829 /* pretend recloned volume is a totally new instance */
830 V_copyDate(clonevp) = time(0);
831 V_creationDate(clonevp) = V_copyDate(clonevp);
832 ClearVolumeStats(&V_disk(clonevp));
833 V_destroyMe(clonevp) = 0;
834 V_inService(clonevp) = 0;
835 if (newType == backupVolume) {
836 V_backupDate(originalvp) = V_copyDate(clonevp);
837 V_backupDate(clonevp) = V_copyDate(clonevp);
839 V_inUse(clonevp) = 0;
840 VUpdateVolume(&error, clonevp);
842 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
846 /* VUpdateVolume succeeded. Mark it in service so there's no window
847 * between FSYNC_VOL_ON and VolSetFlags where it's offline with no
848 * specialStatus; this is a reclone and this volume started online
850 V_inService(clonevp) = 1;
851 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
853 VUpdateVolume(&error, originalvp);
855 Log("1 Volser: Clone: original update %u\n", error);
859 tt->rxCallPtr = (struct rx_call *)0;
861 tt = (struct volser_trans *)0;
862 error = VOLSERTRELE_ERROR;
869 struct DiskPartition64 *tpartp = originalvp->partition;
870 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
876 VDetachVolume(&code, clonevp);
878 tt->rxCallPtr = (struct rx_call *)0;
886 /* create a new transaction, associated with volume and partition. Type of
887 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
888 * See volser.h for definition of iflags (the constants are named IT*).
891 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
892 afs_int32 iflags, afs_int32 *ttid)
896 code = VolTransCreate(acid, volume, partition, iflags, ttid);
897 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
903 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
904 afs_int32 iflags, afs_int32 *ttid)
906 register struct volser_trans *tt;
908 afs_int32 error, code;
910 char caller[MAXKTCNAMELEN];
912 if (!afsconf_SuperUser(tdir, acid, caller))
913 return VOLSERBAD_ACCESS; /*not a super user */
914 if (iflags & ITCreate)
916 else if (iflags & ITBusy)
918 else if (iflags & ITReadOnly)
920 else if (iflags & ITOffline)
923 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
928 tt = NewTrans(volume, partition);
930 /* can't create a transaction? put the volume back */
931 Log("1 transcreate: can't create transaction\n");
932 return VOLSERVOLBUSY;
934 tv = XAttachVolume(&error, volume, partition, mode);
938 VDetachVolume(&code, tv);
946 strcpy(tt->lastProcName, "TransCreate");
948 return VOLSERTRELE_ERROR;
953 /* using aindex as a 0-based index, return the aindex'th volume on this server
954 * Both the volume number and partition number (one-based) are returned.
957 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
962 code = VolGetNthVolume(acid, aindex, avolume, apart);
963 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
968 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
971 Log("1 Volser: GetNthVolume: Not yet implemented\n");
975 /* return the volume flags (VT* constants in volser.h) associated with this
979 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
983 code = VolGetFlags(acid, atid, aflags);
984 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
989 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
991 register struct volser_trans *tt;
993 tt = FindTrans(atid);
996 if (tt->vflags & VTDeleted) {
997 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
1002 strcpy(tt->lastProcName, "GetFlags");
1003 tt->rxCallPtr = acid;
1004 *aflags = tt->vflags;
1005 tt->rxCallPtr = (struct rx_call *)0;
1007 return VOLSERTRELE_ERROR;
1012 /* Change the volume flags (VT* constants in volser.h) associated with this
1013 * transaction. Effects take place immediately on volume, although volume
1014 * remains attached as usual by the transaction.
1017 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1021 code = VolSetFlags(acid, atid, aflags);
1022 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1028 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1030 register struct volser_trans *tt;
1031 register struct Volume *vp;
1033 char caller[MAXKTCNAMELEN];
1035 if (!afsconf_SuperUser(tdir, acid, caller))
1036 return VOLSERBAD_ACCESS; /*not a super user */
1037 /* find the trans */
1038 tt = FindTrans(atid);
1041 if (tt->vflags & VTDeleted) {
1042 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1047 strcpy(tt->lastProcName, "SetFlags");
1048 tt->rxCallPtr = acid;
1049 vp = tt->volume; /* pull volume out of transaction */
1051 /* check if we're allowed to make any updates */
1052 if (tt->iflags & ITReadOnly) {
1057 /* handle delete-on-salvage flag */
1058 if (aflags & VTDeleteOnSalvage) {
1059 V_destroyMe(tt->volume) = DESTROY_ME;
1061 V_destroyMe(tt->volume) = 0;
1064 if (aflags & VTOutOfService) {
1065 V_inService(vp) = 0;
1067 V_inService(vp) = 1;
1069 VUpdateVolume(&error, vp);
1070 tt->vflags = aflags;
1071 if (TRELE(tt) && !error)
1072 return VOLSERTRELE_ERROR;
1077 /* dumpS the volume associated with a particular transaction from a particular
1078 * date. Send the dump to a different transaction (destTrans) on the server
1079 * specified by the destServer structure.
1082 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1083 struct destServer *destination, afs_int32 destTrans,
1084 struct restoreCookie *cookie)
1089 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1090 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1091 destination->destHost, AUD_LONG, destTrans, AUD_END);
1096 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1097 struct destServer *destination, afs_int32 destTrans,
1098 struct restoreCookie *cookie)
1100 register struct volser_trans *tt;
1101 register afs_int32 code;
1102 register struct rx_connection *tcon;
1103 struct rx_call *tcall;
1104 register struct Volume *vp;
1105 struct rx_securityClass *securityObject;
1106 afs_int32 securityIndex;
1107 char caller[MAXKTCNAMELEN];
1109 if (!afsconf_SuperUser(tdir, acid, caller))
1110 return VOLSERBAD_ACCESS; /*not a super user */
1111 /* initialize things */
1112 tcon = (struct rx_connection *)0;
1113 tt = (struct volser_trans *)0;
1115 /* find the local transaction */
1116 tt = FindTrans(fromTrans);
1119 if (tt->vflags & VTDeleted) {
1120 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1125 strcpy(tt->lastProcName, "Forward");
1127 /* get auth info for the this connection (uses afs from ticket file) */
1128 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1134 /* make an rpc connection to the other server */
1136 rx_NewConnection(htonl(destination->destHost),
1137 htons(destination->destPort), VOLSERVICE_ID,
1138 securityObject, securityIndex);
1140 tt->rxCallPtr = (struct rx_call *)0;
1144 tcall = rx_NewCall(tcon);
1145 tt->rxCallPtr = tcall;
1146 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1147 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1152 /* these next calls implictly call rx_Write when writing out data */
1153 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1156 EndAFSVolRestore(tcall); /* probably doesn't do much */
1157 tt->rxCallPtr = (struct rx_call *)0;
1158 code = rx_EndCall(tcall, 0);
1159 rx_DestroyConnection(tcon); /* done with the connection */
1164 return VOLSERTRELE_ERROR;
1170 (void)rx_EndCall(tcall, 0);
1171 rx_DestroyConnection(tcon);
1174 tt->rxCallPtr = (struct rx_call *)0;
1180 /* Start a dump and send it to multiple places simultaneously.
1181 * If this returns an error (eg, return ENOENT), it means that
1182 * none of the releases worked. If this returns 0, that means
1183 * that one or more of the releases worked, and the caller has
1184 * to examine the results array to see which one(s).
1185 * This will only do EITHER incremental or full, not both, so it's
1186 * the caller's responsibility to be sure that all the destinations
1187 * need just an incremental (and from the same time), if that's
1191 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1192 fromDate, manyDests *destinations, afs_int32 spare,
1193 struct restoreCookie *cookie, manyResults *results)
1195 afs_int32 securityIndex;
1196 struct rx_securityClass *securityObject;
1197 char caller[MAXKTCNAMELEN];
1198 struct volser_trans *tt;
1199 afs_int32 ec, code, *codes;
1200 struct rx_connection **tcons;
1201 struct rx_call **tcalls;
1203 int i, is_incremental;
1206 memset(results, 0, sizeof(manyResults));
1207 i = results->manyResults_len = destinations->manyDests_len;
1208 results->manyResults_val = codes =
1209 (afs_int32 *) malloc(i * sizeof(afs_int32));
1211 if (!results || !results->manyResults_val)
1214 if (!afsconf_SuperUser(tdir, acid, caller))
1215 return VOLSERBAD_ACCESS; /*not a super user */
1216 tt = FindTrans(fromTrans);
1219 if (tt->vflags & VTDeleted) {
1220 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1225 strcpy(tt->lastProcName, "ForwardMulti");
1227 /* (fromDate == 0) ==> full dump */
1228 is_incremental = (fromDate ? 1 : 0);
1231 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1235 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1241 /* get auth info for this connection (uses afs from ticket file) */
1242 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1244 goto fail; /* in order to audit each failure */
1247 /* make connections to all the other servers */
1248 for (i = 0; i < destinations->manyDests_len; i++) {
1249 struct replica *dest = &(destinations->manyDests_val[i]);
1251 rx_NewConnection(htonl(dest->server.destHost),
1252 htons(dest->server.destPort), VOLSERVICE_ID,
1253 securityObject, securityIndex);
1255 codes[i] = ENOTCONN;
1257 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1258 codes[i] = ENOTCONN;
1261 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1264 (void)rx_EndCall(tcalls[i], 0);
1266 rx_DestroyConnection(tcons[i]);
1273 /* these next calls implictly call rx_Write when writing out data */
1274 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1278 for (i--; i >= 0; i--) {
1279 struct replica *dest = &(destinations->manyDests_val[i]);
1281 if (!code && tcalls[i] && !codes[i]) {
1282 EndAFSVolRestore(tcalls[i]);
1285 ec = rx_EndCall(tcalls[i], 0);
1290 rx_DestroyConnection(tcons[i]); /* done with the connection */
1293 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1294 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1295 dest->trans, AUD_END);
1301 tt->rxCallPtr = (struct rx_call *)0;
1302 if (TRELE(tt) && !code) /* return the first code if it's set */
1303 return VOLSERTRELE_ERROR;
1310 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1314 code = VolDump(acid, fromTrans, fromDate, 0);
1315 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1320 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1324 code = VolDump(acid, fromTrans, fromDate, flags);
1325 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1330 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1333 register struct volser_trans *tt;
1334 char caller[MAXKTCNAMELEN];
1336 if (!afsconf_SuperUser(tdir, acid, caller))
1337 return VOLSERBAD_ACCESS; /*not a super user */
1338 tt = FindTrans(fromTrans);
1341 if (tt->vflags & VTDeleted) {
1342 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1346 strcpy(tt->lastProcName, "Dump");
1347 tt->rxCallPtr = acid;
1348 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1349 ? 0 : 1); /* squirt out the volume's data, too */
1351 tt->rxCallPtr = (struct rx_call *)0;
1355 tt->rxCallPtr = (struct rx_call *)0;
1358 return VOLSERTRELE_ERROR;
1364 * Ha! No more helper process!
1367 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1368 struct restoreCookie *cookie)
1372 code = VolRestore(acid, atrans, aflags, cookie);
1373 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1378 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1379 struct restoreCookie *cookie)
1381 register struct volser_trans *tt;
1382 register afs_int32 code, tcode;
1383 char caller[MAXKTCNAMELEN];
1385 if (!afsconf_SuperUser(tdir, acid, caller))
1386 return VOLSERBAD_ACCESS; /*not a super user */
1387 tt = FindTrans(atrans);
1390 if (tt->vflags & VTDeleted) {
1391 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1395 strcpy(tt->lastProcName, "Restore");
1396 tt->rxCallPtr = acid;
1398 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1400 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1401 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1402 tt->rxCallPtr = (struct rx_call *)0;
1405 return (code ? code : tcode);
1408 /* end a transaction, returning the transaction's final error code in rcode */
1410 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1414 code = VolEndTrans(acid, destTrans, rcode);
1415 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1420 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1422 register struct volser_trans *tt;
1423 char caller[MAXKTCNAMELEN];
1425 if (!afsconf_SuperUser(tdir, acid, caller))
1426 return VOLSERBAD_ACCESS; /*not a super user */
1427 tt = FindTrans(destTrans);
1431 *rcode = tt->returnCode;
1432 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1438 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1442 code = VolSetForwarding(acid, atid, anewsite);
1443 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1449 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1451 register struct volser_trans *tt;
1452 char caller[MAXKTCNAMELEN];
1455 if (!afsconf_SuperUser(tdir, acid, caller))
1456 return VOLSERBAD_ACCESS; /*not a super user */
1457 tt = FindTrans(atid);
1460 if (tt->vflags & VTDeleted) {
1461 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1466 strcpy(tt->lastProcName, "SetForwarding");
1467 tt->rxCallPtr = acid;
1468 if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
1471 FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
1472 tt->rxCallPtr = (struct rx_call *)0;
1474 return VOLSERTRELE_ERROR;
1480 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1481 register struct volser_status *astatus)
1485 code = VolGetStatus(acid, atrans, astatus);
1486 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1491 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1492 register struct volser_status *astatus)
1494 register struct Volume *tv;
1495 register struct VolumeDiskData *td;
1496 struct volser_trans *tt;
1499 tt = FindTrans(atrans);
1502 if (tt->vflags & VTDeleted) {
1503 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1508 strcpy(tt->lastProcName, "GetStatus");
1509 tt->rxCallPtr = acid;
1512 tt->rxCallPtr = (struct rx_call *)0;
1517 td = &tv->header->diskstuff;
1518 astatus->volID = td->id;
1519 astatus->nextUnique = td->uniquifier;
1520 astatus->type = td->type;
1521 astatus->parentID = td->parentId;
1522 astatus->cloneID = td->cloneId;
1523 astatus->backupID = td->backupId;
1524 astatus->restoredFromID = td->restoredFromId;
1525 astatus->maxQuota = td->maxquota;
1526 astatus->minQuota = td->minquota;
1527 astatus->owner = td->owner;
1528 astatus->creationDate = td->creationDate;
1529 astatus->accessDate = td->accessDate;
1530 astatus->updateDate = td->updateDate;
1531 astatus->expirationDate = td->expirationDate;
1532 astatus->backupDate = td->backupDate;
1533 astatus->copyDate = td->copyDate;
1534 tt->rxCallPtr = (struct rx_call *)0;
1536 return VOLSERTRELE_ERROR;
1542 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1543 register struct volintInfo *astatus)
1547 code = VolSetInfo(acid, atrans, astatus);
1548 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1553 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1554 register struct volintInfo *astatus)
1556 register struct Volume *tv;
1557 register struct VolumeDiskData *td;
1558 struct volser_trans *tt;
1559 char caller[MAXKTCNAMELEN];
1562 if (!afsconf_SuperUser(tdir, acid, caller))
1563 return VOLSERBAD_ACCESS; /*not a super user */
1564 tt = FindTrans(atrans);
1567 if (tt->vflags & VTDeleted) {
1568 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1572 strcpy(tt->lastProcName, "SetStatus");
1573 tt->rxCallPtr = acid;
1576 tt->rxCallPtr = (struct rx_call *)0;
1581 td = &tv->header->diskstuff;
1583 * Add more fields as necessary
1585 if (astatus->maxquota != -1)
1586 td->maxquota = astatus->maxquota;
1587 if (astatus->dayUse != -1)
1588 td->dayUse = astatus->dayUse;
1589 if (astatus->creationDate != -1)
1590 td->creationDate = astatus->creationDate;
1591 if (astatus->updateDate != -1)
1592 td->updateDate = astatus->updateDate;
1593 if (astatus->spare2 != -1)
1594 td->volUpdateCounter = (unsigned int)astatus->spare2;
1595 VUpdateVolume(&error, tv);
1596 tt->rxCallPtr = (struct rx_call *)0;
1598 return VOLSERTRELE_ERROR;
1604 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1608 code = VolGetName(acid, atrans, aname);
1609 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1614 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1616 register struct Volume *tv;
1617 register struct VolumeDiskData *td;
1618 struct volser_trans *tt;
1621 /* We need to at least fill it in */
1622 *aname = (char *)malloc(1);
1625 tt = FindTrans(atrans);
1628 if (tt->vflags & VTDeleted) {
1629 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1633 strcpy(tt->lastProcName, "GetName");
1634 tt->rxCallPtr = acid;
1637 tt->rxCallPtr = (struct rx_call *)0;
1642 td = &tv->header->diskstuff;
1643 len = strlen(td->name) + 1; /* don't forget the null */
1645 tt->rxCallPtr = (struct rx_call *)0;
1649 *aname = (char *)realloc(*aname, len);
1650 strcpy(*aname, td->name);
1651 tt->rxCallPtr = (struct rx_call *)0;
1653 return VOLSERTRELE_ERROR;
1658 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1661 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1662 afs_int32 parentId, afs_int32 cloneId)
1668 /*return a list of all partitions on the server. The non mounted
1669 *partitions are returned as -1 in the corresponding slot in partIds*/
1671 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1675 code = VolListPartitions(acid, partIds);
1676 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1681 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1686 strcpy(namehead, "/vicep"); /*7 including null terminator */
1688 /* Just return attached partitions. */
1690 for (i = 0; i < 26; i++) {
1691 namehead[6] = i + 'a';
1692 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1698 /*return a list of all partitions on the server. The non mounted
1699 *partitions are returned as -1 in the corresponding slot in partIds*/
1701 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1705 code = XVolListPartitions(acid, pEntries);
1706 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1711 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1713 struct stat rbuf, pbuf;
1715 struct partList partList;
1716 struct DiskPartition64 *dp;
1719 strcpy(namehead, "/vicep"); /*7 including null terminator */
1721 /* Only report attached partitions */
1722 for (i = 0; i < VOLMAXPARTS; i++) {
1723 #ifdef AFS_DEMAND_ATTACH_FS
1724 dp = VGetPartitionById(i, 0);
1727 namehead[6] = i + 'a';
1731 namehead[6] = 'a' + (k / 26);
1732 namehead[7] = 'a' + (k % 26);
1735 dp = VGetPartition(namehead, 0);
1738 partList.partId[j++] = i;
1740 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1741 if (!pEntries->partEntries_val)
1743 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1745 pEntries->partEntries_len = j;
1750 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1752 ExtractVolId(char vname[])
1755 char name[VOLSER_MAXVOLNAME + 1];
1757 strcpy(name, vname);
1759 while (name[i] == 'V' || name[i] == '0')
1762 name[11] = '\0'; /* smash the "." */
1763 return (atol(&name[i]));
1766 /*return the name of the next volume header in the directory associated with dirp and dp.
1767 *the volume id is returned in volid, and volume header name is returned in volname*/
1769 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1773 dp = readdir(dirp); /*read next entry in the directory */
1775 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1776 *volid = ExtractVolId(dp->d_name);
1777 strcpy(volname, dp->d_name);
1778 return 0; /*return the name of the file representing a volume */
1780 strcpy(volname, "");
1781 return 0; /*volname doesnot represent a volume */
1784 strcpy(volname, "EOD");
1785 return 0; /*end of directory */
1791 * volint vol info structure type.
1794 VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
1795 VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
1796 } volint_info_type_t;
1799 * handle to various on-wire vol info types.
1802 volint_info_type_t volinfo_type;
1808 } volint_info_handle_t;
1811 * store value to a field at the appropriate location in on-wire structure.
1813 #define VOLINT_INFO_STORE(handle, name, val) \
1815 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
1816 (handle)->volinfo_ptr.base->name = (val); \
1818 (handle)->volinfo_ptr.ext->name = (val); \
1823 * get pointer to appropriate offset of field in on-wire structure.
1825 #define VOLINT_INFO_PTR(handle, name) \
1826 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
1827 &((handle)->volinfo_ptr.base->name) : \
1828 &((handle)->volinfo_ptr.ext->name))
1831 * fill in appropriate type of on-wire volume metadata structure.
1833 * @param vp pointer to volume object
1834 * @param hdr pointer to volume disk data object
1835 * @param handle pointer to wire format handle object
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, VolumeDiskData * hdr, volint_info_handle_t * handle)
1849 unsigned int numStatBytes, now;
1851 /*read in the relevant info */
1852 strcpy(VOLINT_INFO_PTR(handle, name), hdr->name);
1853 VOLINT_INFO_STORE(handle, status, VOK); /*its ok */
1854 VOLINT_INFO_STORE(handle, volid, hdr->id);
1855 VOLINT_INFO_STORE(handle, type, hdr->type); /*if ro volume */
1856 VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId); /*if rw volume */
1857 VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
1858 VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
1859 VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
1860 VOLINT_INFO_STORE(handle, size, hdr->diskused);
1861 VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
1862 VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
1863 now = FT_ApproxTime();
1864 if ((now - hdr->dayUseDate) > OneDay) {
1865 VOLINT_INFO_STORE(handle, dayUse, 0);
1867 VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
1869 VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
1870 VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
1871 VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
1872 VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
1874 #ifdef AFS_DEMAND_ATTACH_FS
1876 * for DAFS, we "lie" about volume state --
1877 * instead of returning the raw state from the disk header,
1878 * we compute state based upon the fileserver's internal
1879 * in-core state enumeration value reported to us via fssync,
1880 * along with the blessed and inService flags from the header.
1881 * -- tkeiser 11/27/2007
1884 (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1885 VIsErrorState(V_attachState(vp)) ||
1888 VOLINT_INFO_STORE(handle, inUse, 0);
1890 VOLINT_INFO_STORE(handle, inUse, 1);
1893 VOLINT_INFO_STORE(handle, inUse, hdr->inUse);
1897 switch(handle->volinfo_type) {
1898 case VOLINT_INFO_TYPE_BASE:
1900 #ifdef AFS_DEMAND_ATTACH_FS
1901 /* see comment above where we set inUse bit */
1902 if (hdr->needsSalvaged ||
1903 (vp && VIsErrorState(V_attachState(vp)))) {
1904 handle->volinfo_ptr.base->needsSalvaged = 1;
1906 handle->volinfo_ptr.base->needsSalvaged = 0;
1909 handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
1911 handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
1912 handle->volinfo_ptr.base->spare0 = hdr->minquota;
1913 handle->volinfo_ptr.base->spare1 =
1914 (long)hdr->weekUse[0] +
1915 (long)hdr->weekUse[1] +
1916 (long)hdr->weekUse[2] +
1917 (long)hdr->weekUse[3] +
1918 (long)hdr->weekUse[4] +
1919 (long)hdr->weekUse[5] +
1920 (long)hdr->weekUse[6];
1921 handle->volinfo_ptr.base->flags = 0;
1922 handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
1923 handle->volinfo_ptr.base->spare3 = 0;
1927 case VOLINT_INFO_TYPE_EXT:
1929 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1930 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1933 * Copy out the stat fields in a single operation.
1935 if ((now - hdr->dayUseDate) > OneDay) {
1936 memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1939 memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1940 (char *)&(hdr->stat_reads[0]),
1950 * get struct Volume out of the fileserver.
1952 * @param[in] volumeId volumeId for which we want state information
1953 * @param[in] pname partition name string
1954 * @param[inout] vp pointer to pointer to Volume object which
1955 * will be populated (see note)
1957 * @return operation status
1959 * @retval non-zero failure
1961 * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
1966 GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
1971 res.hdr.response_len = sizeof(res.hdr);
1972 res.payload.buf = *vp;
1973 res.payload.len = sizeof(Volume);
1975 code = FSYNC_VolOp(volumeId,
1981 if (code != SYNC_OK) {
1982 switch (res.hdr.reason) {
1983 case FSYNC_WRONG_PART:
1984 case FSYNC_UNKNOWN_VOLID:
1995 * mode of volume list operation.
1998 VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
1999 VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
2000 } vol_info_list_mode_t;
2003 * abstract interface to populate wire-format volume metadata structures.
2005 * @param[in] partId partition id
2006 * @param[in] volumeId volume id
2007 * @param[in] pname partition name
2008 * @param[in] volname volume file name
2009 * @param[in] handle handle to on-wire volume metadata object
2010 * @param[in] mode listing mode
2012 * @return operation status
2014 * @retval -2 DESTROY_ME flag is set
2015 * @retval -1 general failure; some data filled in
2016 * @retval -3 couldn't create vtrans; some data filled in
2019 GetVolInfo(afs_uint32 partId,
2020 afs_uint32 volumeId,
2023 volint_info_handle_t * handle,
2024 vol_info_list_mode_t mode)
2029 struct volser_trans *ttc = NULL;
2030 struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf, *tv = NULL;
2032 ttc = NewTrans(volumeId, partId);
2035 VOLINT_INFO_STORE(handle, status, VBUSY);
2036 VOLINT_INFO_STORE(handle, volid, volumeId);
2040 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
2042 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
2043 volumeId, pname, volname, error);
2048 * please note that destroyMe and needsSalvaged checks used to be ordered
2049 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2050 * more correct to check destroyMe before needsSalvaged.
2051 * -- tkeiser 11/28/2007
2054 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2056 case VOL_INFO_LIST_MULTIPLE:
2060 case VOL_INFO_LIST_SINGLE:
2061 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
2062 volumeId, pname, volname);
2069 if (tv->header->diskstuff.needsSalvaged) {
2070 /*this volume will be salvaged */
2071 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2072 volumeId, pname, volname);
2076 #ifdef AFS_DEMAND_ATTACH_FS
2077 if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
2082 /* ok, we have all the data we need; fill in the on-wire struct */
2083 code = FillVolInfo(fs_tv, &tv->header->diskstuff, handle);
2088 VOLINT_INFO_STORE(handle, status, 0);
2089 strcpy(VOLINT_INFO_PTR(handle, name), volname);
2090 VOLINT_INFO_STORE(handle, volid, volumeId);
2093 VDetachVolume(&error, tv);
2096 VOLINT_INFO_STORE(handle, status, 0);
2097 strcpy(VOLINT_INFO_PTR(handle, name), volname);
2098 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2099 volumeId, pname, volname);
2103 DeleteTrans(ttc, 1);
2110 /*return the header information about the <volid> */
2112 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2113 volumeId, volEntries *volumeInfo)
2117 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2118 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
2123 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2124 volumeId, volEntries *volumeInfo)
2127 struct DiskPartition64 *partP;
2128 char pname[9], volname[20];
2129 afs_int32 error = 0;
2135 volint_info_handle_t handle;
2137 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2138 if (!volumeInfo->volEntries_val)
2140 pntr = volumeInfo->volEntries_val;
2141 volumeInfo->volEntries_len = 1;
2142 if (GetPartName(partid, pname))
2143 return VOLSERILLEGAL_PARTITION;
2144 if (!(partP = VGetPartition(pname, 0)))
2145 return VOLSERILLEGAL_PARTITION;
2146 dirp = opendir(VPartitionPath(partP));
2148 return VOLSERILLEGAL_PARTITION;
2150 strcpy(volname, "");
2152 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2154 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2155 GetNextVol(dirp, volname, &volid);
2156 continue; /*back to while loop */
2159 if (volid == volumeId) { /*copy other things too */
2164 GetNextVol(dirp, volname, &volid);
2168 #ifndef AFS_PTHREAD_ENV
2169 IOMGR_Poll(); /*make sure that the client does not time out */
2172 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2173 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2175 code = GetVolInfo(partid,
2180 VOL_INFO_LIST_SINGLE);
2184 return (found) ? 0 : ENODEV;
2187 /*------------------------------------------------------------------------
2188 * EXPORTED SAFSVolXListOneVolume
2191 * Returns extended info on volume a_volID on partition a_partID.
2194 * a_rxCidP : Pointer to the Rx call we're performing.
2195 * a_partID : Partition for which we want the extended list.
2196 * a_volID : Volume ID we wish to know about.
2197 * a_volumeXInfoP : Ptr to the extended info blob.
2200 * 0 Successful operation
2201 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2204 * Nothing interesting.
2208 *------------------------------------------------------------------------*/
2211 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2212 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2216 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2217 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2222 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2223 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2224 { /*SAFSVolXListOneVolume */
2226 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2227 struct DiskPartition64 *partP; /*Ptr to partition */
2228 char pname[9], volname[20]; /*Partition, volume names */
2229 afs_int32 error; /*Error code */
2230 DIR *dirp; /*Partition directory ptr */
2231 afs_int32 currVolID; /*Current volume ID */
2232 int found = 0; /*Did we find the volume we need? */
2235 volint_info_handle_t handle;
2238 * Set up our pointers for action, marking our structure to hold exactly
2239 * one entry. Also, assume we'll fail in our quest.
2241 a_volumeXInfoP->volXEntries_val =
2242 (volintXInfo *) malloc(sizeof(volintXInfo));
2243 if (!a_volumeXInfoP->volXEntries_val)
2245 xInfoP = a_volumeXInfoP->volXEntries_val;
2246 a_volumeXInfoP->volXEntries_len = 1;
2250 * If the partition name we've been given is bad, bogue out.
2252 if (GetPartName(a_partID, pname))
2253 return (VOLSERILLEGAL_PARTITION);
2256 * Open the directory representing the given AFS parttion. If we can't
2259 if (!(partP = VGetPartition(pname, 0)))
2260 return VOLSERILLEGAL_PARTITION;
2261 dirp = opendir(VPartitionPath(partP));
2263 return (VOLSERILLEGAL_PARTITION);
2265 strcpy(volname, "");
2268 * Sweep through the partition directory, looking for the desired entry.
2269 * First, of course, figure out how many stat bytes to copy out of each
2272 while (strcmp(volname, "EOD") && !found) {
2274 * If this is not a volume, move on to the next entry in the
2275 * partition's directory.
2277 if (!strcmp(volname, "")) {
2278 GetNextVol(dirp, volname, &currVolID);
2282 if (currVolID == a_volID) {
2284 * We found the volume entry we're interested. Pull out the
2285 * extended information, remembering to poll (so that the client
2286 * doesn't time out) and to set up a transaction on the volume.
2290 } /*Found desired volume */
2292 GetNextVol(dirp, volname, &currVolID);
2296 #ifndef AFS_PTHREAD_ENV
2300 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2301 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2303 code = GetVolInfo(a_partID,
2308 VOL_INFO_LIST_SINGLE);
2313 * Clean up before going to dinner: close the partition directory,
2314 * return the proper value.
2317 return (found) ? 0 : ENODEV;
2318 } /*SAFSVolXListOneVolume */
2320 /*returns all the volumes on partition partid. If flags = 1 then all the
2321 * relevant info about the volumes is also returned */
2323 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2324 volEntries *volumeInfo)
2328 code = VolListVolumes(acid, partid, flags, volumeInfo);
2329 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2334 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2335 volEntries *volumeInfo)
2338 struct DiskPartition64 *partP;
2339 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2340 char pname[9], volname[20];
2341 afs_int32 error = 0;
2346 volint_info_handle_t handle;
2348 volumeInfo->volEntries_val =
2349 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2350 if (!volumeInfo->volEntries_val)
2352 pntr = volumeInfo->volEntries_val;
2353 volumeInfo->volEntries_len = 0;
2354 if (GetPartName(partid, pname))
2355 return VOLSERILLEGAL_PARTITION;
2356 if (!(partP = VGetPartition(pname, 0)))
2357 return VOLSERILLEGAL_PARTITION;
2358 dirp = opendir(VPartitionPath(partP));
2360 return VOLSERILLEGAL_PARTITION;
2361 strcpy(volname, "");
2363 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2365 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2366 GetNextVol(dirp, volname, &volid);
2367 continue; /*back to while loop */
2370 if (flags) { /*copy other things too */
2371 #ifndef AFS_PTHREAD_ENV
2372 IOMGR_Poll(); /*make sure that the client does not time out */
2375 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2376 handle.volinfo_ptr.base = pntr;
2379 code = GetVolInfo(partid,
2384 VOL_INFO_LIST_MULTIPLE);
2385 if (code == -2) { /* DESTROY_ME flag set */
2389 pntr->volid = volid;
2390 /*just volids are needed */
2395 volumeInfo->volEntries_len += 1;
2396 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2397 /*running out of space, allocate more space */
2398 allocSize = (allocSize * 3) / 2;
2400 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2401 allocSize * sizeof(volintInfo));
2404 return VOLSERNO_MEMORY;
2406 volumeInfo->volEntries_val = pntr; /* point to new block */
2407 /* set pntr to the right position */
2408 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2413 GetNextVol(dirp, volname, &volid);
2421 /*------------------------------------------------------------------------
2422 * EXPORTED SAFSVolXListVolumes
2425 * Returns all the volumes on partition a_partID. If a_flags
2426 * is set to 1, then all the relevant extended volume information
2430 * a_rxCidP : Pointer to the Rx call we're performing.
2431 * a_partID : Partition for which we want the extended list.
2432 * a_flags : Various flags.
2433 * a_volumeXInfoP : Ptr to the extended info blob.
2436 * 0 Successful operation
2437 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2438 * VOLSERNO_MEMORY if we ran out of memory allocating
2442 * Nothing interesting.
2446 *------------------------------------------------------------------------*/
2449 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2450 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2454 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2455 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2460 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2461 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2462 { /*SAFSVolXListVolumes */
2464 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2465 struct DiskPartition64 *partP; /*Ptr to partition */
2466 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2467 char pname[9], volname[20]; /*Partition, volume names */
2468 afs_int32 error = 0; /*Return code */
2469 DIR *dirp; /*Partition directory ptr */
2470 afs_int32 volid; /*Current volume ID */
2473 volint_info_handle_t handle;
2476 * Allocate a large array of extended volume info structures, then
2477 * set it up for action.
2479 a_volumeXInfoP->volXEntries_val =
2480 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2481 if (!a_volumeXInfoP->volXEntries_val)
2483 xInfoP = a_volumeXInfoP->volXEntries_val;
2484 a_volumeXInfoP->volXEntries_len = 0;
2487 * If the partition name we've been given is bad, bogue out.
2489 if (GetPartName(a_partID, pname))
2490 return (VOLSERILLEGAL_PARTITION);
2493 * Open the directory representing the given AFS parttion. If we can't
2496 if (!(partP = VGetPartition(pname, 0)))
2497 return VOLSERILLEGAL_PARTITION;
2498 dirp = opendir(VPartitionPath(partP));
2500 return (VOLSERILLEGAL_PARTITION);
2501 strcpy(volname, "");
2504 * Sweep through the partition directory, acting on each entry. First,
2505 * of course, figure out how many stat bytes to copy out of each volume.
2507 while (strcmp(volname, "EOD")) {
2510 * If this is not a volume, move on to the next entry in the
2511 * partition's directory.
2513 if (!strcmp(volname, "")) {
2514 GetNextVol(dirp, volname, &volid);
2520 * Full info about the volume desired. Poll to make sure the
2521 * client doesn't time out, then start up a new transaction.
2523 #ifndef AFS_PTHREAD_ENV
2527 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2528 handle.volinfo_ptr.ext = xInfoP;
2530 code = GetVolInfo(a_partID,
2535 VOL_INFO_LIST_MULTIPLE);
2536 if (code == -2) { /* DESTROY_ME flag set */
2541 * Just volume IDs are needed.
2543 xInfoP->volid = volid;
2548 * Bump the pointer in the data area we're building, along with
2549 * the count of the number of entries it contains.
2552 (a_volumeXInfoP->volXEntries_len)++;
2553 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2555 * We're running out of space in the area we've built. Grow it.
2557 allocSize = (allocSize * 3) / 2;
2558 xInfoP = (volintXInfo *)
2559 realloc((char *)a_volumeXInfoP->volXEntries_val,
2560 (allocSize * sizeof(volintXInfo)));
2561 if (xInfoP == NULL) {
2563 * Bummer, no memory. Bag it, tell our caller what went wrong.
2566 return (VOLSERNO_MEMORY);
2570 * Memory reallocation worked. Correct our pointers so they
2571 * now point to the new block and the current open position within
2574 a_volumeXInfoP->volXEntries_val = xInfoP;
2576 a_volumeXInfoP->volXEntries_val +
2577 a_volumeXInfoP->volXEntries_len;
2581 GetNextVol(dirp, volname, &volid);
2582 } /*Sweep through the partition directory */
2585 * We've examined all entries in the partition directory. Close it,
2586 * delete our transaction (if any), and go home happy.
2591 } /*SAFSVolXListVolumes */
2593 /*this call is used to monitor the status of volser for debugging purposes.
2594 *information about all the active transactions is returned in transInfo*/
2596 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2600 code = VolMonitor(acid, transInfo);
2601 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2606 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2608 transDebugInfo *pntr;
2609 afs_int32 allocSize = 50;
2610 struct volser_trans *tt, *allTrans;
2612 transInfo->transDebugEntries_val =
2613 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2614 if (!transInfo->transDebugEntries_val)
2616 pntr = transInfo->transDebugEntries_val;
2617 transInfo->transDebugEntries_len = 0;
2618 allTrans = TransList();
2619 if (allTrans == (struct volser_trans *)0)
2620 return 0; /*no active transactions */
2621 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2622 pntr->tid = tt->tid;
2623 pntr->time = tt->time;
2624 pntr->creationTime = tt->creationTime;
2625 pntr->returnCode = tt->returnCode;
2626 pntr->volid = tt->volid;
2627 pntr->partition = tt->partition;
2628 pntr->iflags = tt->iflags;
2629 pntr->vflags = tt->vflags;
2630 pntr->tflags = tt->tflags;
2631 strcpy(pntr->lastProcName, tt->lastProcName);
2632 pntr->callValid = 0;
2633 if (tt->rxCallPtr) { /*record call related info */
2634 pntr->callValid = 1;
2635 pntr->readNext = tt->rxCallPtr->rnext;
2636 pntr->transmitNext = tt->rxCallPtr->tnext;
2637 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2638 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2641 transInfo->transDebugEntries_len += 1;
2642 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2643 allocSize = (allocSize * 3) / 2;
2645 (transDebugInfo *) realloc((char *)transInfo->
2646 transDebugEntries_val,
2648 sizeof(transDebugInfo));
2649 transInfo->transDebugEntries_val = pntr;
2651 transInfo->transDebugEntries_val +
2652 transInfo->transDebugEntries_len;
2653 /*set pntr to right position */
2662 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2666 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2667 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2668 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2674 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2677 afs_int32 error = 0;
2678 register struct volser_trans *tt;
2679 char caller[MAXKTCNAMELEN];
2681 if (strlen(name) > 31)
2682 return VOLSERBADNAME;
2683 if (!afsconf_SuperUser(tdir, acid, caller))
2684 return VOLSERBAD_ACCESS; /*not a super user */
2685 /* find the trans */
2686 tt = FindTrans(atid);
2689 if (tt->vflags & VTDeleted) {
2690 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2694 strcpy(tt->lastProcName, "SetIdsTypes");
2695 tt->rxCallPtr = acid;
2699 V_backupId(tv) = backupId;
2700 V_cloneId(tv) = cloneId;
2701 V_parentId(tv) = pId;
2702 strcpy((&V_disk(tv))->name, name);
2703 VUpdateVolume(&error, tv);
2705 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2709 tt->rxCallPtr = (struct rx_call *)0;
2710 if (TRELE(tt) && !error)
2711 return VOLSERTRELE_ERROR;
2715 tt->rxCallPtr = (struct rx_call *)0;
2716 if (TRELE(tt) && !error)
2717 return VOLSERTRELE_ERROR;
2722 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2726 code = VolSetDate(acid, atid, cdate);
2727 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2733 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2736 afs_int32 error = 0;
2737 register struct volser_trans *tt;
2738 char caller[MAXKTCNAMELEN];
2740 if (!afsconf_SuperUser(tdir, acid, caller))
2741 return VOLSERBAD_ACCESS; /*not a super user */
2742 /* find the trans */
2743 tt = FindTrans(atid);
2746 if (tt->vflags & VTDeleted) {
2747 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2751 strcpy(tt->lastProcName, "SetDate");
2752 tt->rxCallPtr = acid;
2755 V_creationDate(tv) = cdate;
2756 VUpdateVolume(&error, tv);
2758 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2762 tt->rxCallPtr = (struct rx_call *)0;
2763 if (TRELE(tt) && !error)
2764 return VOLSERTRELE_ERROR;
2768 tt->rxCallPtr = (struct rx_call *)0;
2769 if (TRELE(tt) && !error)
2770 return VOLSERTRELE_ERROR;
2775 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2781 char caller[MAXKTCNAMELEN];
2783 register struct volser_trans *ttc;
2784 char pname[16], volname[20];
2785 struct DiskPartition64 *partP;
2786 afs_int32 ret = ENODEV;
2789 if (!afsconf_SuperUser(tdir, acid, caller))
2790 return VOLSERBAD_ACCESS; /*not a super user */
2791 if (GetPartName(partId, pname))
2792 return VOLSERILLEGAL_PARTITION;
2793 if (!(partP = VGetPartition(pname, 0)))
2794 return VOLSERILLEGAL_PARTITION;
2795 dirp = opendir(VPartitionPath(partP));
2797 return VOLSERILLEGAL_PARTITION;
2798 strcpy(volname, "");
2799 ttc = (struct volser_trans *)0;
2801 while (strcmp(volname, "EOD")) {
2802 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2803 GetNextVol(dirp, volname, &volid);
2804 continue; /*back to while loop */
2807 if (volid == volumeId) { /*copy other things too */
2808 #ifndef AFS_PTHREAD_ENV
2809 IOMGR_Poll(); /*make sure that the client doesnot time out */
2811 ttc = NewTrans(volumeId, partId);
2815 #ifdef AFS_NAMEI_ENV
2816 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2818 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2822 GetNextVol(dirp, volname, &volid);
2826 DeleteTrans(ttc, 1);
2827 ttc = (struct volser_trans *)0;
2836 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2837 register struct volintSize *size)
2840 register struct volser_trans *tt;
2841 char caller[MAXKTCNAMELEN];
2843 if (!afsconf_SuperUser(tdir, acid, caller))
2844 return VOLSERBAD_ACCESS; /*not a super user */
2845 tt = FindTrans(fromTrans);
2848 if (tt->vflags & VTDeleted) {
2852 strcpy(tt->lastProcName, "GetSize");
2853 tt->rxCallPtr = acid;
2854 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2855 tt->rxCallPtr = (struct rx_call *)0;
2857 return VOLSERTRELE_ERROR;
2859 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2863 /* GetPartName - map partid (a decimal number) into pname (a string)
2864 * Since for NT we actually want to return the drive name, we map through the
2868 GetPartName(afs_int32 partid, char *pname)
2873 strcpy(pname, "/vicep");
2874 pname[6] = 'a' + partid;
2877 } else if (partid < VOLMAXPARTS) {
2878 strcpy(pname, "/vicep");
2880 pname[6] = 'a' + (partid / 26);
2881 pname[7] = 'a' + (partid % 26);