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
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
23 #include <netinet/in.h>
40 #include <afs/afsint.h>
42 #include <afs/assert.h>
43 #include <afs/prs_fs.h>
48 #include <afs/cellconfig.h>
51 #include <afs/ihandle.h>
53 #include <afs/ntops.h>
55 #include <afs/vnode.h>
56 #include <afs/volume.h>
57 #include <afs/partition.h>
59 #include <afs/fssync.h>
61 #include "afs/audit.h"
66 #include <volser_prototypes.h>
69 extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
70 extern struct afsconf_dir *tdir;
71 extern char *volutil_PartitionName();
73 /* Forward declarations */
74 static int GetPartName(afs_int32 partid, char *pname);
76 #define OneDay (24*60*60)
83 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
84 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
85 afs_int32 VolForwardMultiple();
86 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
87 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
88 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
90 /* this call unlocks all of the partition locks we've set */
92 register struct DiskPartition *tp;
93 for(tp = DiskPartitionList; tp; tp = tp->next) {
94 if (tp->lock_fd != -1) {
95 close(tp->lock_fd); /* releases flock held on this partition */
102 /* get partition id from a name */
103 afs_int32 PartitionID(aname)
106 register int code = 0;
110 if (tc == 0) return -1; /* unknown */
112 /* otherwise check for vicepa or /vicepa, or just plain "a" */
114 if (!strncmp(aname, "/vicep", 6)) {
115 strncpy(ascii, aname+6, 2);
117 else return -1; /* bad partition name */
118 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
119 from 0. Do the appropriate conversion */
121 /* one char name, 0..25 */
122 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
123 return ascii[0] - 'a';
126 /* two char name, 26 .. <whatever> */
127 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
128 if (ascii[1] < 'a' || ascii[1] > 'z') return -1; /* just as bad */
129 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
130 if (code > VOLMAXPARTS) return -1;
135 static int ConvertVolume(avol, aname, asize)
139 if (asize < 18) return -1;
140 /* 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 */
141 sprintf(aname, VFORMAT, avol);
145 static int ConvertPartition(apartno, aname, asize)
149 if (asize < 10) return E2BIG;
150 if (apartno < 0) return EINVAL;
151 strcpy(aname, "/vicep");
153 aname[6] = 'a'+apartno;
158 aname[6] = 'a' + (apartno / 26);
159 aname[7] = 'a' + (apartno % 26);
165 /* the only attach function that takes a partition is "...ByName", so we use it */
166 struct Volume *XAttachVolume(error, avolid, apartid, amode)
171 char pbuf[30], vbuf[20];
172 register struct Volume *tv;
174 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
178 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
182 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
186 /* Adapted from the file server; create a root directory for this volume */
187 static ViceCreateRoot(vp)
191 struct acl_accessList * ACL;
193 Inode inodeNumber, nearInode;
194 char buf[SIZEOF_LARGEDISKVNODE];
195 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
196 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
202 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
204 V_pref(vp, nearInode);
205 inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
206 VPartitionPath(V_partition(vp)), nearInode,
207 V_parentId(vp), 1, 1, 0);
208 assert(VALID_INO(inodeNumber));
210 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
211 did.Volume = V_id(vp);
212 did.Vnode = (VnodeId)1;
215 assert(!(MakeDir(&dir, &did, &did)));
216 DFlush(); /* flush all modified dir buffers out */
217 DZap(&dir); /* Remove all buffers for this dir */
218 length = Length(&dir); /* Remember size of this directory */
220 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
222 /* build a single entry ACL that gives all rights to system:administrators */
223 /* this section of code assumes that access list format is not going to
226 ACL = VVnodeDiskACL(vnode);
227 ACL->size = sizeof(struct acl_accessList);
228 ACL->version = ACL_ACLVERSION;
232 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
233 ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
235 vnode->type = vDirectory;
237 vnode->modeBits = 0777;
238 vnode->linkCount = 2;
239 VNDISK_SET_LEN(vnode, length);
240 vnode->uniquifier = 1;
241 V_uniquifier(vp) = vnode->uniquifier+1;
242 vnode->dataVersion = 1;
243 VNDISK_SET_INO(vnode, inodeNumber);
244 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
248 vnode->vnodeMagic = vcp->magic;
250 IH_INIT(h, vp->device, V_parentId(vp),
251 vp->vnodeIndex[vLarge].handle->ih_ino);
254 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
256 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
257 assert(code == SIZEOF_LARGEDISKVNODE);
258 FDH_REALLYCLOSE(fdP);
260 VNDISK_GET_LEN(length, vnode);
261 V_diskused(vp) = nBlocks(length);
266 afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
267 struct rx_call *acid;
269 struct diskPartition *partition;
273 code = VolPartitionInfo (acid,pname,partition);
274 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
278 afs_int32 VolPartitionInfo (acid,pname,partition)
279 struct rx_call *acid;
281 struct diskPartition *partition;
283 register struct DiskPartition *dp;
286 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
289 dp = VGetPartition(pname, 0);
291 strncpy(partition->name,dp->name,32);
292 strncpy(partition->devName,dp->devName,32);
293 partition->lock_fd = dp->lock_fd ;
294 partition->free = dp->free;
295 partition->minFree = dp->totalUsable;
299 return VOLSERILLEGAL_PARTITION;
302 /* obliterate a volume completely, and slowly. */
303 afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
304 struct rx_call *acid;
305 afs_int32 apartID, avolID;
309 code = VolNukeVolume (acid, apartID, avolID);
310 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
314 afs_int32 VolNukeVolume (acid, apartID, avolID)
315 struct rx_call *acid;
316 afs_int32 apartID, avolID;
321 register afs_int32 code;
323 char caller[MAXKTCNAMELEN];
325 /* check for access */
326 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
327 if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
329 tp = volutil_PartitionName(apartID);
330 if (!tp) return VOLSERNOVOL;
331 strcpy(partName, tp); /* remember it for later */
332 /* we first try to attach the volume in update mode, so that the file
333 * server doesn't try to use it (and abort) while (or after) we delete it.
334 * If we don't get the volume, that's fine, too. We just won't put it back.
336 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
337 code = nuke(partName, avolID);
338 if (tvp) VDetachVolume(&error, tvp);
342 /* create a new volume, with name aname, on the specified partition (1..n)
343 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
344 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
345 * for the volume id (useful for things like volume restore).
346 * Return the new volume id in *avolid.
348 afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
349 struct rx_call *acid;
359 code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
360 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans,
369 afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
370 struct rx_call *acid;
380 afs_int32 junk; /* discardable error code */
381 register afs_int32 volumeID, doCreateRoot=1;
382 register struct volser_trans *tt;
384 char caller[MAXKTCNAMELEN];
386 if (strlen(aname) > 31) return VOLSERBADNAME;
387 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
388 if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
389 if (error = ConvertPartition(apart, ppath, sizeof(ppath))) return error;/*a standard unix error*/
390 if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
392 if ((volumeID = *avolid) == 0) {
394 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
398 if ((aparent == volumeID) && (atype == readwriteVolume)) {
401 if (aparent == 0) aparent = volumeID;
402 tt = NewTrans(volumeID, apart);
404 Log("1 createvolume: failed to create trans\n");
405 return VOLSERVOLBUSY; /* volume already busy! */
407 vp = VCreateVolume(&error, ppath, volumeID, aparent);
409 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
414 V_uniquifier(vp) = 1;
415 V_creationDate(vp) = V_copyDate(vp);
416 V_inService(vp) = V_blessed(vp) = 1;
418 AssignVolumeName(&V_disk(vp), aname, 0);
421 V_destroyMe(vp) = DESTROY_ME;
423 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
424 VUpdateVolume(&error, vp);
426 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
429 VDetachVolume(&junk, vp); /* rather return the real error code */
434 strcpy(tt->lastProcName,"CreateVolume");
435 tt->rxCallPtr = acid;
436 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
437 tt->rxCallPtr = (struct rx_call *)0;
438 if(TRELE(tt)) return VOLSERTRELE_ERROR;
442 /* delete the volume associated with this transaction */
443 afs_int32 SAFSVolDeleteVolume (acid, atrans)
445 struct rx_call *acid;
449 code = VolDeleteVolume (acid, atrans);
450 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
454 afs_int32 VolDeleteVolume (acid, atrans)
456 struct rx_call *acid;
458 register struct volser_trans *tt;
460 char caller[MAXKTCNAMELEN];
462 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
463 tt = FindTrans(atrans);
464 if (!tt) return ENOENT;
465 if (tt->vflags & VTDeleted) {
466 Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
470 if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
471 strcpy(tt->lastProcName,"DeleteVolume");
472 tt->rxCallPtr = acid;
473 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
474 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
475 tt->rxCallPtr = (struct rx_call *)0;
476 if(TRELE(tt)) return VOLSERTRELE_ERROR;
478 Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
479 return 0; /* vpurgevolume doesn't set an error code */
482 /* make a clone of the volume associated with atrans, possibly giving it a new
483 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
484 * for the clone's id). The new clone is given the name newName. Finally, due to
485 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
486 * the clone operation. This may be useful when making new backup volumes, for instance
487 * since the net result of a clone and a purge generally leaves many inode ref counts
488 * the same, while doing them separately would result in far more iincs and idecs being
489 * peformed (and they are slow operations).
491 afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
492 struct rx_call *acid;
495 afs_int32 *newNumber;
496 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
501 code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
502 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans,
506 AUD_LONG, *newNumber, AUD_END);
510 afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
511 struct rx_call *acid;
514 afs_int32 *newNumber;
515 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
519 register struct Volume *originalvp, *purgevp, *newvp;
521 register struct volser_trans *tt,*ttc;
522 char caller[MAXKTCNAMELEN];
524 if (strlen(newName)>31) return VOLSERBADNAME;
525 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
526 if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
528 originalvp = (Volume *) 0;
529 purgevp = (Volume *) 0;
530 newvp = (Volume *) 0;
531 tt = ttc = (struct volser_trans *) 0;
533 if (!newNumber || !*newNumber)
535 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
540 if (newType != readonlyVolume && newType != backupVolume)
542 tt = FindTrans(atrans);
543 if (!tt) return ENOENT;
544 if (tt->vflags & VTDeleted) {
545 Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
549 ttc = NewTrans(newId,tt->partition);
551 { /* someone is messing with the clone already */
555 strcpy(tt->lastProcName,"Clone");
556 tt->rxCallPtr = acid;
560 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
562 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
569 originalvp = tt->volume;
570 if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
571 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
575 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
576 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
582 if (originalvp->device != purgevp->device) {
583 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
587 if (V_type(purgevp) != readonlyVolume) {
588 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
592 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
593 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
597 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
598 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
607 newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
609 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
610 newvp = (Volume *) 0;
613 if (newType == readonlyVolume)
614 V_cloneId(originalvp) = newId;
615 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
617 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
618 CloneVolume(&error, originalvp, newvp, purgevp);
619 purgevp = NULL; /* clone releases it, maybe even if error */
621 Log("1 Volser: Clone: clone operation failed with code %d\n", error);
625 if (newType == readonlyVolume) {
626 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
627 V_type(newvp) = readonlyVolume;
629 else if (newType == backupVolume) {
630 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
631 V_type(newvp) = backupVolume;
632 V_backupId(originalvp) = newId;
634 strcpy(newvp->header->diskstuff.name,newName);
635 V_creationDate(newvp) = V_copyDate(newvp);
636 ClearVolumeStats(&V_disk(newvp));
637 V_destroyMe(newvp) = DESTROY_ME;
638 V_inService(newvp) = 0;
639 if (newType == backupVolume) {
640 V_backupDate(originalvp) = V_copyDate(newvp);
641 V_backupDate(newvp) = V_copyDate(newvp);
644 VUpdateVolume(&error, newvp);
646 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
650 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
652 VUpdateVolume(&error, originalvp);
654 Log("1 Volser: Clone: original update %d\n", error);
658 tt->rxCallPtr = (struct rx_call *)0;
660 tt = (struct volser_trans *) 0;
661 error = VOLSERTRELE_ERROR;
668 if (purgevp) VDetachVolume(&code, purgevp);
669 if (newvp) VDetachVolume(&code, newvp);
671 tt->rxCallPtr = (struct rx_call *)0;
674 if(ttc) DeleteTrans(ttc);
678 /* reclone this volume into the specified id */
679 afs_int32 SAFSVolReClone (acid, atrans, cloneId)
680 struct rx_call *acid;
686 code = VolReClone (acid, atrans, cloneId);
687 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
691 afs_int32 VolReClone (acid, atrans, cloneId)
692 struct rx_call *acid;
696 register struct Volume *originalvp, *clonevp;
699 register struct volser_trans *tt,*ttc;
700 char caller[MAXKTCNAMELEN];
703 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
704 if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
706 clonevp = originalvp = (Volume *) 0;
707 tt = (struct volser_trans *) 0;
709 tt = FindTrans(atrans);
710 if (!tt) return ENOENT;
711 if (tt->vflags & VTDeleted) {
712 Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
716 ttc = NewTrans(cloneId, tt->partition);
717 if (!ttc){ /* someone is messing with the clone already */
721 strcpy(tt->lastProcName,"ReClone");
722 tt->rxCallPtr = acid;
724 originalvp = tt->volume;
725 if ((V_type(originalvp) == backupVolume) ||
726 (V_type(originalvp) == readonlyVolume)){
727 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
731 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
732 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
738 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
740 Log("1 Volser: can't attach clone %d\n", cloneId);
744 newType = V_type(clonevp); /* type of the new volume */
746 if (originalvp->device != clonevp->device) {
747 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
751 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
752 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
756 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
757 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
761 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
762 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
769 Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
771 CloneVolume(&error, originalvp, clonevp, clonevp);
773 Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
778 /* fix up volume name and type, CloneVolume just propagated RW's */
779 if (newType == readonlyVolume) {
780 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
781 V_type(clonevp) = readonlyVolume;
783 else if (newType == backupVolume) {
784 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
785 V_type(clonevp) = backupVolume;
786 V_backupId(originalvp) = cloneId;
788 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
790 /* pretend recloned volume is a totally new instance */
791 V_copyDate(clonevp) = time(0);
792 V_creationDate(clonevp) = V_copyDate(clonevp);
793 ClearVolumeStats(&V_disk(clonevp));
794 V_destroyMe(clonevp) = 0;
795 V_inService(clonevp) = 0;
796 if (newType == backupVolume) {
797 V_backupDate(originalvp) = V_copyDate(clonevp);
798 V_backupDate(clonevp) = V_copyDate(clonevp);
800 V_inUse(clonevp) = 0;
801 VUpdateVolume(&error, clonevp);
803 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
807 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
809 VUpdateVolume(&error, originalvp);
811 Log("1 Volser: Clone: original update %d\n", error);
815 tt->rxCallPtr = (struct rx_call *)0;
817 tt = (struct volser_trans *) 0;
818 error = VOLSERTRELE_ERROR;
825 struct DiskPartition *tpartp = originalvp->partition;
826 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
831 if (clonevp) VDetachVolume(&code, clonevp);
833 tt->rxCallPtr = (struct rx_call *)0;
836 if(ttc) DeleteTrans(ttc);
840 /* create a new transaction, associated with volume and partition. Type of
841 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
842 * See volser.h for definition of iflags (the constants are named IT*).
844 afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
845 struct rx_call *acid;
853 code = VolTransCreate (acid, volume, partition, iflags, ttid);
854 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
858 afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
859 struct rx_call *acid;
865 register struct volser_trans *tt;
867 afs_int32 error, code;
869 char caller[MAXKTCNAMELEN];
871 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
872 if (iflags & ITCreate) mode = V_SECRETLY;
873 else if (iflags & ITBusy) mode = V_CLONE;
874 else if (iflags & ITReadOnly) mode = V_READONLY;
875 else if (iflags & ITOffline) mode = V_VOLUPD;
877 Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
881 tt = NewTrans(volume, partition);
883 /* can't create a transaction? put the volume back */
884 Log("1 transcreate: can't create transaction\n");
885 return VOLSERVOLBUSY;
887 tv = XAttachVolume(&error, volume, partition, mode);
890 if (tv) VDetachVolume(&code, tv);
898 strcpy(tt->lastProcName,"TransCreate");
899 if(TRELE(tt)) return VOLSERTRELE_ERROR;
904 /* using aindex as a 0-based index, return the aindex'th volume on this server
905 * Both the volume number and partition number (one-based) are returned.
907 afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
908 struct rx_call *acid;
915 code = VolGetNthVolume (acid, aindex, avolume, apart);
916 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
920 afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
921 struct rx_call *acid;
926 Log("1 Volser: GetNthVolume: Not yet implemented\n");
930 /* return the volume flags (VT* constants in volser.h) associated with this
933 afs_int32 SAFSVolGetFlags (acid, atid, aflags)
934 struct rx_call *acid;
940 code = VolGetFlags (acid, atid, aflags);
941 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
945 afs_int32 VolGetFlags (acid, atid, aflags)
946 struct rx_call *acid;
950 register struct volser_trans *tt;
952 tt = FindTrans(atid);
953 if (!tt) return ENOENT;
954 if (tt->vflags & VTDeleted) {
955 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
959 strcpy(tt->lastProcName,"GetFlags");
960 tt->rxCallPtr = acid;
961 *aflags = tt->vflags;
962 tt->rxCallPtr = (struct rx_call *)0;
963 if(TRELE(tt)) return VOLSERTRELE_ERROR;
968 /* Change the volume flags (VT* constants in volser.h) associated with this
969 * transaction. Effects take place immediately on volume, although volume
970 * remains attached as usual by the transaction.
972 afs_int32 SAFSVolSetFlags (acid, atid, aflags)
973 struct rx_call *acid;
979 code = VolSetFlags (acid, atid, aflags);
980 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
984 afs_int32 VolSetFlags (acid, atid, aflags)
985 struct rx_call *acid;
989 register struct volser_trans *tt;
990 register struct Volume *vp;
992 char caller[MAXKTCNAMELEN];
994 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
996 tt = FindTrans(atid);
997 if (!tt) return ENOENT;
998 if (tt->vflags & VTDeleted) {
999 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
1003 strcpy(tt->lastProcName,"SetFlags");
1004 tt->rxCallPtr = acid;
1005 vp = tt->volume; /* pull volume out of transaction */
1007 /* check if we're allowed to make any updates */
1008 if (tt->iflags & ITReadOnly) {
1013 /* handle delete-on-salvage flag */
1014 if (aflags & VTDeleteOnSalvage) {
1015 V_destroyMe(tt->volume) = DESTROY_ME;
1018 V_destroyMe(tt->volume) = 0;
1021 if (aflags & VTOutOfService) {
1022 V_inService(vp) = 0;
1025 V_inService(vp) = 1;
1027 VUpdateVolume(&error, vp);
1028 tt->vflags = aflags;
1029 tt->rxCallPtr = (struct rx_call *)0;
1030 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
1035 /* dumpS the volume associated with a particular transaction from a particular
1036 * date. Send the dump to a different transaction (destTrans) on the server
1037 * specified by the destServer structure.
1039 afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1040 struct rx_call *acid;
1041 afs_int32 fromTrans;
1043 struct destServer *destination;
1044 struct restoreCookie *cookie;
1045 afs_int32 destTrans;
1049 code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
1050 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans,
1051 AUD_HOST, destination->destHost,
1052 AUD_LONG, destTrans, AUD_END);
1056 afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1057 struct rx_call *acid;
1058 afs_int32 fromTrans;
1060 struct destServer *destination;
1061 struct restoreCookie *cookie;
1062 afs_int32 destTrans;
1064 register struct volser_trans *tt;
1065 register afs_int32 code;
1066 register struct rx_connection *tcon;
1067 struct rx_call *tcall;
1068 register struct Volume *vp;
1069 struct rx_securityClass *securityObject;
1070 afs_int32 securityIndex;
1071 char caller[MAXKTCNAMELEN];
1073 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1074 /* initialize things */
1075 tcon = (struct rx_connection *) 0;
1076 tt = (struct volser_trans *) 0;
1078 /* find the local transaction */
1079 tt = FindTrans(fromTrans);
1080 if (!tt) return ENOENT;
1081 if (tt->vflags & VTDeleted) {
1082 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1087 strcpy(tt->lastProcName,"Forward");
1089 /* get auth info for the this connection (uses afs from ticket file) */
1090 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1096 /* make an rpc connection to the other server */
1097 tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
1099 tt->rxCallPtr = (struct rx_call *)0;
1103 tcall = rx_NewCall(tcon);
1104 tt->rxCallPtr = tcall;
1105 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1106 code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
1111 /* these next calls implictly call rx_Write when writing out data */
1112 code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
1113 if (code) goto fail;
1114 EndAFSVolRestore(tcall); /* probably doesn't do much */
1115 tt->rxCallPtr = (struct rx_call *)0;
1116 code = rx_EndCall(tcall, 0);
1117 rx_DestroyConnection(tcon); /* done with the connection */
1119 if (code) goto fail;
1120 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1126 rx_EndCall(tcall,0);
1127 rx_DestroyConnection(tcon);
1130 tt->rxCallPtr = (struct rx_call *)0;
1136 /* Start a dump and send it to multiple places simultaneously.
1137 * If this returns an error (eg, return ENOENT), it means that
1138 * none of the releases worked. If this returns 0, that means
1139 * that one or more of the releases worked, and the caller has
1140 * to examine the results array to see which one(s).
1141 * This will only do EITHER incremental or full, not both, so it's
1142 * the caller's responsibility to be sure that all the destinations
1143 * need just an incremental (and from the same time), if that's
1146 afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations,
1147 spare, cookie, results)
1148 struct rx_call *acid;
1149 afs_int32 fromTrans;
1152 manyDests *destinations;
1153 struct restoreCookie *cookie;
1154 manyResults *results;
1156 afs_int32 securityIndex;
1157 struct rx_securityClass *securityObject;
1158 char caller[MAXKTCNAMELEN];
1159 struct volser_trans *tt;
1160 afs_int32 ec, code, *codes;
1161 struct rx_connection **tcons;
1162 struct rx_call **tcalls;
1164 int i, nconns, is_incremental;
1167 memset(results, 0, sizeof(manyResults));
1169 if (!afsconf_SuperUser(tdir, acid, caller))
1170 return VOLSERBAD_ACCESS;/*not a super user*/
1171 tt = FindTrans(fromTrans);
1174 if (tt->vflags & VTDeleted) {
1175 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1180 strcpy(tt->lastProcName, "ForwardMulti");
1182 /* (fromDate == 0) ==> incremental dump */
1183 is_incremental = (fromDate ? 1 : 0);
1185 i= results->manyResults_len = destinations->manyDests_len;
1186 results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
1187 tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
1188 tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
1190 /* get auth info for this connection (uses afs from ticket file) */
1191 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1193 goto fail; /* in order to audit each failure */
1196 /* make connections to all the other servers */
1197 for (i=0; i < destinations->manyDests_len; i++) {
1198 struct replica *dest = &(destinations->manyDests_val[i]);
1199 tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
1200 htons(dest->server.destPort),
1201 VOLSERVICE_ID, securityObject, securityIndex);
1203 codes[i] = ENOTCONN;
1206 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1209 codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
1210 is_incremental,cookie);
1212 rx_EndCall (tcalls[i],0); tcalls[i] = 0;
1213 rx_DestroyConnection(tcons[i]); tcons[i] = 0;
1219 /* these next calls implictly call rx_Write when writing out data */
1220 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1224 for (i--; i >=0 ; i--) {
1225 struct replica *dest = &(destinations->manyDests_val[i]);
1227 if (!code && tcalls[i] && !codes[i]) {
1228 EndAFSVolRestore(tcalls[i]);
1231 ec = rx_EndCall(tcalls[i], 0);
1232 if (!codes[i]) codes[i] = ec;
1235 rx_DestroyConnection(tcons[i]); /* done with the connection */
1238 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]),
1239 AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost,
1240 AUD_LONG, dest->trans, AUD_END);
1246 tt->rxCallPtr = (struct rx_call *)0;
1247 if(TRELE(tt) && !code) /* return the first code if it's set */
1248 return VOLSERTRELE_ERROR;
1254 afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
1255 struct rx_call *acid;
1256 afs_int32 fromTrans;
1261 code = VolDump (acid, fromTrans, fromDate);
1262 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1266 afs_int32 VolDump (acid, fromTrans, fromDate)
1267 struct rx_call *acid;
1268 afs_int32 fromTrans;
1272 register struct volser_trans *tt;
1273 char caller[MAXKTCNAMELEN];
1275 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1276 tt = FindTrans(fromTrans);
1277 if (!tt) return ENOENT;
1278 if (tt->vflags & VTDeleted) {
1279 Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
1283 strcpy(tt->lastProcName,"Dump");
1284 tt->rxCallPtr = acid;
1285 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1286 if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
1287 tt->rxCallPtr = (struct rx_call *)0;
1289 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1295 * Ha! No more helper process!
1297 afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
1298 struct rx_call *acid;
1301 struct restoreCookie *cookie;
1305 code = VolRestore (acid, atrans, aflags,cookie);
1306 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1310 afs_int32 VolRestore (acid, atrans, aflags,cookie)
1311 struct rx_call *acid;
1314 struct restoreCookie *cookie;
1316 register struct volser_trans *tt;
1317 register afs_int32 code,tcode;
1318 char caller[MAXKTCNAMELEN];
1320 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1321 tt = FindTrans(atrans);
1322 if (!tt) return ENOENT;
1323 if (tt->vflags & VTDeleted) {
1324 Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
1328 strcpy(tt->lastProcName,"Restore");
1329 tt->rxCallPtr = acid;
1330 code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie); /* last is incrementalp */
1331 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
1333 tt->rxCallPtr = (struct rx_call *)0;
1336 return (code? code : tcode);
1339 /* end a transaction, returning the transaction's final error code in rcode */
1340 afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
1341 struct rx_call *acid;
1342 afs_int32 destTrans;
1347 code = VolEndTrans (acid, destTrans, rcode);
1348 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1352 afs_int32 VolEndTrans (acid, destTrans, rcode)
1353 struct rx_call *acid;
1354 afs_int32 destTrans;
1357 register struct volser_trans *tt;
1358 char caller[MAXKTCNAMELEN];
1360 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1361 tt = FindTrans(destTrans);
1362 if (!tt) {return ENOENT;}
1363 *rcode = tt->returnCode;
1364 DeleteTrans(tt); /* this does an implicit TRELE */
1369 afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
1370 struct rx_call *acid;
1376 code = VolSetForwarding (acid, atid, anewsite);
1377 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
1381 afs_int32 VolSetForwarding (acid, atid, anewsite)
1382 struct rx_call *acid;
1387 register struct volser_trans *tt;
1388 char caller[MAXKTCNAMELEN];
1390 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1391 tt = FindTrans(atid);
1392 if (!tt) return ENOENT;
1393 if (tt->vflags & VTDeleted) {
1394 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
1398 strcpy(tt->lastProcName,"SetForwarding");
1399 tt->rxCallPtr = acid;
1400 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1401 tt->rxCallPtr = (struct rx_call *)0;
1402 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1407 afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
1408 struct rx_call *acid;
1410 register struct volser_status *astatus;
1414 code = VolGetStatus (acid, atrans, astatus);
1415 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1419 afs_int32 VolGetStatus (acid, atrans, astatus)
1420 struct rx_call *acid;
1422 register struct volser_status *astatus;
1424 register struct Volume *tv;
1425 register struct VolumeDiskData *td;
1426 struct volser_trans *tt;
1429 tt = FindTrans(atrans);
1430 if (!tt) return ENOENT;
1431 if (tt->vflags & VTDeleted) {
1432 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
1436 strcpy(tt->lastProcName,"GetStatus");
1437 tt->rxCallPtr = acid;
1440 tt->rxCallPtr = (struct rx_call *)0;
1445 td = &tv->header->diskstuff;
1446 astatus->volID = td->id;
1447 astatus->nextUnique = td->uniquifier;
1448 astatus->type = td->type;
1449 astatus->parentID = td->parentId;
1450 astatus->cloneID = td->cloneId;
1451 astatus->backupID = td->backupId;
1452 astatus->restoredFromID = td->restoredFromId;
1453 astatus->maxQuota = td->maxquota;
1454 astatus->minQuota = td->minquota;
1455 astatus->owner = td->owner;
1456 astatus->creationDate = td->creationDate;
1457 astatus->accessDate = td->accessDate;
1458 astatus->updateDate = td->updateDate;
1459 astatus->expirationDate = td->expirationDate;
1460 astatus->backupDate = td->backupDate;
1461 astatus->copyDate = td->copyDate;
1462 tt->rxCallPtr = (struct rx_call *)0;
1463 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1468 afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
1469 struct rx_call *acid;
1471 register struct volintInfo *astatus;
1475 code = VolSetInfo (acid, atrans, astatus);
1476 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1480 afs_int32 VolSetInfo (acid, atrans, astatus)
1481 struct rx_call *acid;
1483 register struct volintInfo *astatus;
1485 register struct Volume *tv;
1486 register struct VolumeDiskData *td;
1487 struct volser_trans *tt;
1488 char caller[MAXKTCNAMELEN];
1491 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1492 tt = FindTrans(atrans);
1493 if (!tt) return ENOENT;
1494 if (tt->vflags & VTDeleted) {
1495 Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
1499 strcpy(tt->lastProcName,"SetStatus");
1500 tt->rxCallPtr = acid;
1503 tt->rxCallPtr = (struct rx_call *)0;
1508 td = &tv->header->diskstuff;
1510 * Add more fields as necessary
1512 if (astatus->maxquota != -1)
1513 td->maxquota = astatus->maxquota;
1514 if (astatus->dayUse != -1)
1515 td->dayUse = astatus->dayUse;
1516 VUpdateVolume(&error, tv);
1517 tt->rxCallPtr = (struct rx_call *)0;
1518 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1523 afs_int32 SAFSVolGetName (acid, atrans, aname)
1524 struct rx_call *acid;
1530 code = VolGetName (acid, atrans, aname);
1531 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1535 afs_int32 VolGetName (acid, atrans, aname)
1536 struct rx_call *acid;
1540 register struct Volume *tv;
1541 register struct VolumeDiskData *td;
1542 struct volser_trans *tt;
1546 tt = FindTrans(atrans);
1547 if (!tt) return ENOENT;
1548 if (tt->vflags & VTDeleted) {
1549 Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
1553 strcpy(tt->lastProcName,"GetName");
1554 tt->rxCallPtr = acid;
1557 tt->rxCallPtr = (struct rx_call *)0;
1562 td = &tv->header->diskstuff;
1563 len = strlen(td->name)+1; /* don't forget the null */
1565 tt->rxCallPtr = (struct rx_call *)0;
1569 *aname = (char *)malloc(len);
1570 strcpy(*aname, td->name);
1571 tt->rxCallPtr = (struct rx_call *)0;
1572 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1576 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1578 afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
1579 struct rx_call *acid;
1581 afs_int32 parentId, cloneId;
1588 /*return a list of all partitions on the server. The non mounted
1589 *partitions are returned as -1 in the corresponding slot in partIds*/
1590 afs_int32 SAFSVolListPartitions (acid, partIds)
1591 struct rx_call *acid;
1592 struct pIDs *partIds;
1596 code = VolListPartitions (acid, partIds);
1597 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1601 afs_int32 VolListPartitions (acid, partIds)
1602 struct rx_call *acid;
1603 struct pIDs *partIds;
1609 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1611 /* Just return attached partitions. */
1613 for (i=0; i<26; i++) {
1614 namehead[6] = i + 'a';
1615 if (VGetPartition(namehead, 0))
1616 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1622 /*return a list of all partitions on the server. The non mounted
1623 *partitions are returned as -1 in the corresponding slot in partIds*/
1624 afs_int32 SAFSVolXListPartitions (acid, pEntries)
1625 struct rx_call *acid;
1626 struct partEntries *pEntries;
1630 code = XVolListPartitions (acid, pEntries);
1631 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1635 afs_int32 XVolListPartitions (acid, pEntries)
1636 struct rx_call *acid;
1637 struct partEntries *pEntries;
1639 struct stat rbuf, pbuf;
1641 struct partList partList;
1642 struct DiskPartition *dp;
1645 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1647 /* Only report attached partitions */
1648 for(i = 0 ; i < VOLMAXPARTS; i++){
1650 namehead[6] = i + 'a';
1654 namehead[6] = 'a' + (k/26);
1655 namehead[7] = 'a' + (k%26);
1658 dp = VGetPartition(namehead, 0);
1660 partList.partId[j++] = i;
1662 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1663 memcpy((char *)pEntries->partEntries_val, (char *)&partList, j * sizeof(int));
1664 pEntries->partEntries_len = j;
1669 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1670 afs_int32 ExtractVolId(vname)
1674 char name[VOLSER_MAXVOLNAME +1];
1678 while(name[i] == 'V' || name[i] == '0')
1681 name[11] = '\0'; /* smash the "." */
1682 return(atol(&name[i]));
1685 /*return the name of the next volume header in the directory associated with dirp and dp.
1686 *the volume id is returned in volid, and volume header name is returned in volname*/
1687 GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
1691 dp = readdir(dirp);/*read next entry in the directory */
1694 if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
1695 *volid = ExtractVolId(dp->d_name);
1696 strcpy(volname,dp->d_name);
1697 return 0;/*return the name of the file representing a volume */
1701 return 0;/*volname doesnot represent a volume*/
1704 else {strcpy(volname,"EOD"); return 0;/*end of directory */}
1708 /*return the header information about the <volid> */
1709 afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
1710 struct rx_call *acid;
1711 afs_int32 volumeId, partid;
1712 volEntries *volumeInfo;
1716 code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
1717 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1721 afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
1722 struct rx_call *acid;
1723 afs_int32 volumeId, partid;
1724 volEntries *volumeInfo;
1726 register struct Volume *tv;
1727 struct DiskPartition *partP;
1728 struct volser_trans *ttc;
1729 char pname[9], volname[20];
1730 afs_int32 error = 0;
1736 volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
1737 pntr = volumeInfo->volEntries_val;
1738 volumeInfo->volEntries_len = 1;
1739 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
1740 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1741 dirp = opendir(VPartitionPath(partP));
1742 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
1744 ttc = (struct volser_trans *) 0;
1745 tv = (Volume *) 0; /* volume not attached */
1747 while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
1749 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
1750 GetNextVol(dirp, volname, &volid);
1751 continue; /*back to while loop */
1754 if(volid == volumeId) { /*copy other things too */
1756 IOMGR_Poll(); /*make sure that the client doesnot time out*/
1757 ttc = NewTrans(volid,partid);
1759 pntr->status = VBUSY;
1760 pntr->volid = volid;
1763 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
1765 pntr->status = 0; /*things are messed up */
1766 strcpy(pntr->name,volname);
1767 pntr->volid = volid;
1768 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
1771 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
1772 /*this volume will be salvaged */
1774 strcpy(pntr->name,volname);
1775 pntr->volid = volid;
1776 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
1780 if(tv->header->diskstuff.needsSalvaged){
1781 /*this volume will be salvaged */
1783 strcpy(pntr->name,volname);
1784 pntr->volid = volid;
1785 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
1789 /*read in the relevant info */
1790 pntr->status = VOK ; /*its ok */
1791 pntr->volid = tv->header->diskstuff.id;
1792 strcpy(pntr->name,tv->header->diskstuff.name);
1793 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
1794 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
1795 pntr->backupID = tv->header->diskstuff.backupId;
1796 pntr->parentID = tv->header->diskstuff.parentId;
1797 pntr->copyDate = tv->header->diskstuff.copyDate;
1798 pntr->inUse = tv->header->diskstuff.inUse;
1799 pntr->size = tv->header->diskstuff.diskused;
1800 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1801 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1802 pntr->maxquota = tv->header->diskstuff.maxquota;
1803 pntr->filecount = tv->header->diskstuff.filecount;
1804 now = FT_ApproxTime();
1805 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1808 pntr->dayUse = tv->header->diskstuff.dayUse;
1809 pntr->creationDate = tv->header->diskstuff.creationDate;
1810 pntr->accessDate = tv->header->diskstuff.accessDate;
1811 pntr->updateDate = tv->header->diskstuff.updateDate;
1812 pntr->backupDate = tv->header->diskstuff.backupDate;
1813 pntr->spare0 = tv->header->diskstuff.minquota;
1814 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
1815 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
1816 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
1817 (long) tv->header->diskstuff.weekUse[6];
1818 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
1819 VDetachVolume(&error,tv);/*free the volume */
1822 pntr->status = 0; /*things are messed up */
1823 strcpy(pntr->name,volname);
1824 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
1828 GetNextVol(dirp, volname, &volid);
1832 VDetachVolume(&error, tv);
1837 ttc = (struct volser_trans *) 0;
1845 /*------------------------------------------------------------------------
1846 * EXPORTED SAFSVolXListOneVolume
1849 * Returns extended info on volume a_volID on partition a_partID.
1852 * a_rxCidP : Pointer to the Rx call we're performing.
1853 * a_partID : Partition for which we want the extended list.
1854 * a_volID : Volume ID we wish to know about.
1855 * a_volumeXInfoP : Ptr to the extended info blob.
1858 * 0 Successful operation
1859 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1862 * Nothing interesting.
1866 *------------------------------------------------------------------------*/
1868 afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1869 struct rx_call *a_rxCidP;
1872 volXEntries *a_volumeXInfoP;
1876 code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1877 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1881 afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1882 struct rx_call *a_rxCidP;
1885 volXEntries *a_volumeXInfoP;
1887 { /*SAFSVolXListOneVolume*/
1889 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
1890 register struct Volume *tv; /*Volume ptr*/
1891 struct volser_trans *ttc; /*Volume transaction ptr*/
1892 struct DiskPartition *partP; /*Ptr to partition */
1893 char pname[9], volname[20]; /*Partition, volume names*/
1894 afs_int32 error; /*Error code*/
1895 afs_int32 code; /*Return code*/
1896 DIR *dirp; /*Partition directory ptr*/
1897 afs_int32 currVolID; /*Current volume ID*/
1898 int found = 0; /*Did we find the volume we need?*/
1899 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
1900 int numStatBytes; /*Num stat bytes to copy per volume*/
1904 * Set up our pointers for action, marking our structure to hold exactly
1905 * one entry. Also, assume we'll fail in our quest.
1907 a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
1908 xInfoP = a_volumeXInfoP->volXEntries_val;
1909 a_volumeXInfoP->volXEntries_len = 1;
1913 * If the partition name we've been given is bad, bogue out.
1915 if (GetPartName(a_partID, pname))
1916 return(VOLSERILLEGAL_PARTITION);
1919 * Open the directory representing the given AFS parttion. If we can't
1922 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1923 dirp = opendir(VPartitionPath(partP));
1925 return(VOLSERILLEGAL_PARTITION);
1928 * Sweep through the partition directory, looking for the desired entry.
1929 * First, of course, figure out how many stat bytes to copy out of each
1932 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
1933 (4*VOLINT_STATS_NUM_TIME_FIELDS));
1934 strcpy(volname, "");
1935 ttc = (struct volser_trans *)0; /*No transaction yet*/
1936 tv = (Volume *)0; /*Volume not yet attached*/
1938 while (strcmp(volname,"EOD") && !found) {
1940 * If this is not a volume, move on to the next entry in the
1941 * partition's directory.
1943 if (!strcmp(volname,"")) {
1944 GetNextVol(dirp, volname, &currVolID);
1948 if (currVolID == a_volID) {
1950 * We found the volume entry we're interested. Pull out the
1951 * extended information, remembering to poll (so that the client
1952 * doesn't time out) and to set up a transaction on the volume.
1956 ttc = NewTrans(currVolID, a_partID);
1959 * Couldn't get a transaction on this volume; let our caller
1962 xInfoP->status = VBUSY;
1963 xInfoP->volid = currVolID;
1968 * Attach the volume, give up on the volume if we can't.
1970 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1972 xInfoP->status = 0; /*things are messed up */
1973 strcpy(xInfoP->name, volname);
1974 xInfoP->volid = currVolID;
1975 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
1981 * Also bag out on this volume if it's been marked as needing a
1982 * salvage or to-be-destroyed.
1984 volDiskDataP = &(tv->header->diskstuff);
1985 if (volDiskDataP->destroyMe == DESTROY_ME) {
1987 strcpy(xInfoP->name, volname);
1988 xInfoP->volid = currVolID;
1989 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
1993 if (volDiskDataP->needsSalvaged) {
1995 strcpy(xInfoP->name, volname);
1996 xInfoP->volid = currVolID;
1997 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
2003 * Pull out the desired info and stuff it into the area we'll be
2004 * returning to our caller.
2006 strcpy(xInfoP->name,volDiskDataP->name);
2007 xInfoP->volid = volDiskDataP->id;
2008 xInfoP->type = volDiskDataP->type;
2009 xInfoP->backupID = volDiskDataP->backupId;
2010 xInfoP->parentID = volDiskDataP->parentId;
2011 xInfoP->cloneID = volDiskDataP->cloneId;
2012 xInfoP->status = VOK;
2013 xInfoP->copyDate = volDiskDataP->copyDate;
2014 xInfoP->inUse = volDiskDataP->inUse;
2015 xInfoP->creationDate = volDiskDataP->creationDate;
2016 xInfoP->accessDate = volDiskDataP->accessDate;
2017 xInfoP->updateDate = volDiskDataP->updateDate;
2018 xInfoP->backupDate = volDiskDataP->backupDate;
2019 now = FT_ApproxTime();
2020 if (now - volDiskDataP->dayUseDate > OneDay)
2023 xInfoP->dayUse = volDiskDataP->dayUse;
2024 xInfoP->filecount = volDiskDataP->filecount;
2025 xInfoP->maxquota = volDiskDataP->maxquota;
2026 xInfoP->size = volDiskDataP->diskused;
2029 * Copy out the stat fields in a single operation.
2031 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2034 * We're done copying. Detach the volume and iterate (at this
2035 * point, since we found our volume, we'll then drop out of the
2038 VDetachVolume(&error, tv);
2042 strcpy(xInfoP->name, volname);
2043 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2049 * At this point, we're golden.
2052 } /*Found desired volume*/
2053 GetNextVol(dirp, volname, &currVolID);
2057 * Drop the transaction we have for this volume.
2061 VDetachVolume(&error, tv);
2066 ttc = (struct volser_trans *)0;
2070 * Clean up before going to dinner: close the partition directory,
2071 * return the proper value.
2076 } /*SAFSVolXListOneVolume*/
2078 /*returns all the volumes on partition partid. If flags = 1 then all the
2079 * relevant info about the volumes is also returned */
2080 afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
2081 struct rx_call *acid;
2082 afs_int32 flags, partid;
2083 volEntries *volumeInfo;
2087 code = VolListVolumes (acid, partid, flags, volumeInfo);
2088 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2092 afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
2093 struct rx_call *acid;
2094 afs_int32 flags, partid;
2095 volEntries *volumeInfo;
2097 register struct Volume *tv;
2098 struct DiskPartition *partP;
2099 struct volser_trans *ttc;
2100 afs_int32 allocSize = 1000;/*to be changed to a larger figure */
2101 char pname[9], volname[20];
2102 afs_int32 error = 0;
2107 volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2108 pntr = volumeInfo->volEntries_val;
2109 volumeInfo->volEntries_len = 0;
2110 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
2111 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2112 dirp = opendir(VPartitionPath(partP));
2113 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2115 while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
2116 ttc = (struct volser_trans *) 0; /* new one for each pass */
2117 tv = (Volume *) 0; /* volume not attached */
2119 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
2120 GetNextVol(dirp, volname, &volid);
2121 continue; /*back to while loop */
2124 if(flags) { /*copy other things too */
2125 IOMGR_Poll(); /*make sure that the client doesnot time out*/
2126 ttc = NewTrans(volid,partid);
2128 pntr->status = VBUSY;
2129 pntr->volid = volid;
2132 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
2134 pntr->status = 0; /*things are messed up */
2135 strcpy(pntr->name,volname);
2136 pntr->volid = volid;
2137 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
2140 if(tv->header->diskstuff.needsSalvaged){
2141 /*this volume will be salvaged */
2143 strcpy(pntr->name,volname);
2144 pntr->volid = volid;
2145 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
2149 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
2150 /*this volume will be salvaged */
2153 /*read in the relevant info */
2154 pntr->status = VOK ; /*its ok */
2155 pntr->volid = tv->header->diskstuff.id;
2156 strcpy(pntr->name,tv->header->diskstuff.name);
2157 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
2158 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
2159 pntr->backupID = tv->header->diskstuff.backupId;
2160 pntr->parentID = tv->header->diskstuff.parentId;
2161 pntr->copyDate = tv->header->diskstuff.copyDate;
2162 pntr->inUse = tv->header->diskstuff.inUse;
2163 pntr->size = tv->header->diskstuff.diskused;
2164 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2165 pntr->maxquota = tv->header->diskstuff.maxquota;
2166 pntr->filecount = tv->header->diskstuff.filecount;
2167 now = FT_ApproxTime();
2168 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2171 pntr->dayUse = tv->header->diskstuff.dayUse;
2172 pntr->creationDate = tv->header->diskstuff.creationDate;
2173 pntr->accessDate = tv->header->diskstuff.accessDate;
2174 pntr->updateDate = tv->header->diskstuff.updateDate;
2175 pntr->backupDate = tv->header->diskstuff.backupDate;
2176 pntr->spare0 = tv->header->diskstuff.minquota;
2177 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
2178 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
2179 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
2180 (long) tv->header->diskstuff.weekUse[6];
2181 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
2182 VDetachVolume(&error,tv);/*free the volume */
2185 pntr->status = 0; /*things are messed up */
2186 strcpy(pntr->name,volname);
2187 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
2191 pntr->volid = volid;
2192 /*just volids are needed*/
2198 ttc = (struct volser_trans *) 0;
2201 volumeInfo->volEntries_len += 1;
2202 if((allocSize - volumeInfo->volEntries_len) < 5) {
2203 /*running out of space, allocate more space */
2204 allocSize = (allocSize *3)/2;
2205 pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
2206 allocSize * sizeof(volintInfo));
2209 VDetachVolume(&error, tv);
2214 ttc = (struct volser_trans *) 0;
2217 return VOLSERNO_MEMORY;
2219 volumeInfo->volEntries_val = pntr; /* point to new block */
2220 /* set pntr to the right position */
2221 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2227 VDetachVolume(&error, tv);
2232 ttc = (struct volser_trans *) 0;
2234 GetNextVol(dirp, volname, &volid);
2244 /*------------------------------------------------------------------------
2245 * EXPORTED SAFSVolXListVolumes
2248 * Returns all the volumes on partition a_partID. If a_flags
2249 * is set to 1, then all the relevant extended volume information
2253 * a_rxCidP : Pointer to the Rx call we're performing.
2254 * a_partID : Partition for which we want the extended list.
2255 * a_flags : Various flags.
2256 * a_volumeXInfoP : Ptr to the extended info blob.
2259 * 0 Successful operation
2260 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2261 * VOLSERNO_MEMORY if we ran out of memory allocating
2265 * Nothing interesting.
2269 *------------------------------------------------------------------------*/
2271 afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2272 struct rx_call *a_rxCidP;
2275 volXEntries *a_volumeXInfoP;
2279 code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2280 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2284 afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2285 struct rx_call *a_rxCidP;
2288 volXEntries *a_volumeXInfoP;
2290 { /*SAFSVolXListVolumes*/
2292 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
2293 register struct Volume *tv; /*Volume ptr*/
2294 struct DiskPartition *partP; /*Ptr to partition*/
2295 struct volser_trans *ttc; /*Volume transaction ptr*/
2296 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2297 char pname[9], volname[20]; /*Partition, volume names*/
2298 afs_int32 error = 0; /*Return code*/
2299 DIR *dirp; /*Partition directory ptr*/
2300 afs_int32 volid; /*Current volume ID*/
2301 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
2302 int numStatBytes; /*Num stat bytes to copy per volume*/
2306 * Allocate a large array of extended volume info structures, then
2307 * set it up for action.
2309 a_volumeXInfoP->volXEntries_val =
2310 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2311 xInfoP = a_volumeXInfoP->volXEntries_val;
2312 a_volumeXInfoP->volXEntries_len = 0;
2315 * If the partition name we've been given is bad, bogue out.
2317 if (GetPartName(a_partID, pname))
2318 return(VOLSERILLEGAL_PARTITION);
2321 * Open the directory representing the given AFS parttion. If we can't
2324 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2325 dirp = opendir(VPartitionPath(partP));
2327 return (VOLSERILLEGAL_PARTITION);
2330 * Sweep through the partition directory, acting on each entry. First,
2331 * of course, figure out how many stat bytes to copy out of each volume.
2333 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
2334 (4*VOLINT_STATS_NUM_TIME_FIELDS));
2336 while (strcmp(volname, "EOD")) {
2337 ttc = (struct volser_trans *)0; /*New one for each pass*/
2338 tv = (Volume *)0; /*Volume not yet attached*/
2341 * If this is not a volume, move on to the next entry in the
2342 * partition's directory.
2344 if(!strcmp(volname,"")) {
2345 GetNextVol(dirp, volname, &volid);
2351 * Full info about the volume desired. Poll to make sure the
2352 * client doesn't time out, then start up a new transaction.
2355 ttc = NewTrans(volid,a_partID);
2358 * Couldn't get a transaction on this volume; let our caller
2361 xInfoP->status = VBUSY;
2362 xInfoP->volid = volid;
2367 * Attach the volume, give up on this volume if we can't.
2369 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2371 xInfoP->status = 0; /*things are messed up */
2372 strcpy(xInfoP->name, volname);
2373 xInfoP->volid = volid;
2374 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2380 * Also bag out on this volume if it's been marked as needing a
2381 * salvage or to-be-destroyed.
2383 volDiskDataP = &(tv->header->diskstuff);
2384 if (volDiskDataP->needsSalvaged) {
2386 strcpy(xInfoP->name, volname);
2387 xInfoP->volid = volid;
2388 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
2393 if (volDiskDataP->destroyMe == DESTROY_ME)
2397 * Pull out the desired info and stuff it into the area we'll be
2398 * returning to our caller.
2400 strcpy(xInfoP->name,volDiskDataP->name);
2401 xInfoP->volid = volDiskDataP->id;
2402 xInfoP->type = volDiskDataP->type;
2403 xInfoP->backupID = volDiskDataP->backupId;
2404 xInfoP->parentID = volDiskDataP->parentId;
2405 xInfoP->cloneID = volDiskDataP->cloneId;
2406 xInfoP->status = VOK;
2407 xInfoP->copyDate = volDiskDataP->copyDate;
2408 xInfoP->inUse = volDiskDataP->inUse;
2409 xInfoP->creationDate = volDiskDataP->creationDate;
2410 xInfoP->accessDate = volDiskDataP->accessDate;
2411 xInfoP->updateDate = volDiskDataP->updateDate;
2412 xInfoP->backupDate = volDiskDataP->backupDate;
2413 now = FT_ApproxTime();
2414 if (now - volDiskDataP->dayUseDate > OneDay)
2417 xInfoP->dayUse = volDiskDataP->dayUse;
2418 xInfoP->filecount = volDiskDataP->filecount;
2419 xInfoP->maxquota = volDiskDataP->maxquota;
2420 xInfoP->size = volDiskDataP->diskused;
2423 * Copy out the stat fields in a single operation.
2425 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2428 * We're done copying. Detach the volume and iterate.
2430 VDetachVolume(&error, tv);
2434 strcpy(xInfoP->name, volname);
2435 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2439 } /*Full contents desired*/
2442 * Just volume IDs are needed.
2444 xInfoP->volid = volid;
2448 * Drop the transaction we have for this volume.
2452 ttc = (struct volser_trans *) 0;
2456 * Bump the pointer in the data area we're building, along with
2457 * the count of the number of entries it contains.
2460 (a_volumeXInfoP->volXEntries_len)++;
2461 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2463 * We're running out of space in the area we've built. Grow it.
2465 allocSize = (allocSize * 3)/2;
2466 xInfoP = (volintXInfo *)
2467 realloc((char *) a_volumeXInfoP->volXEntries_val,
2468 (allocSize * sizeof(volintXInfo)));
2469 if (xInfoP == NULL) {
2471 * Bummer, no memory. Bag it, tell our caller what went wrong.
2474 VDetachVolume(&error, tv);
2479 ttc = (struct volser_trans *) 0;
2482 return(VOLSERNO_MEMORY);
2486 * Memory reallocation worked. Correct our pointers so they
2487 * now point to the new block and the current open position within
2490 a_volumeXInfoP->volXEntries_val = xInfoP;
2491 xInfoP = a_volumeXInfoP->volXEntries_val +
2492 a_volumeXInfoP->volXEntries_len;
2493 } /*Need more space*/
2497 * Detach our current volume and the transaction on it, then move on
2498 * to the next volume in the partition directory.
2501 VDetachVolume(&error, tv);
2506 ttc = (struct volser_trans *) 0;
2508 GetNextVol(dirp, volname, &volid);
2509 } /*Sweep through the partition directory*/
2512 * We've examined all entries in the partition directory. Close it,
2513 * delete our transaction (if any), and go home happy.
2520 } /*SAFSVolXListVolumes*/
2522 /*this call is used to monitor the status of volser for debugging purposes.
2523 *information about all the active transactions is returned in transInfo*/
2524 afs_int32 SAFSVolMonitor (acid,transInfo)
2525 struct rx_call *acid;
2526 transDebugEntries *transInfo;
2530 code = VolMonitor (acid,transInfo);
2531 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2535 afs_int32 VolMonitor (acid,transInfo)
2536 struct rx_call *acid;
2537 transDebugEntries *transInfo;
2539 transDebugInfo *pntr;
2540 afs_int32 allocSize = 50;
2541 struct volser_trans *tt, *allTrans;
2543 transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2544 pntr = transInfo->transDebugEntries_val;
2545 transInfo->transDebugEntries_len = 0;
2546 allTrans = TransList();
2547 if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
2548 for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
2549 pntr->tid = tt->tid;
2550 pntr->time = tt->time;
2551 pntr->creationTime = tt->creationTime;
2552 pntr->returnCode = tt->returnCode;
2553 pntr->volid = tt->volid;
2554 pntr->partition = tt->partition;
2555 pntr->iflags = tt->iflags;
2556 pntr->vflags = tt->vflags;
2557 pntr->tflags = tt->tflags;
2558 strcpy(pntr->lastProcName,tt->lastProcName);
2559 pntr->callValid = 0;
2560 if(tt->rxCallPtr) { /*record call related info */
2561 pntr->callValid = 1;
2562 pntr->readNext = tt->rxCallPtr->rnext;
2563 pntr->transmitNext = tt->rxCallPtr->tnext;
2564 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2565 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2568 transInfo->transDebugEntries_len += 1;
2569 if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
2570 allocSize = (allocSize *3)/2;
2571 pntr = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
2572 transInfo->transDebugEntries_val = pntr;
2573 pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
2574 /*set pntr to right position*/
2582 afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2583 struct rx_call *acid;
2584 afs_int32 type, pId, cloneId, backupId, atid;
2589 code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
2590 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid,
2595 AUD_LONG, backupId, AUD_END);
2599 afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2600 struct rx_call *acid;
2601 afs_int32 type, pId, cloneId, backupId, atid;
2605 afs_int32 error = 0;
2606 register struct volser_trans *tt;
2607 char caller[MAXKTCNAMELEN];
2609 if (strlen(name)>31) return VOLSERBADNAME;
2610 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2611 /* find the trans */
2612 tt = FindTrans(atid);
2613 if (!tt) return ENOENT;
2614 if (tt->vflags & VTDeleted) {
2615 Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
2619 strcpy(tt->lastProcName,"SetIdsTypes");
2620 tt->rxCallPtr = acid;
2624 V_backupId(tv) = backupId;
2625 V_cloneId(tv) = cloneId;
2626 V_parentId(tv) = pId;
2627 strcpy((&V_disk(tv))->name,name);
2628 VUpdateVolume(&error, tv);
2630 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2634 tt->rxCallPtr = (struct rx_call *)0;
2635 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2639 tt->rxCallPtr = (struct rx_call *)0;
2640 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2644 afs_int32 SAFSVolSetDate (acid,atid,cdate)
2645 struct rx_call *acid;
2646 afs_int32 atid, cdate;
2650 code = VolSetDate (acid,atid,cdate);
2651 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
2655 afs_int32 VolSetDate (acid,atid,cdate)
2656 struct rx_call *acid;
2657 afs_int32 atid, cdate;
2660 afs_int32 error = 0;
2661 register struct volser_trans *tt;
2662 char caller[MAXKTCNAMELEN];
2664 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2665 /* find the trans */
2666 tt = FindTrans(atid);
2667 if (!tt) return ENOENT;
2668 if (tt->vflags & VTDeleted) {
2669 Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
2673 strcpy(tt->lastProcName,"SetDate");
2674 tt->rxCallPtr = acid;
2677 V_creationDate(tv) = cdate;
2678 VUpdateVolume(&error, tv);
2680 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2684 tt->rxCallPtr = (struct rx_call *)0;
2685 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2689 tt->rxCallPtr = (struct rx_call *)0;
2690 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2694 #ifdef AFS_NAMEI_ENV
2696 * Inode number format (from namei_ops.c):
2697 * low 26 bits - vnode number - all 1's if volume special file.
2699 * next 3 bits spare (0's)
2700 * high 32 bits - uniquifier (regular) or type if spare
2702 #define NAMEI_VNODEMASK 0x003ffffff
2703 #define NAMEI_TAGMASK 0x7
2704 #define NAMEI_TAGSHIFT 26
2705 #define NAMEI_UNIQMASK 0xffffffff
2706 #define NAMEI_UNIQSHIFT 32
2707 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2708 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2709 #endif /* AFS_NAMEI_ENV */
2711 afs_int32 SAFSVolConvertROtoRWvolume(acid, partId, volumeId)
2712 struct rx_call *acid;
2716 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2720 afs_int32 error = 0;
2723 char caller[MAXKTCNAMELEN];
2724 char headername[16];
2727 struct VolumeDiskHeader h;
2731 struct DiskPartition *dp;
2733 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2734 if(GetPartName(partId, pname)) return VOLSERILLEGAL_PARTITION;
2735 dirp = opendir(pname);
2736 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2739 while(strcmp(volname,"EOD") && !found) { /*while there are more volumes in the partition */
2740 GetNextVol(dirp,volname,&volid);
2741 if(strcmp(volname,"")) {/* its a volume */
2742 if(volid == volumeId) found = 1;
2745 if (!found) return ENOENT;
2746 sprintf(headername, VFORMAT, volumeId);
2747 sprintf(opath,"%s/%s", pname, headername);
2748 fd = open(opath, O_RDONLY);
2750 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2753 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2754 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2759 FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
2761 for(dp = DiskPartitionList; dp && strcmp(dp->name, pname); dp = dp->next) ;
2763 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2766 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
2767 IH_INIT(ih, dp->device, h.parent, ino);
2769 error = namei_ConvertROtoRWvolume(ih, volumeId);
2773 h.volumeInfo_hi = h.id;
2774 h.smallVnodeIndex_hi = h.id;
2775 h.largeVnodeIndex_hi = h.id;
2776 h.linkTable_hi = h.id;
2777 sprintf(headername, VFORMAT, h.id);
2778 sprintf(npath, "%s/%s", pname, headername);
2779 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
2781 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
2784 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
2785 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
2790 if (unlink(opath) < 0) {
2791 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
2793 FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
2794 FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
2796 #else /* AFS_NAMEI_ENV */
2798 #endif /* AFS_NAMEI_ENV */
2801 /* GetPartName - map partid (a decimal number) into pname (a string)
2802 * Since for NT we actually want to return the drive name, we map through the
2805 static int GetPartName(afs_int32 partid, char *pname)
2810 strcpy(pname,"/vicep");
2811 pname[6] = 'a' + partid;
2814 } else if (partid < VOLMAXPARTS) {
2815 strcpy(pname,"/vicep");
2817 pname[6] = 'a' + (partid / 26);
2818 pname[7] = 'a' + (partid % 26);