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 DiskPartition *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
291 code = VolPartitionInfo(acid, pname, partition);
292 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
297 VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
300 register struct DiskPartition *dp;
303 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
306 dp = VGetPartition(pname, 0);
308 strncpy(partition->name, dp->name, 32);
309 strncpy(partition->devName, dp->devName, 32);
310 partition->lock_fd = dp->lock_fd;
311 partition->free = dp->free;
312 partition->minFree = dp->totalUsable;
315 return VOLSERILLEGAL_PARTITION;
318 /* obliterate a volume completely, and slowly. */
320 SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
324 code = VolNukeVolume(acid, apartID, avolID);
325 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
330 VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
335 register afs_int32 code;
337 char caller[MAXKTCNAMELEN];
339 /* check for access */
340 if (!afsconf_SuperUser(tdir, acid, caller))
341 return VOLSERBAD_ACCESS;
343 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
345 tp = volutil_PartitionName(apartID);
348 strcpy(partName, tp); /* remember it for later */
349 /* we first try to attach the volume in update mode, so that the file
350 * server doesn't try to use it (and abort) while (or after) we delete it.
351 * If we don't get the volume, that's fine, too. We just won't put it back.
353 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
354 code = nuke(partName, avolID);
356 VDetachVolume(&error, tvp);
360 /* create a new volume, with name aname, on the specified partition (1..n)
361 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
362 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
363 * for the volume id (useful for things like volume restore).
364 * Return the new volume id in *avolid.
367 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
368 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
374 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
375 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
376 *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
382 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
383 afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
388 afs_int32 junk; /* discardable error code */
389 register afs_int32 volumeID, doCreateRoot = 1;
390 register struct volser_trans *tt;
392 char caller[MAXKTCNAMELEN];
394 if (strlen(aname) > 31)
395 return VOLSERBADNAME;
396 if (!afsconf_SuperUser(tdir, acid, caller))
397 return VOLSERBAD_ACCESS;
399 Log("%s is executing CreateVolume '%s'\n", caller, aname);
400 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
401 return error; /*a standard unix error */
402 if (atype != readwriteVolume && atype != readonlyVolume
403 && atype != backupVolume)
405 if ((volumeID = *avolid) == 0) {
407 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
411 if ((aparent == volumeID) && (atype == readwriteVolume)) {
416 tt = NewTrans(volumeID, apart);
418 Log("1 createvolume: failed to create trans\n");
419 return VOLSERVOLBUSY; /* volume already busy! */
421 vp = VCreateVolume(&error, ppath, volumeID, aparent);
423 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
428 V_uniquifier(vp) = 1;
429 V_creationDate(vp) = V_copyDate(vp);
430 V_inService(vp) = V_blessed(vp) = 1;
432 AssignVolumeName(&V_disk(vp), aname, 0);
435 V_destroyMe(vp) = DESTROY_ME;
437 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
438 VUpdateVolume(&error, vp);
440 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
443 VDetachVolume(&junk, vp); /* rather return the real error code */
448 strcpy(tt->lastProcName, "CreateVolume");
449 tt->rxCallPtr = acid;
450 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
451 tt->rxCallPtr = (struct rx_call *)0;
453 return VOLSERTRELE_ERROR;
457 /* delete the volume associated with this transaction */
459 SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
463 code = VolDeleteVolume(acid, atrans);
464 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
469 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
471 register struct volser_trans *tt;
473 char caller[MAXKTCNAMELEN];
475 if (!afsconf_SuperUser(tdir, acid, caller))
476 return VOLSERBAD_ACCESS;
477 tt = FindTrans(atrans);
480 if (tt->vflags & VTDeleted) {
481 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
486 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
487 strcpy(tt->lastProcName, "DeleteVolume");
488 tt->rxCallPtr = acid;
489 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
490 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
491 tt->rxCallPtr = (struct rx_call *)0;
493 return VOLSERTRELE_ERROR;
495 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
496 return 0; /* vpurgevolume doesn't set an error code */
499 /* make a clone of the volume associated with atrans, possibly giving it a new
500 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
501 * for the clone's id). The new clone is given the name newName. Finally, due to
502 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
503 * the clone operation. This may be useful when making new backup volumes, for instance
504 * since the net result of a clone and a purge generally leaves many inode ref counts
505 * the same, while doing them separately would result in far more iincs and idecs being
506 * peformed (and they are slow operations).
508 /* for efficiency reasons, sometimes faster to piggyback a purge here */
510 SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
511 afs_int32 newType, char *newName, afs_int32 *newNumber)
515 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
516 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
517 AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
523 VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
524 afs_int32 newType, char *newName, afs_int32 *newNumber)
527 register struct Volume *originalvp, *purgevp, *newvp;
529 register struct volser_trans *tt, *ttc;
530 char caller[MAXKTCNAMELEN];
532 if (strlen(newName) > 31)
533 return VOLSERBADNAME;
534 if (!afsconf_SuperUser(tdir, acid, caller))
535 return VOLSERBAD_ACCESS; /*not a super user */
537 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
539 originalvp = (Volume *) 0;
540 purgevp = (Volume *) 0;
541 newvp = (Volume *) 0;
542 tt = ttc = (struct volser_trans *)0;
544 if (!newNumber || !*newNumber) {
545 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
550 if (newType != readonlyVolume && newType != backupVolume)
552 tt = FindTrans(atrans);
555 if (tt->vflags & VTDeleted) {
556 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
560 ttc = NewTrans(newId, tt->partition);
561 if (!ttc) { /* someone is messing with the clone already */
565 strcpy(tt->lastProcName, "Clone");
566 tt->rxCallPtr = acid;
570 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
572 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
578 originalvp = tt->volume;
579 if ((V_type(originalvp) == backupVolume)
580 || (V_type(originalvp) == readonlyVolume)) {
581 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
585 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
586 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
592 if (originalvp->device != purgevp->device) {
593 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
597 if (V_type(purgevp) != readonlyVolume) {
598 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
602 if (V_type(originalvp) == readonlyVolume
603 && V_parentId(originalvp) != V_parentId(purgevp)) {
604 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
608 if (V_type(originalvp) == readwriteVolume
609 && tt->volid != V_parentId(purgevp)) {
610 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
619 VCreateVolume(&error, originalvp->partition->name, newId,
620 V_parentId(originalvp));
622 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
623 newvp = (Volume *) 0;
626 if (newType == readonlyVolume)
627 V_cloneId(originalvp) = newId;
628 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
631 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
632 CloneVolume(&error, originalvp, newvp, purgevp);
633 purgevp = NULL; /* clone releases it, maybe even if error */
635 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
639 if (newType == readonlyVolume) {
640 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
641 V_type(newvp) = readonlyVolume;
642 } else if (newType == backupVolume) {
643 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
644 V_type(newvp) = backupVolume;
645 V_backupId(originalvp) = newId;
647 strcpy(newvp->header->diskstuff.name, newName);
648 V_creationDate(newvp) = V_copyDate(newvp);
649 ClearVolumeStats(&V_disk(newvp));
650 V_destroyMe(newvp) = DESTROY_ME;
651 V_inService(newvp) = 0;
652 if (newType == backupVolume) {
653 V_backupDate(originalvp) = V_copyDate(newvp);
654 V_backupDate(newvp) = V_copyDate(newvp);
657 VUpdateVolume(&error, newvp);
659 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
663 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
665 VUpdateVolume(&error, originalvp);
667 Log("1 Volser: Clone: original update %u\n", error);
671 tt->rxCallPtr = (struct rx_call *)0;
673 tt = (struct volser_trans *)0;
674 error = VOLSERTRELE_ERROR;
682 VDetachVolume(&code, purgevp);
684 VDetachVolume(&code, newvp);
686 tt->rxCallPtr = (struct rx_call *)0;
694 /* reclone this volume into the specified id */
696 SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
700 code = VolReClone(acid, atrans, cloneId);
701 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
707 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
709 register struct Volume *originalvp, *clonevp;
712 register struct volser_trans *tt, *ttc;
713 char caller[MAXKTCNAMELEN];
715 /*not a super user */
716 if (!afsconf_SuperUser(tdir, acid, caller))
717 return VOLSERBAD_ACCESS;
719 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
721 clonevp = originalvp = (Volume *) 0;
722 tt = (struct volser_trans *)0;
724 tt = FindTrans(atrans);
727 if (tt->vflags & VTDeleted) {
728 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
732 ttc = NewTrans(cloneId, tt->partition);
733 if (!ttc) { /* someone is messing with the clone already */
737 strcpy(tt->lastProcName, "ReClone");
738 tt->rxCallPtr = acid;
740 originalvp = tt->volume;
741 if ((V_type(originalvp) == backupVolume)
742 || (V_type(originalvp) == readonlyVolume)) {
743 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
747 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
748 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
754 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
756 Log("1 Volser: can't attach clone %d\n", cloneId);
760 newType = V_type(clonevp); /* type of the new volume */
762 if (originalvp->device != clonevp->device) {
763 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
768 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
769 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
773 if (V_type(originalvp) == readonlyVolume
774 && V_parentId(originalvp) != V_parentId(clonevp)) {
775 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
779 if (V_type(originalvp) == readwriteVolume
780 && tt->volid != V_parentId(clonevp)) {
781 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
787 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
789 CloneVolume(&error, originalvp, clonevp, clonevp);
791 Log("1 Volser: Clone: reclone operation failed with code %d\n",
797 /* fix up volume name and type, CloneVolume just propagated RW's */
798 if (newType == readonlyVolume) {
799 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
800 V_type(clonevp) = readonlyVolume;
801 } else if (newType == backupVolume) {
802 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
803 V_type(clonevp) = backupVolume;
804 V_backupId(originalvp) = cloneId;
806 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
808 /* pretend recloned volume is a totally new instance */
809 V_copyDate(clonevp) = time(0);
810 V_creationDate(clonevp) = V_copyDate(clonevp);
811 ClearVolumeStats(&V_disk(clonevp));
812 V_destroyMe(clonevp) = 0;
813 V_inService(clonevp) = 0;
814 if (newType == backupVolume) {
815 V_backupDate(originalvp) = V_copyDate(clonevp);
816 V_backupDate(clonevp) = V_copyDate(clonevp);
818 V_inUse(clonevp) = 0;
819 VUpdateVolume(&error, clonevp);
821 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
825 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
827 VUpdateVolume(&error, originalvp);
829 Log("1 Volser: Clone: original update %u\n", error);
833 tt->rxCallPtr = (struct rx_call *)0;
835 tt = (struct volser_trans *)0;
836 error = VOLSERTRELE_ERROR;
843 struct DiskPartition *tpartp = originalvp->partition;
844 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
850 VDetachVolume(&code, clonevp);
852 tt->rxCallPtr = (struct rx_call *)0;
860 /* create a new transaction, associated with volume and partition. Type of
861 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
862 * See volser.h for definition of iflags (the constants are named IT*).
865 SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
866 afs_int32 iflags, afs_int32 *ttid)
870 code = VolTransCreate(acid, volume, partition, iflags, ttid);
871 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
877 VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
878 afs_int32 iflags, afs_int32 *ttid)
880 register struct volser_trans *tt;
882 afs_int32 error, code;
884 char caller[MAXKTCNAMELEN];
886 if (!afsconf_SuperUser(tdir, acid, caller))
887 return VOLSERBAD_ACCESS; /*not a super user */
888 if (iflags & ITCreate)
890 else if (iflags & ITBusy)
892 else if (iflags & ITReadOnly)
894 else if (iflags & ITOffline)
897 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
902 tt = NewTrans(volume, partition);
904 /* can't create a transaction? put the volume back */
905 Log("1 transcreate: can't create transaction\n");
906 return VOLSERVOLBUSY;
908 tv = XAttachVolume(&error, volume, partition, mode);
912 VDetachVolume(&code, tv);
920 strcpy(tt->lastProcName, "TransCreate");
922 return VOLSERTRELE_ERROR;
927 /* using aindex as a 0-based index, return the aindex'th volume on this server
928 * Both the volume number and partition number (one-based) are returned.
931 SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
936 code = VolGetNthVolume(acid, aindex, avolume, apart);
937 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
942 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
945 Log("1 Volser: GetNthVolume: Not yet implemented\n");
949 /* return the volume flags (VT* constants in volser.h) associated with this
953 SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
957 code = VolGetFlags(acid, atid, aflags);
958 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
963 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
965 register struct volser_trans *tt;
967 tt = FindTrans(atid);
970 if (tt->vflags & VTDeleted) {
971 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
976 strcpy(tt->lastProcName, "GetFlags");
977 tt->rxCallPtr = acid;
978 *aflags = tt->vflags;
979 tt->rxCallPtr = (struct rx_call *)0;
981 return VOLSERTRELE_ERROR;
986 /* Change the volume flags (VT* constants in volser.h) associated with this
987 * transaction. Effects take place immediately on volume, although volume
988 * remains attached as usual by the transaction.
991 SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
995 code = VolSetFlags(acid, atid, aflags);
996 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
1002 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1004 register struct volser_trans *tt;
1005 register struct Volume *vp;
1007 char caller[MAXKTCNAMELEN];
1009 if (!afsconf_SuperUser(tdir, acid, caller))
1010 return VOLSERBAD_ACCESS; /*not a super user */
1011 /* find the trans */
1012 tt = FindTrans(atid);
1015 if (tt->vflags & VTDeleted) {
1016 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1021 strcpy(tt->lastProcName, "SetFlags");
1022 tt->rxCallPtr = acid;
1023 vp = tt->volume; /* pull volume out of transaction */
1025 /* check if we're allowed to make any updates */
1026 if (tt->iflags & ITReadOnly) {
1031 /* handle delete-on-salvage flag */
1032 if (aflags & VTDeleteOnSalvage) {
1033 V_destroyMe(tt->volume) = DESTROY_ME;
1035 V_destroyMe(tt->volume) = 0;
1038 if (aflags & VTOutOfService) {
1039 V_inService(vp) = 0;
1041 V_inService(vp) = 1;
1043 VUpdateVolume(&error, vp);
1044 tt->vflags = aflags;
1045 if (TRELE(tt) && !error)
1046 return VOLSERTRELE_ERROR;
1051 /* dumpS the volume associated with a particular transaction from a particular
1052 * date. Send the dump to a different transaction (destTrans) on the server
1053 * specified by the destServer structure.
1056 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1057 struct destServer *destination, afs_int32 destTrans,
1058 struct restoreCookie *cookie)
1063 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1064 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
1065 destination->destHost, AUD_LONG, destTrans, AUD_END);
1070 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1071 struct destServer *destination, afs_int32 destTrans,
1072 struct restoreCookie *cookie)
1074 register struct volser_trans *tt;
1075 register afs_int32 code;
1076 register struct rx_connection *tcon;
1077 struct rx_call *tcall;
1078 register struct Volume *vp;
1079 struct rx_securityClass *securityObject;
1080 afs_int32 securityIndex;
1081 char caller[MAXKTCNAMELEN];
1083 if (!afsconf_SuperUser(tdir, acid, caller))
1084 return VOLSERBAD_ACCESS; /*not a super user */
1085 /* initialize things */
1086 tcon = (struct rx_connection *)0;
1087 tt = (struct volser_trans *)0;
1089 /* find the local transaction */
1090 tt = FindTrans(fromTrans);
1093 if (tt->vflags & VTDeleted) {
1094 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1099 strcpy(tt->lastProcName, "Forward");
1101 /* get auth info for the this connection (uses afs from ticket file) */
1102 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1108 /* make an rpc connection to the other server */
1110 rx_NewConnection(htonl(destination->destHost),
1111 htons(destination->destPort), VOLSERVICE_ID,
1112 securityObject, securityIndex);
1114 tt->rxCallPtr = (struct rx_call *)0;
1118 tcall = rx_NewCall(tcon);
1119 tt->rxCallPtr = tcall;
1120 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1121 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1126 /* these next calls implictly call rx_Write when writing out data */
1127 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1130 EndAFSVolRestore(tcall); /* probably doesn't do much */
1131 tt->rxCallPtr = (struct rx_call *)0;
1132 code = rx_EndCall(tcall, 0);
1133 rx_DestroyConnection(tcon); /* done with the connection */
1138 return VOLSERTRELE_ERROR;
1144 (void)rx_EndCall(tcall, 0);
1145 rx_DestroyConnection(tcon);
1148 tt->rxCallPtr = (struct rx_call *)0;
1154 /* Start a dump and send it to multiple places simultaneously.
1155 * If this returns an error (eg, return ENOENT), it means that
1156 * none of the releases worked. If this returns 0, that means
1157 * that one or more of the releases worked, and the caller has
1158 * to examine the results array to see which one(s).
1159 * This will only do EITHER incremental or full, not both, so it's
1160 * the caller's responsibility to be sure that all the destinations
1161 * need just an incremental (and from the same time), if that's
1165 SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1166 fromDate, manyDests *destinations, afs_int32 spare,
1167 struct restoreCookie *cookie, manyResults *results)
1169 afs_int32 securityIndex;
1170 struct rx_securityClass *securityObject;
1171 char caller[MAXKTCNAMELEN];
1172 struct volser_trans *tt;
1173 afs_int32 ec, code, *codes;
1174 struct rx_connection **tcons;
1175 struct rx_call **tcalls;
1177 int i, is_incremental;
1180 memset(results, 0, sizeof(manyResults));
1182 if (!afsconf_SuperUser(tdir, acid, caller))
1183 return VOLSERBAD_ACCESS; /*not a super user */
1184 tt = FindTrans(fromTrans);
1187 if (tt->vflags & VTDeleted) {
1188 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1193 strcpy(tt->lastProcName, "ForwardMulti");
1195 /* (fromDate == 0) ==> full dump */
1196 is_incremental = (fromDate ? 1 : 0);
1198 i = results->manyResults_len = destinations->manyDests_len;
1199 results->manyResults_val = codes =
1200 (afs_int32 *) malloc(i * sizeof(afs_int32));
1202 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1203 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1205 /* get auth info for this connection (uses afs from ticket file) */
1206 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1208 goto fail; /* in order to audit each failure */
1211 /* make connections to all the other servers */
1212 for (i = 0; i < destinations->manyDests_len; i++) {
1213 struct replica *dest = &(destinations->manyDests_val[i]);
1215 rx_NewConnection(htonl(dest->server.destHost),
1216 htons(dest->server.destPort), VOLSERVICE_ID,
1217 securityObject, securityIndex);
1219 codes[i] = ENOTCONN;
1221 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1222 codes[i] = ENOTCONN;
1225 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1228 (void)rx_EndCall(tcalls[i], 0);
1230 rx_DestroyConnection(tcons[i]);
1237 /* these next calls implictly call rx_Write when writing out data */
1238 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1242 for (i--; i >= 0; i--) {
1243 struct replica *dest = &(destinations->manyDests_val[i]);
1245 if (!code && tcalls[i] && !codes[i]) {
1246 EndAFSVolRestore(tcalls[i]);
1249 ec = rx_EndCall(tcalls[i], 0);
1254 rx_DestroyConnection(tcons[i]); /* done with the connection */
1257 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
1258 fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
1259 dest->trans, AUD_END);
1265 tt->rxCallPtr = (struct rx_call *)0;
1266 if (TRELE(tt) && !code) /* return the first code if it's set */
1267 return VOLSERTRELE_ERROR;
1274 SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1278 code = VolDump(acid, fromTrans, fromDate, 0);
1279 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1284 SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1288 code = VolDump(acid, fromTrans, fromDate, flags);
1289 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1294 VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
1297 register struct volser_trans *tt;
1298 char caller[MAXKTCNAMELEN];
1300 if (!afsconf_SuperUser(tdir, acid, caller))
1301 return VOLSERBAD_ACCESS; /*not a super user */
1302 tt = FindTrans(fromTrans);
1305 if (tt->vflags & VTDeleted) {
1306 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1310 strcpy(tt->lastProcName, "Dump");
1311 tt->rxCallPtr = acid;
1312 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
1313 ? 0 : 1); /* squirt out the volume's data, too */
1315 tt->rxCallPtr = (struct rx_call *)0;
1319 tt->rxCallPtr = (struct rx_call *)0;
1322 return VOLSERTRELE_ERROR;
1328 * Ha! No more helper process!
1331 SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1332 struct restoreCookie *cookie)
1336 code = VolRestore(acid, atrans, aflags, cookie);
1337 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1342 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1343 struct restoreCookie *cookie)
1345 register struct volser_trans *tt;
1346 register afs_int32 code, tcode;
1347 char caller[MAXKTCNAMELEN];
1349 if (!afsconf_SuperUser(tdir, acid, caller))
1350 return VOLSERBAD_ACCESS; /*not a super user */
1351 tt = FindTrans(atrans);
1354 if (tt->vflags & VTDeleted) {
1355 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1359 strcpy(tt->lastProcName, "Restore");
1360 tt->rxCallPtr = acid;
1362 DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
1364 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1365 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
1366 tt->rxCallPtr = (struct rx_call *)0;
1369 return (code ? code : tcode);
1372 /* end a transaction, returning the transaction's final error code in rcode */
1374 SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1378 code = VolEndTrans(acid, destTrans, rcode);
1379 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1384 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1386 register struct volser_trans *tt;
1387 char caller[MAXKTCNAMELEN];
1389 if (!afsconf_SuperUser(tdir, acid, caller))
1390 return VOLSERBAD_ACCESS; /*not a super user */
1391 tt = FindTrans(destTrans);
1395 *rcode = tt->returnCode;
1396 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1402 SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1406 code = VolSetForwarding(acid, atid, anewsite);
1407 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
1413 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1415 register struct volser_trans *tt;
1416 char caller[MAXKTCNAMELEN];
1418 if (!afsconf_SuperUser(tdir, acid, caller))
1419 return VOLSERBAD_ACCESS; /*not a super user */
1420 tt = FindTrans(atid);
1423 if (tt->vflags & VTDeleted) {
1424 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1429 strcpy(tt->lastProcName, "SetForwarding");
1430 tt->rxCallPtr = acid;
1431 FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
1432 tt->rxCallPtr = (struct rx_call *)0;
1434 return VOLSERTRELE_ERROR;
1440 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1441 register struct volser_status *astatus)
1445 code = VolGetStatus(acid, atrans, astatus);
1446 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1451 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1452 register struct volser_status *astatus)
1454 register struct Volume *tv;
1455 register struct VolumeDiskData *td;
1456 struct volser_trans *tt;
1459 tt = FindTrans(atrans);
1462 if (tt->vflags & VTDeleted) {
1463 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1468 strcpy(tt->lastProcName, "GetStatus");
1469 tt->rxCallPtr = acid;
1472 tt->rxCallPtr = (struct rx_call *)0;
1477 td = &tv->header->diskstuff;
1478 astatus->volID = td->id;
1479 astatus->nextUnique = td->uniquifier;
1480 astatus->type = td->type;
1481 astatus->parentID = td->parentId;
1482 astatus->cloneID = td->cloneId;
1483 astatus->backupID = td->backupId;
1484 astatus->restoredFromID = td->restoredFromId;
1485 astatus->maxQuota = td->maxquota;
1486 astatus->minQuota = td->minquota;
1487 astatus->owner = td->owner;
1488 astatus->creationDate = td->creationDate;
1489 astatus->accessDate = td->accessDate;
1490 astatus->updateDate = td->updateDate;
1491 astatus->expirationDate = td->expirationDate;
1492 astatus->backupDate = td->backupDate;
1493 astatus->copyDate = td->copyDate;
1494 tt->rxCallPtr = (struct rx_call *)0;
1496 return VOLSERTRELE_ERROR;
1502 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1503 register struct volintInfo *astatus)
1507 code = VolSetInfo(acid, atrans, astatus);
1508 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1513 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1514 register struct volintInfo *astatus)
1516 register struct Volume *tv;
1517 register struct VolumeDiskData *td;
1518 struct volser_trans *tt;
1519 char caller[MAXKTCNAMELEN];
1522 if (!afsconf_SuperUser(tdir, acid, caller))
1523 return VOLSERBAD_ACCESS; /*not a super user */
1524 tt = FindTrans(atrans);
1527 if (tt->vflags & VTDeleted) {
1528 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1532 strcpy(tt->lastProcName, "SetStatus");
1533 tt->rxCallPtr = acid;
1536 tt->rxCallPtr = (struct rx_call *)0;
1541 td = &tv->header->diskstuff;
1543 * Add more fields as necessary
1545 if (astatus->maxquota != -1)
1546 td->maxquota = astatus->maxquota;
1547 if (astatus->dayUse != -1)
1548 td->dayUse = astatus->dayUse;
1549 if (astatus->creationDate != -1)
1550 td->creationDate = astatus->creationDate;
1551 if (astatus->updateDate != -1)
1552 td->updateDate = astatus->updateDate;
1553 if (astatus->spare2 != -1)
1554 td->volUpdateCounter = (unsigned int)astatus->spare2;
1555 VUpdateVolume(&error, tv);
1556 tt->rxCallPtr = (struct rx_call *)0;
1558 return VOLSERTRELE_ERROR;
1564 SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1568 code = VolGetName(acid, atrans, aname);
1569 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1574 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1576 register struct Volume *tv;
1577 register struct VolumeDiskData *td;
1578 struct volser_trans *tt;
1582 tt = FindTrans(atrans);
1585 if (tt->vflags & VTDeleted) {
1586 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1590 strcpy(tt->lastProcName, "GetName");
1591 tt->rxCallPtr = acid;
1594 tt->rxCallPtr = (struct rx_call *)0;
1599 td = &tv->header->diskstuff;
1600 len = strlen(td->name) + 1; /* don't forget the null */
1602 tt->rxCallPtr = (struct rx_call *)0;
1606 *aname = (char *)malloc(len);
1607 strcpy(*aname, td->name);
1608 tt->rxCallPtr = (struct rx_call *)0;
1610 return VOLSERTRELE_ERROR;
1615 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1618 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1619 afs_int32 parentId, afs_int32 cloneId)
1625 /*return a list of all partitions on the server. The non mounted
1626 *partitions are returned as -1 in the corresponding slot in partIds*/
1628 SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1632 code = VolListPartitions(acid, partIds);
1633 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1638 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1643 strcpy(namehead, "/vicep"); /*7 including null terminator */
1645 /* Just return attached partitions. */
1647 for (i = 0; i < 26; i++) {
1648 namehead[6] = i + 'a';
1649 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1655 /*return a list of all partitions on the server. The non mounted
1656 *partitions are returned as -1 in the corresponding slot in partIds*/
1658 SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1662 code = XVolListPartitions(acid, pEntries);
1663 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1668 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1670 struct stat rbuf, pbuf;
1672 struct partList partList;
1673 struct DiskPartition *dp;
1676 strcpy(namehead, "/vicep"); /*7 including null terminator */
1678 /* Only report attached partitions */
1679 for (i = 0; i < VOLMAXPARTS; i++) {
1680 #ifdef AFS_DEMAND_ATTACH_FS
1681 dp = VGetPartitionById(i, 0);
1684 namehead[6] = i + 'a';
1688 namehead[6] = 'a' + (k / 26);
1689 namehead[7] = 'a' + (k % 26);
1692 dp = VGetPartition(namehead, 0);
1695 partList.partId[j++] = i;
1697 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1698 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1700 pEntries->partEntries_len = j;
1705 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1707 ExtractVolId(char vname[])
1710 char name[VOLSER_MAXVOLNAME + 1];
1712 strcpy(name, vname);
1714 while (name[i] == 'V' || name[i] == '0')
1717 name[11] = '\0'; /* smash the "." */
1718 return (atol(&name[i]));
1721 /*return the name of the next volume header in the directory associated with dirp and dp.
1722 *the volume id is returned in volid, and volume header name is returned in volname*/
1724 GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
1728 dp = readdir(dirp); /*read next entry in the directory */
1730 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
1731 *volid = ExtractVolId(dp->d_name);
1732 strcpy(volname, dp->d_name);
1733 return 0; /*return the name of the file representing a volume */
1735 strcpy(volname, "");
1736 return 0; /*volname doesnot represent a volume */
1739 strcpy(volname, "EOD");
1740 return 0; /*end of directory */
1746 * volint vol info structure type.
1749 VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
1750 VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
1751 } volint_info_type_t;
1754 * handle to various on-wire vol info types.
1757 volint_info_type_t volinfo_type;
1763 } volint_info_handle_t;
1766 * store value to a field at the appropriate location in on-wire structure.
1768 #define VOLINT_INFO_STORE(handle, name, val) \
1770 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
1771 (handle)->volinfo_ptr.base->name = (val); \
1773 (handle)->volinfo_ptr.ext->name = (val); \
1778 * get pointer to appropriate offset of field in on-wire structure.
1780 #define VOLINT_INFO_PTR(handle, name) \
1781 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
1782 &((handle)->volinfo_ptr.base->name) : \
1783 &((handle)->volinfo_ptr.ext->name))
1786 * fill in appropriate type of on-wire volume metadata structure.
1788 * @param vp pointer to volume object
1789 * @param hdr pointer to volume disk data object
1790 * @param handle pointer to wire format handle object
1792 * @pre handle object must have a valid pointer and enumeration value
1794 * @return operation status
1799 FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
1801 unsigned int numStatBytes, now;
1803 /*read in the relevant info */
1804 strcpy(VOLINT_INFO_PTR(handle, name), hdr->name);
1805 VOLINT_INFO_STORE(handle, status, VOK); /*its ok */
1806 VOLINT_INFO_STORE(handle, volid, hdr->id);
1807 VOLINT_INFO_STORE(handle, type, hdr->type); /*if ro volume */
1808 VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId); /*if rw volume */
1809 VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
1810 VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
1811 VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
1812 VOLINT_INFO_STORE(handle, size, hdr->diskused);
1813 VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
1814 VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
1815 now = FT_ApproxTime();
1816 if ((now - hdr->dayUseDate) > OneDay) {
1817 VOLINT_INFO_STORE(handle, dayUse, 0);
1819 VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
1821 VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
1822 VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
1823 VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
1824 VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
1826 #ifdef AFS_DEMAND_ATTACH_FS
1828 * for DAFS, we "lie" about volume state --
1829 * instead of returning the raw state from the disk header,
1830 * we compute state based upon the fileserver's internal
1831 * in-core state enumeration value reported to us via fssync,
1832 * along with the blessed and inService flags from the header.
1833 * -- tkeiser 11/27/2007
1835 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1836 VIsErrorState(V_attachState(vp)) ||
1839 VOLINT_INFO_STORE(handle, inUse, 0);
1841 VOLINT_INFO_STORE(handle, inUse, 1);
1844 VOLINT_INFO_STORE(handle, inUse, hdr->inUse);
1848 switch(handle->volinfo_type) {
1849 case VOLINT_INFO_TYPE_BASE:
1851 #ifdef AFS_DEMAND_ATTACH_FS
1852 /* see comment above where we set inUse bit */
1853 if (hdr->needsSalvaged || VIsErrorState(V_attachState(vp))) {
1854 handle->volinfo_ptr.base->needsSalvaged = 1;
1856 handle->volinfo_ptr.base->needsSalvaged = 0;
1859 handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
1861 handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
1862 handle->volinfo_ptr.base->spare0 = hdr->minquota;
1863 handle->volinfo_ptr.base->spare1 =
1864 (long)hdr->weekUse[0] +
1865 (long)hdr->weekUse[1] +
1866 (long)hdr->weekUse[2] +
1867 (long)hdr->weekUse[3] +
1868 (long)hdr->weekUse[4] +
1869 (long)hdr->weekUse[5] +
1870 (long)hdr->weekUse[6];
1871 handle->volinfo_ptr.base->flags = 0;
1872 handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
1873 handle->volinfo_ptr.base->spare3 = 0;
1877 case VOLINT_INFO_TYPE_EXT:
1879 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
1880 (4 * VOLINT_STATS_NUM_TIME_FIELDS));
1883 * Copy out the stat fields in a single operation.
1885 if ((now - hdr->dayUseDate) > OneDay) {
1886 memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1889 memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
1890 (char *)&(hdr->stat_reads[0]),
1900 * get struct Volume out of the fileserver.
1902 * @param[in] volumeId volumeId for which we want state information
1903 * @param[out] vp pointer to Volume object
1905 * @return operation status
1907 * @retval nonzero failure
1910 GetVolObject(afs_uint32 volumeId, Volume * vp)
1915 res.hdr.response_len = sizeof(res.hdr);
1916 res.payload.buf = vp;
1917 res.payload.len = sizeof(*vp);
1919 code = FSYNC_VolOp(volumeId,
1929 * mode of volume list operation.
1932 VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
1933 VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
1934 } vol_info_list_mode_t;
1937 * abstract interface to populate wire-format volume metadata structures.
1939 * @param[in] partId partition id
1940 * @param[in] volumeId volume id
1941 * @param[in] pname partition name
1942 * @param[in] volname volume file name
1943 * @param[in] handle handle to on-wire volume metadata object
1944 * @param[in] mode listing mode
1946 * @return operation status
1948 * @retval -2 DESTROY_ME flag is set
1949 * @retval -1 general failure; some data filled in
1950 * @retval -3 couldn't create vtrans; some data filled in
1953 GetVolInfo(afs_uint32 partId,
1954 afs_uint32 volumeId,
1957 volint_info_handle_t * handle,
1958 vol_info_list_mode_t mode)
1962 struct volser_trans *ttc = NULL;
1963 struct Volume fs_tv, *tv = NULL;
1965 ttc = NewTrans(volumeId, partId);
1968 VOLINT_INFO_STORE(handle, status, VBUSY);
1969 VOLINT_INFO_STORE(handle, volid, volumeId);
1973 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
1975 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
1976 volumeId, pname, volname, error);
1981 * please note that destroyMe and needsSalvaged checks used to be ordered
1982 * in the opposite manner for ListVolumes and XListVolumes. I think it's
1983 * more correct to check destroyMe before needsSalvaged.
1984 * -- tkeiser 11/28/2007
1987 if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
1989 case VOL_INFO_LIST_MULTIPLE:
1993 case VOL_INFO_LIST_SINGLE:
1994 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
1995 volumeId, pname, volname);
2002 if (tv->header->diskstuff.needsSalvaged) {
2003 /*this volume will be salvaged */
2004 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2005 volumeId, pname, volname);
2009 #ifdef AFS_DEMAND_ATTACH_FS
2010 if (GetVolObject(volumeId, &fs_tv)) {
2015 /* ok, we have all the data we need; fill in the on-wire struct */
2016 code = FillVolInfo(&fs_tv, &tv->header->diskstuff, handle);
2021 VOLINT_INFO_STORE(handle, status, 0);
2022 strcpy(VOLINT_INFO_PTR(handle, name), volname);
2023 VOLINT_INFO_STORE(handle, volid, volumeId);
2026 VDetachVolume(&error, tv);
2029 VOLINT_INFO_STORE(handle, status, 0);
2030 strcpy(VOLINT_INFO_PTR(handle, name), volname);
2031 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2032 volumeId, pname, volname);
2036 DeleteTrans(ttc, 1);
2043 /*return the header information about the <volid> */
2045 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2046 volumeId, volEntries *volumeInfo)
2050 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2051 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
2056 VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
2057 volumeId, volEntries *volumeInfo)
2060 struct DiskPartition *partP;
2061 char pname[9], volname[20];
2062 afs_int32 error = 0;
2068 volint_info_handle_t handle;
2070 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2071 pntr = volumeInfo->volEntries_val;
2072 volumeInfo->volEntries_len = 1;
2073 if (GetPartName(partid, pname))
2074 return VOLSERILLEGAL_PARTITION;
2075 if (!(partP = VGetPartition(pname, 0)))
2076 return VOLSERILLEGAL_PARTITION;
2077 dirp = opendir(VPartitionPath(partP));
2079 return VOLSERILLEGAL_PARTITION;
2081 strcpy(volname, "");
2083 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2085 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2086 GetNextVol(dirp, volname, &volid);
2087 continue; /*back to while loop */
2090 if (volid == volumeId) { /*copy other things too */
2095 GetNextVol(dirp, volname, &volid);
2099 #ifndef AFS_PTHREAD_ENV
2100 IOMGR_Poll(); /*make sure that the client does not time out */
2103 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2104 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2106 code = GetVolInfo(partid,
2111 VOL_INFO_LIST_SINGLE);
2115 return (found) ? 0 : ENODEV;
2118 /*------------------------------------------------------------------------
2119 * EXPORTED SAFSVolXListOneVolume
2122 * Returns extended info on volume a_volID on partition a_partID.
2125 * a_rxCidP : Pointer to the Rx call we're performing.
2126 * a_partID : Partition for which we want the extended list.
2127 * a_volID : Volume ID we wish to know about.
2128 * a_volumeXInfoP : Ptr to the extended info blob.
2131 * 0 Successful operation
2132 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2135 * Nothing interesting.
2139 *------------------------------------------------------------------------*/
2142 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2143 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2147 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2148 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
2153 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2154 afs_int32 a_volID, volXEntries *a_volumeXInfoP)
2155 { /*SAFSVolXListOneVolume */
2157 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2158 struct DiskPartition *partP; /*Ptr to partition */
2159 char pname[9], volname[20]; /*Partition, volume names */
2160 afs_int32 error; /*Error code */
2161 DIR *dirp; /*Partition directory ptr */
2162 afs_int32 currVolID; /*Current volume ID */
2163 int found = 0; /*Did we find the volume we need? */
2166 volint_info_handle_t handle;
2169 * Set up our pointers for action, marking our structure to hold exactly
2170 * one entry. Also, assume we'll fail in our quest.
2172 a_volumeXInfoP->volXEntries_val =
2173 (volintXInfo *) malloc(sizeof(volintXInfo));
2174 xInfoP = a_volumeXInfoP->volXEntries_val;
2175 a_volumeXInfoP->volXEntries_len = 1;
2179 * If the partition name we've been given is bad, bogue out.
2181 if (GetPartName(a_partID, pname))
2182 return (VOLSERILLEGAL_PARTITION);
2185 * Open the directory representing the given AFS parttion. If we can't
2188 if (!(partP = VGetPartition(pname, 0)))
2189 return VOLSERILLEGAL_PARTITION;
2190 dirp = opendir(VPartitionPath(partP));
2192 return (VOLSERILLEGAL_PARTITION);
2194 strcpy(volname, "");
2197 * Sweep through the partition directory, looking for the desired entry.
2198 * First, of course, figure out how many stat bytes to copy out of each
2201 while (strcmp(volname, "EOD") && !found) {
2203 * If this is not a volume, move on to the next entry in the
2204 * partition's directory.
2206 if (!strcmp(volname, "")) {
2207 GetNextVol(dirp, volname, &currVolID);
2211 if (currVolID == a_volID) {
2213 * We found the volume entry we're interested. Pull out the
2214 * extended information, remembering to poll (so that the client
2215 * doesn't time out) and to set up a transaction on the volume.
2219 } /*Found desired volume */
2221 GetNextVol(dirp, volname, &currVolID);
2225 #ifndef AFS_PTHREAD_ENV
2229 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2230 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2232 code = GetVolInfo(a_partID,
2237 VOL_INFO_LIST_SINGLE);
2242 * Clean up before going to dinner: close the partition directory,
2243 * return the proper value.
2246 return (found) ? 0 : ENODEV;
2247 } /*SAFSVolXListOneVolume */
2249 /*returns all the volumes on partition partid. If flags = 1 then all the
2250 * relevant info about the volumes is also returned */
2252 SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2253 volEntries *volumeInfo)
2257 code = VolListVolumes(acid, partid, flags, volumeInfo);
2258 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2263 VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2264 volEntries *volumeInfo)
2267 struct DiskPartition *partP;
2268 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2269 char pname[9], volname[20];
2270 afs_int32 error = 0;
2275 volint_info_handle_t handle;
2277 volumeInfo->volEntries_val =
2278 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2279 pntr = volumeInfo->volEntries_val;
2280 volumeInfo->volEntries_len = 0;
2281 if (GetPartName(partid, pname))
2282 return VOLSERILLEGAL_PARTITION;
2283 if (!(partP = VGetPartition(pname, 0)))
2284 return VOLSERILLEGAL_PARTITION;
2285 dirp = opendir(VPartitionPath(partP));
2287 return VOLSERILLEGAL_PARTITION;
2288 strcpy(volname, "");
2290 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2292 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2293 GetNextVol(dirp, volname, &volid);
2294 continue; /*back to while loop */
2297 if (flags) { /*copy other things too */
2298 #ifndef AFS_PTHREAD_ENV
2299 IOMGR_Poll(); /*make sure that the client does not time out */
2302 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2303 handle.volinfo_ptr.base = pntr;
2306 code = GetVolInfo(partid,
2311 VOL_INFO_LIST_MULTIPLE);
2312 if (code == -2) { /* DESTROY_ME flag set */
2316 pntr->volid = volid;
2317 /*just volids are needed */
2322 volumeInfo->volEntries_len += 1;
2323 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2324 /*running out of space, allocate more space */
2325 allocSize = (allocSize * 3) / 2;
2327 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2328 allocSize * sizeof(volintInfo));
2331 return VOLSERNO_MEMORY;
2333 volumeInfo->volEntries_val = pntr; /* point to new block */
2334 /* set pntr to the right position */
2335 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2340 GetNextVol(dirp, volname, &volid);
2348 /*------------------------------------------------------------------------
2349 * EXPORTED SAFSVolXListVolumes
2352 * Returns all the volumes on partition a_partID. If a_flags
2353 * is set to 1, then all the relevant extended volume information
2357 * a_rxCidP : Pointer to the Rx call we're performing.
2358 * a_partID : Partition for which we want the extended list.
2359 * a_flags : Various flags.
2360 * a_volumeXInfoP : Ptr to the extended info blob.
2363 * 0 Successful operation
2364 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2365 * VOLSERNO_MEMORY if we ran out of memory allocating
2369 * Nothing interesting.
2373 *------------------------------------------------------------------------*/
2376 SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2377 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2381 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2382 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2387 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2388 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2389 { /*SAFSVolXListVolumes */
2391 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2392 struct DiskPartition *partP; /*Ptr to partition */
2393 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2394 char pname[9], volname[20]; /*Partition, volume names */
2395 afs_int32 error = 0; /*Return code */
2396 DIR *dirp; /*Partition directory ptr */
2397 afs_int32 volid; /*Current volume ID */
2400 volint_info_handle_t handle;
2403 * Allocate a large array of extended volume info structures, then
2404 * set it up for action.
2406 a_volumeXInfoP->volXEntries_val =
2407 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2408 xInfoP = a_volumeXInfoP->volXEntries_val;
2409 a_volumeXInfoP->volXEntries_len = 0;
2412 * If the partition name we've been given is bad, bogue out.
2414 if (GetPartName(a_partID, pname))
2415 return (VOLSERILLEGAL_PARTITION);
2418 * Open the directory representing the given AFS parttion. If we can't
2421 if (!(partP = VGetPartition(pname, 0)))
2422 return VOLSERILLEGAL_PARTITION;
2423 dirp = opendir(VPartitionPath(partP));
2425 return (VOLSERILLEGAL_PARTITION);
2426 strcpy(volname, "");
2429 * Sweep through the partition directory, acting on each entry. First,
2430 * of course, figure out how many stat bytes to copy out of each volume.
2432 while (strcmp(volname, "EOD")) {
2435 * If this is not a volume, move on to the next entry in the
2436 * partition's directory.
2438 if (!strcmp(volname, "")) {
2439 GetNextVol(dirp, volname, &volid);
2445 * Full info about the volume desired. Poll to make sure the
2446 * client doesn't time out, then start up a new transaction.
2448 #ifndef AFS_PTHREAD_ENV
2452 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2453 handle.volinfo_ptr.ext = xInfoP;
2455 code = GetVolInfo(a_partID,
2460 VOL_INFO_LIST_MULTIPLE);
2461 if (code == -2) { /* DESTROY_ME flag set */
2466 * Just volume IDs are needed.
2468 xInfoP->volid = volid;
2473 * Bump the pointer in the data area we're building, along with
2474 * the count of the number of entries it contains.
2477 (a_volumeXInfoP->volXEntries_len)++;
2478 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2480 * We're running out of space in the area we've built. Grow it.
2482 allocSize = (allocSize * 3) / 2;
2483 xInfoP = (volintXInfo *)
2484 realloc((char *)a_volumeXInfoP->volXEntries_val,
2485 (allocSize * sizeof(volintXInfo)));
2486 if (xInfoP == NULL) {
2488 * Bummer, no memory. Bag it, tell our caller what went wrong.
2491 return (VOLSERNO_MEMORY);
2495 * Memory reallocation worked. Correct our pointers so they
2496 * now point to the new block and the current open position within
2499 a_volumeXInfoP->volXEntries_val = xInfoP;
2501 a_volumeXInfoP->volXEntries_val +
2502 a_volumeXInfoP->volXEntries_len;
2506 GetNextVol(dirp, volname, &volid);
2507 } /*Sweep through the partition directory */
2510 * We've examined all entries in the partition directory. Close it,
2511 * delete our transaction (if any), and go home happy.
2516 } /*SAFSVolXListVolumes */
2518 /*this call is used to monitor the status of volser for debugging purposes.
2519 *information about all the active transactions is returned in transInfo*/
2521 SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2525 code = VolMonitor(acid, transInfo);
2526 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2531 VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2533 transDebugInfo *pntr;
2534 afs_int32 allocSize = 50;
2535 struct volser_trans *tt, *allTrans;
2537 transInfo->transDebugEntries_val =
2538 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2539 pntr = transInfo->transDebugEntries_val;
2540 transInfo->transDebugEntries_len = 0;
2541 allTrans = TransList();
2542 if (allTrans == (struct volser_trans *)0)
2543 return 0; /*no active transactions */
2544 for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
2545 pntr->tid = tt->tid;
2546 pntr->time = tt->time;
2547 pntr->creationTime = tt->creationTime;
2548 pntr->returnCode = tt->returnCode;
2549 pntr->volid = tt->volid;
2550 pntr->partition = tt->partition;
2551 pntr->iflags = tt->iflags;
2552 pntr->vflags = tt->vflags;
2553 pntr->tflags = tt->tflags;
2554 strcpy(pntr->lastProcName, tt->lastProcName);
2555 pntr->callValid = 0;
2556 if (tt->rxCallPtr) { /*record call related info */
2557 pntr->callValid = 1;
2558 pntr->readNext = tt->rxCallPtr->rnext;
2559 pntr->transmitNext = tt->rxCallPtr->tnext;
2560 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2561 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2564 transInfo->transDebugEntries_len += 1;
2565 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2566 allocSize = (allocSize * 3) / 2;
2568 (transDebugInfo *) realloc((char *)transInfo->
2569 transDebugEntries_val,
2571 sizeof(transDebugInfo));
2572 transInfo->transDebugEntries_val = pntr;
2574 transInfo->transDebugEntries_val +
2575 transInfo->transDebugEntries_len;
2576 /*set pntr to right position */
2585 SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2589 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2590 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
2591 AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
2597 VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
2600 afs_int32 error = 0;
2601 register struct volser_trans *tt;
2602 char caller[MAXKTCNAMELEN];
2604 if (strlen(name) > 31)
2605 return VOLSERBADNAME;
2606 if (!afsconf_SuperUser(tdir, acid, caller))
2607 return VOLSERBAD_ACCESS; /*not a super user */
2608 /* find the trans */
2609 tt = FindTrans(atid);
2612 if (tt->vflags & VTDeleted) {
2613 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2617 strcpy(tt->lastProcName, "SetIdsTypes");
2618 tt->rxCallPtr = acid;
2622 V_backupId(tv) = backupId;
2623 V_cloneId(tv) = cloneId;
2624 V_parentId(tv) = pId;
2625 strcpy((&V_disk(tv))->name, name);
2626 VUpdateVolume(&error, tv);
2628 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2632 tt->rxCallPtr = (struct rx_call *)0;
2633 if (TRELE(tt) && !error)
2634 return VOLSERTRELE_ERROR;
2638 tt->rxCallPtr = (struct rx_call *)0;
2639 if (TRELE(tt) && !error)
2640 return VOLSERTRELE_ERROR;
2645 SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2649 code = VolSetDate(acid, atid, cdate);
2650 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
2656 VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2659 afs_int32 error = 0;
2660 register struct volser_trans *tt;
2661 char caller[MAXKTCNAMELEN];
2663 if (!afsconf_SuperUser(tdir, acid, caller))
2664 return VOLSERBAD_ACCESS; /*not a super user */
2665 /* find the trans */
2666 tt = FindTrans(atid);
2669 if (tt->vflags & VTDeleted) {
2670 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2674 strcpy(tt->lastProcName, "SetDate");
2675 tt->rxCallPtr = acid;
2678 V_creationDate(tv) = cdate;
2679 VUpdateVolume(&error, tv);
2681 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2685 tt->rxCallPtr = (struct rx_call *)0;
2686 if (TRELE(tt) && !error)
2687 return VOLSERTRELE_ERROR;
2691 tt->rxCallPtr = (struct rx_call *)0;
2692 if (TRELE(tt) && !error)
2693 return VOLSERTRELE_ERROR;
2698 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2704 char caller[MAXKTCNAMELEN];
2706 register struct volser_trans *ttc;
2707 char pname[16], volname[20];
2708 struct DiskPartition *partP;
2709 afs_int32 ret = ENODEV;
2712 if (!afsconf_SuperUser(tdir, acid, caller))
2713 return VOLSERBAD_ACCESS; /*not a super user */
2714 if (GetPartName(partId, pname))
2715 return VOLSERILLEGAL_PARTITION;
2716 if (!(partP = VGetPartition(pname, 0)))
2717 return VOLSERILLEGAL_PARTITION;
2718 dirp = opendir(VPartitionPath(partP));
2720 return VOLSERILLEGAL_PARTITION;
2721 strcpy(volname, "");
2722 ttc = (struct volser_trans *)0;
2724 while (strcmp(volname, "EOD")) {
2725 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2726 GetNextVol(dirp, volname, &volid);
2727 continue; /*back to while loop */
2730 if (volid == volumeId) { /*copy other things too */
2731 #ifndef AFS_PTHREAD_ENV
2732 IOMGR_Poll(); /*make sure that the client doesnot time out */
2734 ttc = NewTrans(volumeId, partId);
2738 #ifdef AFS_NAMEI_ENV
2739 ret = namei_ConvertROtoRWvolume(pname, volumeId);
2741 ret = inode_ConvertROtoRWvolume(pname, volumeId);
2745 GetNextVol(dirp, volname, &volid);
2749 DeleteTrans(ttc, 1);
2750 ttc = (struct volser_trans *)0;
2759 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
2760 register struct volintSize *size)
2763 register struct volser_trans *tt;
2764 char caller[MAXKTCNAMELEN];
2766 if (!afsconf_SuperUser(tdir, acid, caller))
2767 return VOLSERBAD_ACCESS; /*not a super user */
2768 tt = FindTrans(fromTrans);
2771 if (tt->vflags & VTDeleted) {
2775 strcpy(tt->lastProcName, "GetSize");
2776 tt->rxCallPtr = acid;
2777 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2778 tt->rxCallPtr = (struct rx_call *)0;
2780 return VOLSERTRELE_ERROR;
2782 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2786 /* GetPartName - map partid (a decimal number) into pname (a string)
2787 * Since for NT we actually want to return the drive name, we map through the
2791 GetPartName(afs_int32 partid, char *pname)
2796 strcpy(pname, "/vicep");
2797 pname[6] = 'a' + partid;
2800 } else if (partid < VOLMAXPARTS) {
2801 strcpy(pname, "/vicep");
2803 pname[6] = 'a' + (partid / 26);
2804 pname[7] = 'a' + (partid % 26);