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);
217 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
219 V_pref(vp, nearInode);
221 IH_CREATE(V_linkHandle(vp), V_device(vp),
222 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
224 assert(VALID_INO(inodeNumber));
226 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
227 did.Volume = V_id(vp);
228 did.Vnode = (VnodeId) 1;
231 assert(!(MakeDir(&dir, &did, &did)));
232 DFlush(); /* flush all modified dir buffers out */
233 DZap(&dir); /* Remove all buffers for this dir */
234 length = Length(&dir); /* Remember size of this directory */
236 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
238 /* build a single entry ACL that gives all rights to system:administrators */
239 /* this section of code assumes that access list format is not going to
242 ACL = VVnodeDiskACL(vnode);
243 ACL->size = sizeof(struct acl_accessList);
244 ACL->version = ACL_ACLVERSION;
248 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
249 ACL->entries[0].rights =
250 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
251 | PRSFS_LOCK | PRSFS_ADMINISTER;
253 vnode->type = vDirectory;
255 vnode->modeBits = 0777;
256 vnode->linkCount = 2;
257 VNDISK_SET_LEN(vnode, length);
258 vnode->uniquifier = 1;
259 V_uniquifier(vp) = vnode->uniquifier + 1;
260 vnode->dataVersion = 1;
261 VNDISK_SET_INO(vnode, inodeNumber);
262 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
266 vnode->vnodeMagic = vcp->magic;
268 IH_INIT(h, vp->device, V_parentId(vp),
269 vp->vnodeIndex[vLarge].handle->ih_ino);
272 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
274 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
275 assert(code == SIZEOF_LARGEDISKVNODE);
276 FDH_REALLYCLOSE(fdP);
278 VNDISK_GET_LEN(length, vnode);
279 V_diskused(vp) = nBlocks(length);
286 SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
290 struct diskPartition64 *dp = (struct diskPartition64 *)
291 malloc(sizeof(struct diskPartition64));
293 code = VolPartitionInfo(acid, pname, dp);
295 strncpy(partition->name, dp->name, 32);
296 strncpy(partition->devName, dp->devName, 32);
297 partition->lock_fd = dp->lock_fd;
298 partition->free=RoundInt64ToInt32(dp->free);
299 partition->minFree=RoundInt64ToInt32(dp->minFree);
302 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
307 SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
312 code = VolPartitionInfo(acid, pname, partition);
313 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
318 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
321 register struct DiskPartition64 *dp;
324 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
327 dp = VGetPartition(pname, 0);
329 strncpy(partition->name, dp->name, 32);
330 strncpy(partition->devName, dp->devName, 32);
331 partition->lock_fd = dp->lock_fd;
332 partition->free = dp->free;
333 partition->minFree = dp->totalUsable;
336 return VOLSERILLEGAL_PARTITION;
339 /* obliterate a volume completely, and slowly. */
341 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
345 code = VolNukeVolume(acid, apartID, avolID);
346 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
351 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 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 tp = volutil_PartitionName(apartID);
369 strcpy(partName, tp); /* remember it for later */
370 /* we first try to attach the volume in update mode, so that the file
371 * server doesn't try to use it (and abort) while (or after) we delete it.
372 * If we don't get the volume, that's fine, too. We just won't put it back.
374 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
375 code = nuke(partName, avolID);
377 VDetachVolume(&error, tvp);
381 /* create a new volume, with name aname, on the specified partition (1..n)
382 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
383 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
384 * for the volume id (useful for things like volume restore).
385 * Return the new volume id in *avolid.
388 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
389 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
395 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
396 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
397 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
403 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
404 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
409 afs_int32 junk; /* discardable error code */
410 register afs_int32 volumeID, doCreateRoot = 1;
411 register struct volser_trans *tt;
413 char caller[MAXKTCNAMELEN];
415 if (strlen(aname) > 31)
416 return VOLSERBADNAME;
417 if (!afsconf_SuperUser(tdir, acid, caller))
418 return VOLSERBAD_ACCESS;
420 Log("%s is executing CreateVolume '%s'\n", caller, aname);
421 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
422 return error; /*a standard unix error */
423 if (atype != readwriteVolume && atype != readonlyVolume
424 && atype != backupVolume)
426 if ((volumeID = *avolid) == 0) {
428 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
432 if ((aparent == volumeID) && (atype == readwriteVolume)) {
437 tt = NewTrans(volumeID, apart);
439 Log("1 createvolume: failed to create trans\n");
440 return VOLSERVOLBUSY; /* volume already busy! */
442 vp = VCreateVolume(&error, ppath, volumeID, aparent);
444 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
449 V_uniquifier(vp) = 1;
450 V_creationDate(vp) = V_copyDate(vp);
451 V_inService(vp) = V_blessed(vp) = 1;
453 AssignVolumeName(&V_disk(vp), aname, 0);
456 V_destroyMe(vp) = DESTROY_ME;
458 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
459 VUpdateVolume(&error, vp);
461 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
464 VDetachVolume(&junk, vp); /* rather return the real error code */
469 strcpy(tt->lastProcName, "CreateVolume");
470 tt->rxCallPtr = acid;
471 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
472 tt->rxCallPtr = (struct rx_call *)0;
474 return VOLSERTRELE_ERROR;
478 /* delete the volume associated with this transaction */
480 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
484 code = VolDeleteVolume(acid, atrans);
485 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
490 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
492 register struct volser_trans *tt;
494 char caller[MAXKTCNAMELEN];
496 if (!afsconf_SuperUser(tdir, acid, caller))
497 return VOLSERBAD_ACCESS;
498 tt = FindTrans(atrans);
501 if (tt->vflags & VTDeleted) {
502 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
507 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
508 strcpy(tt->lastProcName, "DeleteVolume");
509 tt->rxCallPtr = acid;
510 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
511 V_destroyMe(tt->volume) = DESTROY_ME; /* so endtrans does the right fssync opcode */
512 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
513 tt->rxCallPtr = (struct rx_call *)0;
515 return VOLSERTRELE_ERROR;
517 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
518 return 0; /* vpurgevolume doesn't set an error code */
521 /* make a clone of the volume associated with atrans, possibly giving it a new
522 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
523 * for the clone's id). The new clone is given the name newName. Finally, due to
524 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
525 * the clone operation. This may be useful when making new backup volumes, for instance
526 * since the net result of a clone and a purge generally leaves many inode ref counts
527 * the same, while doing them separately would result in far more iincs and idecs being
528 * peformed (and they are slow operations).
530 /* for efficiency reasons, sometimes faster to piggyback a purge here */
532 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
533 afs_int32 newType, char *newName, afs_int32 *newNumber)
537 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
538 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
539 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
545 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
546 afs_int32 newType, char *newName, afs_int32 *newNumber)
549 register struct Volume *originalvp, *purgevp, *newvp;
551 register struct volser_trans *tt, *ttc;
552 char caller[MAXKTCNAMELEN];
554 if (strlen(newName) > 31)
555 return VOLSERBADNAME;
556 if (!afsconf_SuperUser(tdir, acid, caller))
557 return VOLSERBAD_ACCESS; /*not a super user */
559 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
561 originalvp = (Volume *) 0;
562 purgevp = (Volume *) 0;
563 newvp = (Volume *) 0;
564 tt = ttc = (struct volser_trans *)0;
566 if (!newNumber || !*newNumber) {
567 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
572 if (newType != readonlyVolume && newType != backupVolume)
574 tt = FindTrans(atrans);
577 if (tt->vflags & VTDeleted) {
578 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
582 ttc = NewTrans(newId, tt->partition);
583 if (!ttc) { /* someone is messing with the clone already */
587 strcpy(tt->lastProcName, "Clone");
588 tt->rxCallPtr = acid;
592 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
594 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
600 originalvp = tt->volume;
601 if ((V_type(originalvp) == backupVolume)
602 || (V_type(originalvp) == readonlyVolume)) {
603 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
607 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
608 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
614 if (originalvp->device != purgevp->device) {
615 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
619 if (V_type(purgevp) != readonlyVolume) {
620 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
624 if (V_type(originalvp) == readonlyVolume
625 && V_parentId(originalvp) != V_parentId(purgevp)) {
626 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
630 if (V_type(originalvp) == readwriteVolume
631 && tt->volid != V_parentId(purgevp)) {
632 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
641 VCreateVolume(&error, originalvp->partition->name, newId,
642 V_parentId(originalvp));
644 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
645 newvp = (Volume *) 0;
648 if (newType == readonlyVolume)
649 V_cloneId(originalvp) = newId;
650 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
653 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
654 CloneVolume(&error, originalvp, newvp, purgevp);
655 purgevp = NULL; /* clone releases it, maybe even if error */
657 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
661 if (newType == readonlyVolume) {
662 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
663 V_type(newvp) = readonlyVolume;
664 } else if (newType == backupVolume) {
665 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
666 V_type(newvp) = backupVolume;
667 V_backupId(originalvp) = newId;
669 strcpy(newvp->header->diskstuff.name, newName);
670 V_creationDate(newvp) = V_copyDate(newvp);
671 ClearVolumeStats(&V_disk(newvp));
672 V_destroyMe(newvp) = DESTROY_ME;
673 V_inService(newvp) = 0;
674 if (newType == backupVolume) {
675 V_backupDate(originalvp) = V_copyDate(newvp);
676 V_backupDate(newvp) = V_copyDate(newvp);
679 VUpdateVolume(&error, newvp);
681 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
685 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
687 VUpdateVolume(&error, originalvp);
689 Log("1 Volser: Clone: original update %u\n", error);
693 tt->rxCallPtr = (struct rx_call *)0;
695 tt = (struct volser_trans *)0;
696 error = VOLSERTRELE_ERROR;
704 VDetachVolume(&code, purgevp);
706 VDetachVolume(&code, newvp);
708 tt->rxCallPtr = (struct rx_call *)0;
716 /* reclone this volume into the specified id */
718 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
722 code = VolReClone(acid, atrans, cloneId);
723 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
729 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
731 register struct Volume *originalvp, *clonevp;
734 register struct volser_trans *tt, *ttc;
735 char caller[MAXKTCNAMELEN];
737 /*not a super user */
738 if (!afsconf_SuperUser(tdir, acid, caller))
739 return VOLSERBAD_ACCESS;
741 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
743 clonevp = originalvp = (Volume *) 0;
744 tt = (struct volser_trans *)0;
746 tt = FindTrans(atrans);
749 if (tt->vflags & VTDeleted) {
750 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
754 ttc = NewTrans(cloneId, tt->partition);
755 if (!ttc) { /* someone is messing with the clone already */
759 strcpy(tt->lastProcName, "ReClone");
760 tt->rxCallPtr = acid;
762 originalvp = tt->volume;
763 if ((V_type(originalvp) == backupVolume)
764 || (V_type(originalvp) == readonlyVolume)) {
765 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
769 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
770 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
776 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
778 Log("1 Volser: can't attach clone %d\n", cloneId);
782 newType = V_type(clonevp); /* type of the new volume */
784 if (originalvp->device != clonevp->device) {
785 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
790 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
791 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
795 if (V_type(originalvp) == readonlyVolume
796 && V_parentId(originalvp) != V_parentId(clonevp)) {
797 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
801 if (V_type(originalvp) == readwriteVolume
802 && tt->volid != V_parentId(clonevp)) {
803 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
809 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
811 CloneVolume(&error, originalvp, clonevp, clonevp);
813 Log("1 Volser: Clone: reclone operation failed with code %d\n",
819 /* fix up volume name and type, CloneVolume just propagated RW's */
820 if (newType == readonlyVolume) {
821 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
822 V_type(clonevp) = readonlyVolume;
823 } else if (newType == backupVolume) {
824 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
825 V_type(clonevp) = backupVolume;
826 V_backupId(originalvp) = cloneId;
828 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
830 /* pretend recloned volume is a totally new instance */
831 V_copyDate(clonevp) = time(0);
832 V_creationDate(clonevp) = V_copyDate(clonevp);
833 ClearVolumeStats(&V_disk(clonevp));
834 V_destroyMe(clonevp) = 0;
835 V_inService(clonevp) = 0;
836 if (newType == backupVolume) {
837 V_backupDate(originalvp) = V_copyDate(clonevp);
838 V_backupDate(clonevp) = V_copyDate(clonevp);
840 V_inUse(clonevp) = 0;
841 VUpdateVolume(&error, clonevp);
843 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
847 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
849 VUpdateVolume(&error, originalvp);
851 Log("1 Volser: Clone: original update %u\n", error);
855 tt->rxCallPtr = (struct rx_call *)0;
857 tt = (struct volser_trans *)0;
858 error = VOLSERTRELE_ERROR;
865 struct DiskPartition64 *tpartp = originalvp->partition;
866 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
872 VDetachVolume(&code, clonevp);
874 tt->rxCallPtr = (struct rx_call *)0;
882 /* create a new transaction, associated with volume and partition. Type of
883 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
884 * See volser.h for definition of iflags (the constants are named IT*).
887 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
888 afs_int32 iflags, afs_int32 *ttid)
892 code = VolTransCreate(acid, volume, partition, iflags, ttid);
893 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
899 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
900 afs_int32 iflags, afs_int32 *ttid)
902 register struct volser_trans *tt;
904 afs_int32 error, code;
906 char caller[MAXKTCNAMELEN];
908 if (!afsconf_SuperUser(tdir, acid, caller))
909 return VOLSERBAD_ACCESS; /*not a super user */
910 if (iflags & ITCreate)
912 else if (iflags & ITBusy)
914 else if (iflags & ITReadOnly)
916 else if (iflags & ITOffline)
919 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
924 tt = NewTrans(volume, partition);
926 /* can't create a transaction? put the volume back */
927 Log("1 transcreate: can't create transaction\n");
928 return VOLSERVOLBUSY;
930 tv = XAttachVolume(&error, volume, partition, mode);
934 VDetachVolume(&code, tv);
942 strcpy(tt->lastProcName, "TransCreate");
944 return VOLSERTRELE_ERROR;
949 /* using aindex as a 0-based index, return the aindex'th volume on this server
950 * Both the volume number and partition number (one-based) are returned.
953 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
958 code = VolGetNthVolume(acid, aindex, avolume, apart);
959 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
964 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
967 Log("1 Volser: GetNthVolume: Not yet implemented\n");
971 /* return the volume flags (VT* constants in volser.h) associated with this
975 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
979 code = VolGetFlags(acid, atid, aflags);
980 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
985 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
987 register struct volser_trans *tt;
989 tt = FindTrans(atid);
992 if (tt->vflags & VTDeleted) {
993 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
998 strcpy(tt->lastProcName, "GetFlags");
999 tt->rxCallPtr = acid;
1000 *aflags = tt->vflags;
1001 tt->rxCallPtr = (struct rx_call *)0;
1003 return VOLSERTRELE_ERROR;
1008 /* Change the volume flags (VT* constants in volser.h) associated with this
1009 * transaction. Effects take place immediately on volume, although volume
1010 * remains attached as usual by the transaction.
1013 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1017 code = VolSetFlags(acid, atid, aflags);
1018 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1024 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1026 register struct volser_trans *tt;
1027 register struct Volume *vp;
1029 char caller[MAXKTCNAMELEN];
1031 if (!afsconf_SuperUser(tdir, acid, caller))
1032 return VOLSERBAD_ACCESS; /*not a super user */
1033 /* find the trans */
1034 tt = FindTrans(atid);
1037 if (tt->vflags & VTDeleted) {
1038 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1043 strcpy(tt->lastProcName, "SetFlags");
1044 tt->rxCallPtr = acid;
1045 vp = tt->volume; /* pull volume out of transaction */
1047 /* check if we're allowed to make any updates */
1048 if (tt->iflags & ITReadOnly) {
1053 /* handle delete-on-salvage flag */
1054 if (aflags & VTDeleteOnSalvage) {
1055 V_destroyMe(tt->volume) = DESTROY_ME;
1057 V_destroyMe(tt->volume) = 0;
1060 if (aflags & VTOutOfService) {
1061 V_inService(vp) = 0;
1063 V_inService(vp) = 1;
1065 VUpdateVolume(&error, vp);
1066 tt->vflags = aflags;
1067 if (TRELE(tt) && !error)
1068 return VOLSERTRELE_ERROR;
1073 /* dumpS the volume associated with a particular transaction from a particular
1074 * date. Send the dump to a different transaction (destTrans) on the server
1075 * specified by the destServer structure.
1078 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1079 struct destServer *destination, afs_int32 destTrans,
1080 struct restoreCookie *cookie)
1085 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1086 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1087 destination->destHost, AUD_LONG, destTrans, AUD_END);
1092 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1093 struct destServer *destination, afs_int32 destTrans,
1094 struct restoreCookie *cookie)
1096 register struct volser_trans *tt;
1097 register afs_int32 code;
1098 register struct rx_connection *tcon;
1099 struct rx_call *tcall;
1100 register struct Volume *vp;
1101 struct rx_securityClass *securityObject;
1102 afs_int32 securityIndex;
1103 char caller[MAXKTCNAMELEN];
1105 if (!afsconf_SuperUser(tdir, acid, caller))
1106 return VOLSERBAD_ACCESS; /*not a super user */
1107 /* initialize things */
1108 tcon = (struct rx_connection *)0;
1109 tt = (struct volser_trans *)0;
1111 /* find the local transaction */
1112 tt = FindTrans(fromTrans);
1115 if (tt->vflags & VTDeleted) {
1116 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1121 strcpy(tt->lastProcName, "Forward");
1123 /* get auth info for the this connection (uses afs from ticket file) */
1124 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1130 /* make an rpc connection to the other server */
1132 rx_NewConnection(htonl(destination->destHost),
1133 htons(destination->destPort), VOLSERVICE_ID,
1134 securityObject, securityIndex);
1136 tt->rxCallPtr = (struct rx_call *)0;
1140 tcall = rx_NewCall(tcon);
1141 tt->rxCallPtr = tcall;
1142 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1143 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1148 /* these next calls implictly call rx_Write when writing out data */
1149 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1152 EndAFSVolRestore(tcall); /* probably doesn't do much */
1153 tt->rxCallPtr = (struct rx_call *)0;
1154 code = rx_EndCall(tcall, 0);
1155 rx_DestroyConnection(tcon); /* done with the connection */
1160 return VOLSERTRELE_ERROR;
1166 (void)rx_EndCall(tcall, 0);
1167 rx_DestroyConnection(tcon);
1170 tt->rxCallPtr = (struct rx_call *)0;
1176 /* Start a dump and send it to multiple places simultaneously.
1177 * If this returns an error (eg, return ENOENT), it means that
1178 * none of the releases worked. If this returns 0, that means
1179 * that one or more of the releases worked, and the caller has
1180 * to examine the results array to see which one(s).
1181 * This will only do EITHER incremental or full, not both, so it's
1182 * the caller's responsibility to be sure that all the destinations
1183 * need just an incremental (and from the same time), if that's
1187 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1188 fromDate, manyDests *destinations, afs_int32 spare,
1189 struct restoreCookie *cookie, manyResults *results)
1191 afs_int32 securityIndex;
1192 struct rx_securityClass *securityObject;
1193 char caller[MAXKTCNAMELEN];
1194 struct volser_trans *tt;
1195 afs_int32 ec, code, *codes;
1196 struct rx_connection **tcons;
1197 struct rx_call **tcalls;
1199 int i, is_incremental;
1202 memset(results, 0, sizeof(manyResults));
1204 if (!afsconf_SuperUser(tdir, acid, caller))
1205 return VOLSERBAD_ACCESS; /*not a super user */
1206 tt = FindTrans(fromTrans);
1209 if (tt->vflags & VTDeleted) {
1210 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1215 strcpy(tt->lastProcName, "ForwardMulti");
1217 /* (fromDate == 0) ==> full dump */
1218 is_incremental = (fromDate ? 1 : 0);
1220 i = results->manyResults_len = destinations->manyDests_len;
1221 results->manyResults_val = codes =
1222 (afs_int32 *) malloc(i * sizeof(afs_int32));
1224 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1225 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1227 /* get auth info for this connection (uses afs from ticket file) */
1228 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1230 goto fail; /* in order to audit each failure */
1233 /* make connections to all the other servers */
1234 for (i = 0; i < destinations->manyDests_len; i++) {
1235 struct replica *dest = &(destinations->manyDests_val[i]);
1237 rx_NewConnection(htonl(dest->server.destHost),
1238 htons(dest->server.destPort), VOLSERVICE_ID,
1239 securityObject, securityIndex);
1241 codes[i] = ENOTCONN;
1243 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1244 codes[i] = ENOTCONN;
1247 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1250 (void)rx_EndCall(tcalls[i], 0);
1252 rx_DestroyConnection(tcons[i]);
1259 /* these next calls implictly call rx_Write when writing out data */
1260 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1264 for (i--; i >= 0; i--) {
1265 struct replica *dest = &(destinations->manyDests_val[i]);
1267 if (!code && tcalls[i] && !codes[i]) {
1268 EndAFSVolRestore(tcalls[i]);
1271 ec = rx_EndCall(tcalls[i], 0);
1276 rx_DestroyConnection(tcons[i]); /* done with the connection */
1279 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1280 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1281 dest->trans, AUD_END);
1287 tt->rxCallPtr = (struct rx_call *)0;
1288 if (TRELE(tt) && !code) /* return the first code if it's set */
1289 return VOLSERTRELE_ERROR;
1296 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1300 code = VolDump(acid, fromTrans, fromDate, 0);
1301 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1306 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1310 code = VolDump(acid, fromTrans, fromDate, flags);
1311 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1316 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1319 register struct volser_trans *tt;
1320 char caller[MAXKTCNAMELEN];
1322 if (!afsconf_SuperUser(tdir, acid, caller))
1323 return VOLSERBAD_ACCESS; /*not a super user */
1324 tt = FindTrans(fromTrans);
1327 if (tt->vflags & VTDeleted) {
1328 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1332 strcpy(tt->lastProcName, "Dump");
1333 tt->rxCallPtr = acid;
1334 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1335 ? 0 : 1); /* squirt out the volume's data, too */
1337 tt->rxCallPtr = (struct rx_call *)0;
1341 tt->rxCallPtr = (struct rx_call *)0;
1344 return VOLSERTRELE_ERROR;
1350 * Ha! No more helper process!
1353 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1354 struct restoreCookie *cookie)
1358 code = VolRestore(acid, atrans, aflags, cookie);
1359 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1364 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1365 struct restoreCookie *cookie)
1367 register struct volser_trans *tt;
1368 register afs_int32 code, tcode;
1369 char caller[MAXKTCNAMELEN];
1371 if (!afsconf_SuperUser(tdir, acid, caller))
1372 return VOLSERBAD_ACCESS; /*not a super user */
1373 tt = FindTrans(atrans);
1376 if (tt->vflags & VTDeleted) {
1377 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1381 strcpy(tt->lastProcName, "Restore");
1382 tt->rxCallPtr = acid;
1384 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1386 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1387 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1388 tt->rxCallPtr = (struct rx_call *)0;
1391 return (code ? code : tcode);
1394 /* end a transaction, returning the transaction's final error code in rcode */
1396 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1400 code = VolEndTrans(acid, destTrans, rcode);
1401 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1406 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1408 register struct volser_trans *tt;
1409 char caller[MAXKTCNAMELEN];
1411 if (!afsconf_SuperUser(tdir, acid, caller))
1412 return VOLSERBAD_ACCESS; /*not a super user */
1413 tt = FindTrans(destTrans);
1417 *rcode = tt->returnCode;
1418 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1424 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1428 code = VolSetForwarding(acid, atid, anewsite);
1429 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1435 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1437 register struct volser_trans *tt;
1438 char caller[MAXKTCNAMELEN];
1440 if (!afsconf_SuperUser(tdir, acid, caller))
1441 return VOLSERBAD_ACCESS; /*not a super user */
1442 tt = FindTrans(atid);
1445 if (tt->vflags & VTDeleted) {
1446 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1451 strcpy(tt->lastProcName, "SetForwarding");
1452 tt->rxCallPtr = acid;
1453 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
1454 tt->rxCallPtr = (struct rx_call *)0;
1456 return VOLSERTRELE_ERROR;
1462 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1463 register struct volser_status *astatus)
1467 code = VolGetStatus(acid, atrans, astatus);
1468 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1473 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1474 register struct volser_status *astatus)
1476 register struct Volume *tv;
1477 register struct VolumeDiskData *td;
1478 struct volser_trans *tt;
1481 tt = FindTrans(atrans);
1484 if (tt->vflags & VTDeleted) {
1485 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1490 strcpy(tt->lastProcName, "GetStatus");
1491 tt->rxCallPtr = acid;
1494 tt->rxCallPtr = (struct rx_call *)0;
1499 td = &tv->header->diskstuff;
1500 astatus->volID = td->id;
1501 astatus->nextUnique = td->uniquifier;
1502 astatus->type = td->type;
1503 astatus->parentID = td->parentId;
1504 astatus->cloneID = td->cloneId;
1505 astatus->backupID = td->backupId;
1506 astatus->restoredFromID = td->restoredFromId;
1507 astatus->maxQuota = td->maxquota;
1508 astatus->minQuota = td->minquota;
1509 astatus->owner = td->owner;
1510 astatus->creationDate = td->creationDate;
1511 astatus->accessDate = td->accessDate;
1512 astatus->updateDate = td->updateDate;
1513 astatus->expirationDate = td->expirationDate;
1514 astatus->backupDate = td->backupDate;
1515 astatus->copyDate = td->copyDate;
1516 tt->rxCallPtr = (struct rx_call *)0;
1518 return VOLSERTRELE_ERROR;
1524 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1525 register struct volintInfo *astatus)
1529 code = VolSetInfo(acid, atrans, astatus);
1530 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1535 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1536 register struct volintInfo *astatus)
1538 register struct Volume *tv;
1539 register struct VolumeDiskData *td;
1540 struct volser_trans *tt;
1541 char caller[MAXKTCNAMELEN];
1544 if (!afsconf_SuperUser(tdir, acid, caller))
1545 return VOLSERBAD_ACCESS; /*not a super user */
1546 tt = FindTrans(atrans);
1549 if (tt->vflags & VTDeleted) {
1550 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1554 strcpy(tt->lastProcName, "SetStatus");
1555 tt->rxCallPtr = acid;
1558 tt->rxCallPtr = (struct rx_call *)0;
1563 td = &tv->header->diskstuff;
1565 * Add more fields as necessary
1567 if (astatus->maxquota != -1)
1568 td->maxquota = astatus->maxquota;
1569 if (astatus->dayUse != -1)
1570 td->dayUse = astatus->dayUse;
1571 if (astatus->creationDate != -1)
1572 td->creationDate = astatus->creationDate;
1573 if (astatus->updateDate != -1)
1574 td->updateDate = astatus->updateDate;
1575 if (astatus->spare2 != -1)
1576 td->volUpdateCounter = (unsigned int)astatus->spare2;
1577 VUpdateVolume(&error, tv);
1578 tt->rxCallPtr = (struct rx_call *)0;
1580 return VOLSERTRELE_ERROR;
1586 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1590 code = VolGetName(acid, atrans, aname);
1591 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1596 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1598 register struct Volume *tv;
1599 register struct VolumeDiskData *td;
1600 struct volser_trans *tt;
1604 tt = FindTrans(atrans);
1607 if (tt->vflags & VTDeleted) {
1608 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1612 strcpy(tt->lastProcName, "GetName");
1613 tt->rxCallPtr = acid;
1616 tt->rxCallPtr = (struct rx_call *)0;
1621 td = &tv->header->diskstuff;
1622 len = strlen(td->name) + 1; /* don't forget the null */
1624 tt->rxCallPtr = (struct rx_call *)0;
1628 *aname = (char *)malloc(len);
1629 strcpy(*aname, td->name);
1630 tt->rxCallPtr = (struct rx_call *)0;
1632 return VOLSERTRELE_ERROR;
1637 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1640 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1641 afs_int32 parentId, afs_int32 cloneId)
1647 /*return a list of all partitions on the server. The non mounted
1648 *partitions are returned as -1 in the corresponding slot in partIds*/
1650 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1654 code = VolListPartitions(acid, partIds);
1655 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1660 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1665 strcpy(namehead, "/vicep"); /*7 including null terminator */
1667 /* Just return attached partitions. */
1669 for (i = 0; i < 26; i++) {
1670 namehead[6] = i + 'a';
1671 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1677 /*return a list of all partitions on the server. The non mounted
1678 *partitions are returned as -1 in the corresponding slot in partIds*/
1680 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1684 code = XVolListPartitions(acid, pEntries);
1685 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1690 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1692 struct stat rbuf, pbuf;
1694 struct partList partList;
1695 struct DiskPartition64 *dp;
1698 strcpy(namehead, "/vicep"); /*7 including null terminator */
1700 /* Only report attached partitions */
1701 for (i = 0; i < VOLMAXPARTS; i++) {
1702 #ifdef AFS_DEMAND_ATTACH_FS
1703 dp = VGetPartitionById(i, 0);
1706 namehead[6] = i + 'a';
1710 namehead[6] = 'a' + (k / 26);
1711 namehead[7] = 'a' + (k % 26);
1714 dp = VGetPartition(namehead, 0);
1717 partList.partId[j++] = i;
1719 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1720 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1722 pEntries->partEntries_len = j;
1727 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1729 ExtractVolId(char vname[])
1732 char name[VOLSER_MAXVOLNAME + 1];
1734 strcpy(name, vname);
1736 while (name[i] == 'V' || name[i] == '0')
1739 name[11] = '\0'; /* smash the "." */
1740 return (atol(&name[i]));
1743 /*return the name of the next volume header in the directory associated with dirp and dp.
1744 *the volume id is returned in volid, and volume header name is returned in volname*/
1746 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1750 dp = readdir(dirp); /*read next entry in the directory */
1752 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1753 *volid = ExtractVolId(dp->d_name);
1754 strcpy(volname, dp->d_name);
1755 return 0; /*return the name of the file representing a volume */
1757 strcpy(volname, "");
1758 return 0; /*volname doesnot represent a volume */
1761 strcpy(volname, "EOD");
1762 return 0; /*end of directory */
1768 * volint vol info structure type.
1771 VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
1772 VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
1773 } volint_info_type_t;
1776 * handle to various on-wire vol info types.
1779 volint_info_type_t volinfo_type;
1785 } volint_info_handle_t;
1788 * store value to a field at the appropriate location in on-wire structure.
1790 #define VOLINT_INFO_STORE(handle, name, val) \
1792 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
1793 (handle)->volinfo_ptr.base->name = (val); \
1795 (handle)->volinfo_ptr.ext->name = (val); \
1800 * get pointer to appropriate offset of field in on-wire structure.
1802 #define VOLINT_INFO_PTR(handle, name) \
1803 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
1804 &((handle)->volinfo_ptr.base->name) : \
1805 &((handle)->volinfo_ptr.ext->name))
1808 * fill in appropriate type of on-wire volume metadata structure.
1810 * @param vp pointer to volume object
1811 * @param hdr pointer to volume disk data object
1812 * @param handle pointer to wire format handle object
1814 * @pre handle object must have a valid pointer and enumeration value
1816 * @return operation status
1821 FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
1823 unsigned int numStatBytes, now;
1825 /*read in the relevant info */
1826 strcpy(VOLINT_INFO_PTR(handle, name), hdr->name);
1827 VOLINT_INFO_STORE(handle, status, VOK); /*its ok */
1828 VOLINT_INFO_STORE(handle, volid, hdr->id);
1829 VOLINT_INFO_STORE(handle, type, hdr->type); /*if ro volume */
1830 VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId); /*if rw volume */
1831 VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
1832 VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
1833 VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
1834 VOLINT_INFO_STORE(handle, size, hdr->diskused);
1835 VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
1836 VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
1837 now = FT_ApproxTime();
1838 if ((now - hdr->dayUseDate) > OneDay) {
1839 VOLINT_INFO_STORE(handle, dayUse, 0);
1841 VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
1843 VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
1844 VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
1845 VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
1846 VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
1848 #ifdef AFS_DEMAND_ATTACH_FS
1850 * for DAFS, we "lie" about volume state --
1851 * instead of returning the raw state from the disk header,
1852 * we compute state based upon the fileserver's internal
1853 * in-core state enumeration value reported to us via fssync,
1854 * along with the blessed and inService flags from the header.
1855 * -- tkeiser 11/27/2007
1857 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1858 VIsErrorState(V_attachState(vp)) ||
1861 VOLINT_INFO_STORE(handle, inUse, 0);
1863 VOLINT_INFO_STORE(handle, inUse, 1);
1866 VOLINT_INFO_STORE(handle, inUse, hdr->inUse);
1870 switch(handle->volinfo_type) {
1871 case VOLINT_INFO_TYPE_BASE:
1873 #ifdef AFS_DEMAND_ATTACH_FS
1874 /* see comment above where we set inUse bit */
1875 if (hdr->needsSalvaged || VIsErrorState(V_attachState(vp))) {
1876 handle->volinfo_ptr.base->needsSalvaged = 1;
1878 handle->volinfo_ptr.base->needsSalvaged = 0;
1881 handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
1883 handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
1884 handle->volinfo_ptr.base->spare0 = hdr->minquota;
1885 handle->volinfo_ptr.base->spare1 =
1886 (long)hdr->weekUse[0] +
1887 (long)hdr->weekUse[1] +
1888 (long)hdr->weekUse[2] +
1889 (long)hdr->weekUse[3] +
1890 (long)hdr->weekUse[4] +
1891 (long)hdr->weekUse[5] +
1892 (long)hdr->weekUse[6];
1893 handle->volinfo_ptr.base->flags = 0;
1894 handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
1895 handle->volinfo_ptr.base->spare3 = 0;
1899 case VOLINT_INFO_TYPE_EXT:
1901 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1902 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1905 * Copy out the stat fields in a single operation.
1907 if ((now - hdr->dayUseDate) > OneDay) {
1908 memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1911 memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1912 (char *)&(hdr->stat_reads[0]),
1922 * get struct Volume out of the fileserver.
1924 * @param[in] volumeId volumeId for which we want state information
1925 * @param[out] vp pointer to Volume object
1927 * @return operation status
1929 * @retval nonzero failure
1932 GetVolObject(afs_uint32 volumeId, Volume * vp)
1937 res.hdr.response_len = sizeof(res.hdr);
1938 res.payload.buf = vp;
1939 res.payload.len = sizeof(*vp);
1941 code = FSYNC_VolOp(volumeId,
1951 * mode of volume list operation.
1954 VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
1955 VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
1956 } vol_info_list_mode_t;
1959 * abstract interface to populate wire-format volume metadata structures.
1961 * @param[in] partId partition id
1962 * @param[in] volumeId volume id
1963 * @param[in] pname partition name
1964 * @param[in] volname volume file name
1965 * @param[in] handle handle to on-wire volume metadata object
1966 * @param[in] mode listing mode
1968 * @return operation status
1970 * @retval -2 DESTROY_ME flag is set
1971 * @retval -1 general failure; some data filled in
1972 * @retval -3 couldn't create vtrans; some data filled in
1975 GetVolInfo(afs_uint32 partId,
1976 afs_uint32 volumeId,
1979 volint_info_handle_t * handle,
1980 vol_info_list_mode_t mode)
1984 struct volser_trans *ttc = NULL;
1985 struct Volume fs_tv, *tv = NULL;
1987 ttc = NewTrans(volumeId, partId);
1990 VOLINT_INFO_STORE(handle, status, VBUSY);
1991 VOLINT_INFO_STORE(handle, volid, volumeId);
1995 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
1997 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
1998 volumeId, pname, volname, error);
2003 * please note that destroyMe and needsSalvaged checks used to be ordered
2004 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2005 * more correct to check destroyMe before needsSalvaged.
2006 * -- tkeiser 11/28/2007
2009 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
2011 case VOL_INFO_LIST_MULTIPLE:
2015 case VOL_INFO_LIST_SINGLE:
2016 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
2017 volumeId, pname, volname);
2024 if (tv->header->diskstuff.needsSalvaged) {
2025 /*this volume will be salvaged */
2026 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2027 volumeId, pname, volname);
2031 #ifdef AFS_DEMAND_ATTACH_FS
2032 if (GetVolObject(volumeId, &fs_tv)) {
2037 /* ok, we have all the data we need; fill in the on-wire struct */
2038 code = FillVolInfo(&fs_tv, &tv->header->diskstuff, handle);
2043 VOLINT_INFO_STORE(handle, status, 0);
2044 strcpy(VOLINT_INFO_PTR(handle, name), volname);
2045 VOLINT_INFO_STORE(handle, volid, volumeId);
2048 VDetachVolume(&error, tv);
2051 VOLINT_INFO_STORE(handle, status, 0);
2052 strcpy(VOLINT_INFO_PTR(handle, name), volname);
2053 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2054 volumeId, pname, volname);
2058 DeleteTrans(ttc, 1);
2065 /*return the header information about the <volid> */
2067 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2068 volumeId, volEntries *volumeInfo)
2072 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2073 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
2078 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2079 volumeId, volEntries *volumeInfo)
2082 struct DiskPartition64 *partP;
2083 char pname[9], volname[20];
2084 afs_int32 error = 0;
2090 volint_info_handle_t handle;
2092 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2093 pntr = volumeInfo->volEntries_val;
2094 volumeInfo->volEntries_len = 1;
2095 if (GetPartName(partid, pname))
2096 return VOLSERILLEGAL_PARTITION;
2097 if (!(partP = VGetPartition(pname, 0)))
2098 return VOLSERILLEGAL_PARTITION;
2099 dirp = opendir(VPartitionPath(partP));
2101 return VOLSERILLEGAL_PARTITION;
2103 strcpy(volname, "");
2105 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2107 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2108 GetNextVol(dirp, volname, &volid);
2109 continue; /*back to while loop */
2112 if (volid == volumeId) { /*copy other things too */
2117 GetNextVol(dirp, volname, &volid);
2121 #ifndef AFS_PTHREAD_ENV
2122 IOMGR_Poll(); /*make sure that the client does not time out */
2125 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2126 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2128 code = GetVolInfo(partid,
2133 VOL_INFO_LIST_SINGLE);
2137 return (found) ? 0 : ENODEV;
2140 /*------------------------------------------------------------------------
2141 * EXPORTED SAFSVolXListOneVolume
2144 * Returns extended info on volume a_volID on partition a_partID.
2147 * a_rxCidP : Pointer to the Rx call we're performing.
2148 * a_partID : Partition for which we want the extended list.
2149 * a_volID : Volume ID we wish to know about.
2150 * a_volumeXInfoP : Ptr to the extended info blob.
2153 * 0 Successful operation
2154 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2157 * Nothing interesting.
2161 *------------------------------------------------------------------------*/
2164 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2165 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2169 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2170 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2175 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2176 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2177 { /*SAFSVolXListOneVolume */
2179 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2180 struct DiskPartition64 *partP; /*Ptr to partition */
2181 char pname[9], volname[20]; /*Partition, volume names */
2182 afs_int32 error; /*Error code */
2183 DIR *dirp; /*Partition directory ptr */
2184 afs_int32 currVolID; /*Current volume ID */
2185 int found = 0; /*Did we find the volume we need? */
2188 volint_info_handle_t handle;
2191 * Set up our pointers for action, marking our structure to hold exactly
2192 * one entry. Also, assume we'll fail in our quest.
2194 a_volumeXInfoP->volXEntries_val =
2195 (volintXInfo *) malloc(sizeof(volintXInfo));
2196 xInfoP = a_volumeXInfoP->volXEntries_val;
2197 a_volumeXInfoP->volXEntries_len = 1;
2201 * If the partition name we've been given is bad, bogue out.
2203 if (GetPartName(a_partID, pname))
2204 return (VOLSERILLEGAL_PARTITION);
2207 * Open the directory representing the given AFS parttion. If we can't
2210 if (!(partP = VGetPartition(pname, 0)))
2211 return VOLSERILLEGAL_PARTITION;
2212 dirp = opendir(VPartitionPath(partP));
2214 return (VOLSERILLEGAL_PARTITION);
2216 strcpy(volname, "");
2219 * Sweep through the partition directory, looking for the desired entry.
2220 * First, of course, figure out how many stat bytes to copy out of each
2223 while (strcmp(volname, "EOD") && !found) {
2225 * If this is not a volume, move on to the next entry in the
2226 * partition's directory.
2228 if (!strcmp(volname, "")) {
2229 GetNextVol(dirp, volname, &currVolID);
2233 if (currVolID == a_volID) {
2235 * We found the volume entry we're interested. Pull out the
2236 * extended information, remembering to poll (so that the client
2237 * doesn't time out) and to set up a transaction on the volume.
2241 } /*Found desired volume */
2243 GetNextVol(dirp, volname, &currVolID);
2247 #ifndef AFS_PTHREAD_ENV
2251 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2252 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2254 code = GetVolInfo(a_partID,
2259 VOL_INFO_LIST_SINGLE);
2264 * Clean up before going to dinner: close the partition directory,
2265 * return the proper value.
2268 return (found) ? 0 : ENODEV;
2269 } /*SAFSVolXListOneVolume */
2271 /*returns all the volumes on partition partid. If flags = 1 then all the
2272 * relevant info about the volumes is also returned */
2274 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2275 volEntries *volumeInfo)
2279 code = VolListVolumes(acid, partid, flags, volumeInfo);
2280 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2285 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2286 volEntries *volumeInfo)
2289 struct DiskPartition64 *partP;
2290 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2291 char pname[9], volname[20];
2292 afs_int32 error = 0;
2297 volint_info_handle_t handle;
2299 volumeInfo->volEntries_val =
2300 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2301 pntr = volumeInfo->volEntries_val;
2302 volumeInfo->volEntries_len = 0;
2303 if (GetPartName(partid, pname))
2304 return VOLSERILLEGAL_PARTITION;
2305 if (!(partP = VGetPartition(pname, 0)))
2306 return VOLSERILLEGAL_PARTITION;
2307 dirp = opendir(VPartitionPath(partP));
2309 return VOLSERILLEGAL_PARTITION;
2310 strcpy(volname, "");
2312 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2314 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2315 GetNextVol(dirp, volname, &volid);
2316 continue; /*back to while loop */
2319 if (flags) { /*copy other things too */
2320 #ifndef AFS_PTHREAD_ENV
2321 IOMGR_Poll(); /*make sure that the client does not time out */
2324 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2325 handle.volinfo_ptr.base = pntr;
2328 code = GetVolInfo(partid,
2333 VOL_INFO_LIST_MULTIPLE);
2334 if (code == -2) { /* DESTROY_ME flag set */
2338 pntr->volid = volid;
2339 /*just volids are needed */
2344 volumeInfo->volEntries_len += 1;
2345 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2346 /*running out of space, allocate more space */
2347 allocSize = (allocSize * 3) / 2;
2349 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2350 allocSize * sizeof(volintInfo));
2353 return VOLSERNO_MEMORY;
2355 volumeInfo->volEntries_val = pntr; /* point to new block */
2356 /* set pntr to the right position */
2357 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2362 GetNextVol(dirp, volname, &volid);
2370 /*------------------------------------------------------------------------
2371 * EXPORTED SAFSVolXListVolumes
2374 * Returns all the volumes on partition a_partID. If a_flags
2375 * is set to 1, then all the relevant extended volume information
2379 * a_rxCidP : Pointer to the Rx call we're performing.
2380 * a_partID : Partition for which we want the extended list.
2381 * a_flags : Various flags.
2382 * a_volumeXInfoP : Ptr to the extended info blob.
2385 * 0 Successful operation
2386 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2387 * VOLSERNO_MEMORY if we ran out of memory allocating
2391 * Nothing interesting.
2395 *------------------------------------------------------------------------*/
2398 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2399 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2403 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2404 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2409 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2410 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2411 { /*SAFSVolXListVolumes */
2413 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2414 struct DiskPartition64 *partP; /*Ptr to partition */
2415 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2416 char pname[9], volname[20]; /*Partition, volume names */
2417 afs_int32 error = 0; /*Return code */
2418 DIR *dirp; /*Partition directory ptr */
2419 afs_int32 volid; /*Current volume ID */
2422 volint_info_handle_t handle;
2425 * Allocate a large array of extended volume info structures, then
2426 * set it up for action.
2428 a_volumeXInfoP->volXEntries_val =
2429 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2430 xInfoP = a_volumeXInfoP->volXEntries_val;
2431 a_volumeXInfoP->volXEntries_len = 0;
2434 * If the partition name we've been given is bad, bogue out.
2436 if (GetPartName(a_partID, pname))
2437 return (VOLSERILLEGAL_PARTITION);
2440 * Open the directory representing the given AFS parttion. If we can't
2443 if (!(partP = VGetPartition(pname, 0)))
2444 return VOLSERILLEGAL_PARTITION;
2445 dirp = opendir(VPartitionPath(partP));
2447 return (VOLSERILLEGAL_PARTITION);
2448 strcpy(volname, "");
2451 * Sweep through the partition directory, acting on each entry. First,
2452 * of course, figure out how many stat bytes to copy out of each volume.
2454 while (strcmp(volname, "EOD")) {
2457 * If this is not a volume, move on to the next entry in the
2458 * partition's directory.
2460 if (!strcmp(volname, "")) {
2461 GetNextVol(dirp, volname, &volid);
2467 * Full info about the volume desired. Poll to make sure the
2468 * client doesn't time out, then start up a new transaction.
2470 #ifndef AFS_PTHREAD_ENV
2474 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2475 handle.volinfo_ptr.ext = xInfoP;
2477 code = GetVolInfo(a_partID,
2482 VOL_INFO_LIST_MULTIPLE);
2483 if (code == -2) { /* DESTROY_ME flag set */
2488 * Just volume IDs are needed.
2490 xInfoP->volid = volid;
2495 * Bump the pointer in the data area we're building, along with
2496 * the count of the number of entries it contains.
2499 (a_volumeXInfoP->volXEntries_len)++;
2500 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2502 * We're running out of space in the area we've built. Grow it.
2504 allocSize = (allocSize * 3) / 2;
2505 xInfoP = (volintXInfo *)
2506 realloc((char *)a_volumeXInfoP->volXEntries_val,
2507 (allocSize * sizeof(volintXInfo)));
2508 if (xInfoP == NULL) {
2510 * Bummer, no memory. Bag it, tell our caller what went wrong.
2513 return (VOLSERNO_MEMORY);
2517 * Memory reallocation worked. Correct our pointers so they
2518 * now point to the new block and the current open position within
2521 a_volumeXInfoP->volXEntries_val = xInfoP;
2523 a_volumeXInfoP->volXEntries_val +
2524 a_volumeXInfoP->volXEntries_len;
2528 GetNextVol(dirp, volname, &volid);
2529 } /*Sweep through the partition directory */
2532 * We've examined all entries in the partition directory. Close it,
2533 * delete our transaction (if any), and go home happy.
2538 } /*SAFSVolXListVolumes */
2540 /*this call is used to monitor the status of volser for debugging purposes.
2541 *information about all the active transactions is returned in transInfo*/
2543 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2547 code = VolMonitor(acid, transInfo);
2548 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2553 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2555 transDebugInfo *pntr;
2556 afs_int32 allocSize = 50;
2557 struct volser_trans *tt, *allTrans;
2559 transInfo->transDebugEntries_val =
2560 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2561 pntr = transInfo->transDebugEntries_val;
2562 transInfo->transDebugEntries_len = 0;
2563 allTrans = TransList();
2564 if (allTrans == (struct volser_trans *)0)
2565 return 0; /*no active transactions */
2566 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2567 pntr->tid = tt->tid;
2568 pntr->time = tt->time;
2569 pntr->creationTime = tt->creationTime;
2570 pntr->returnCode = tt->returnCode;
2571 pntr->volid = tt->volid;
2572 pntr->partition = tt->partition;
2573 pntr->iflags = tt->iflags;
2574 pntr->vflags = tt->vflags;
2575 pntr->tflags = tt->tflags;
2576 strcpy(pntr->lastProcName, tt->lastProcName);
2577 pntr->callValid = 0;
2578 if (tt->rxCallPtr) { /*record call related info */
2579 pntr->callValid = 1;
2580 pntr->readNext = tt->rxCallPtr->rnext;
2581 pntr->transmitNext = tt->rxCallPtr->tnext;
2582 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2583 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2586 transInfo->transDebugEntries_len += 1;
2587 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2588 allocSize = (allocSize * 3) / 2;
2590 (transDebugInfo *) realloc((char *)transInfo->
2591 transDebugEntries_val,
2593 sizeof(transDebugInfo));
2594 transInfo->transDebugEntries_val = pntr;
2596 transInfo->transDebugEntries_val +
2597 transInfo->transDebugEntries_len;
2598 /*set pntr to right position */
2607 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2611 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2612 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2613 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2619 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2622 afs_int32 error = 0;
2623 register struct volser_trans *tt;
2624 char caller[MAXKTCNAMELEN];
2626 if (strlen(name) > 31)
2627 return VOLSERBADNAME;
2628 if (!afsconf_SuperUser(tdir, acid, caller))
2629 return VOLSERBAD_ACCESS; /*not a super user */
2630 /* find the trans */
2631 tt = FindTrans(atid);
2634 if (tt->vflags & VTDeleted) {
2635 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2639 strcpy(tt->lastProcName, "SetIdsTypes");
2640 tt->rxCallPtr = acid;
2644 V_backupId(tv) = backupId;
2645 V_cloneId(tv) = cloneId;
2646 V_parentId(tv) = pId;
2647 strcpy((&V_disk(tv))->name, name);
2648 VUpdateVolume(&error, tv);
2650 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2654 tt->rxCallPtr = (struct rx_call *)0;
2655 if (TRELE(tt) && !error)
2656 return VOLSERTRELE_ERROR;
2660 tt->rxCallPtr = (struct rx_call *)0;
2661 if (TRELE(tt) && !error)
2662 return VOLSERTRELE_ERROR;
2667 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2671 code = VolSetDate(acid, atid, cdate);
2672 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2678 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2681 afs_int32 error = 0;
2682 register struct volser_trans *tt;
2683 char caller[MAXKTCNAMELEN];
2685 if (!afsconf_SuperUser(tdir, acid, caller))
2686 return VOLSERBAD_ACCESS; /*not a super user */
2687 /* find the trans */
2688 tt = FindTrans(atid);
2691 if (tt->vflags & VTDeleted) {
2692 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2696 strcpy(tt->lastProcName, "SetDate");
2697 tt->rxCallPtr = acid;
2700 V_creationDate(tv) = cdate;
2701 VUpdateVolume(&error, tv);
2703 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2707 tt->rxCallPtr = (struct rx_call *)0;
2708 if (TRELE(tt) && !error)
2709 return VOLSERTRELE_ERROR;
2713 tt->rxCallPtr = (struct rx_call *)0;
2714 if (TRELE(tt) && !error)
2715 return VOLSERTRELE_ERROR;
2720 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2726 char caller[MAXKTCNAMELEN];
2728 register struct volser_trans *ttc;
2729 char pname[16], volname[20];
2730 struct DiskPartition64 *partP;
2731 afs_int32 ret = ENODEV;
2734 if (!afsconf_SuperUser(tdir, acid, caller))
2735 return VOLSERBAD_ACCESS; /*not a super user */
2736 if (GetPartName(partId, pname))
2737 return VOLSERILLEGAL_PARTITION;
2738 if (!(partP = VGetPartition(pname, 0)))
2739 return VOLSERILLEGAL_PARTITION;
2740 dirp = opendir(VPartitionPath(partP));
2742 return VOLSERILLEGAL_PARTITION;
2743 strcpy(volname, "");
2744 ttc = (struct volser_trans *)0;
2746 while (strcmp(volname, "EOD")) {
2747 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2748 GetNextVol(dirp, volname, &volid);
2749 continue; /*back to while loop */
2752 if (volid == volumeId) { /*copy other things too */
2753 #ifndef AFS_PTHREAD_ENV
2754 IOMGR_Poll(); /*make sure that the client doesnot time out */
2756 ttc = NewTrans(volumeId, partId);
2760 #ifdef AFS_NAMEI_ENV
2761 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2763 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2767 GetNextVol(dirp, volname, &volid);
2771 DeleteTrans(ttc, 1);
2772 ttc = (struct volser_trans *)0;
2781 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2782 register struct volintSize *size)
2785 register struct volser_trans *tt;
2786 char caller[MAXKTCNAMELEN];
2788 if (!afsconf_SuperUser(tdir, acid, caller))
2789 return VOLSERBAD_ACCESS; /*not a super user */
2790 tt = FindTrans(fromTrans);
2793 if (tt->vflags & VTDeleted) {
2797 strcpy(tt->lastProcName, "GetSize");
2798 tt->rxCallPtr = acid;
2799 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2800 tt->rxCallPtr = (struct rx_call *)0;
2802 return VOLSERTRELE_ERROR;
2804 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2808 /* GetPartName - map partid (a decimal number) into pname (a string)
2809 * Since for NT we actually want to return the drive name, we map through the
2813 GetPartName(afs_int32 partid, char *pname)
2818 strcpy(pname, "/vicep");
2819 pname[6] = 'a' + partid;
2822 } else if (partid < VOLMAXPARTS) {
2823 strcpy(pname, "/vicep");
2825 pname[6] = 'a' + (partid / 26);
2826 pname[7] = 'a' + (partid % 26);