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>
31 #include <afs/afsint.h>
33 #include <afs/assert.h>
34 #include <afs/prs_fs.h>
39 #include <afs/cellconfig.h>
42 #include <afs/ihandle.h>
44 #include <afs/ntops.h>
46 #include <afs/vnode.h>
47 #include <afs/volume.h>
48 #include <afs/partition.h>
50 #include <afs/fssync.h>
52 #include "afs/audit.h"
57 extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
58 extern struct rx_securityClass *rxnull_NewServerSecurityObject();
59 extern struct rx_service *rx_NewService();
60 extern struct rx_securityClass *rxnull_NewClientSecurityObject();
61 extern struct afsconf_dir *tdir;
62 extern char *volutil_PartitionName();
64 /* Forward declarations */
65 static int GetPartName(afs_int32 partid, char *pname);
67 #define OneDay (24*60*60)
74 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
75 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
76 afs_int32 VolForwardMultiple();
77 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
78 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
79 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
81 /* this call unlocks all of the partition locks we've set */
83 register struct DiskPartition *tp;
84 for(tp = DiskPartitionList; tp; tp = tp->next) {
85 if (tp->lock_fd != -1) {
86 close(tp->lock_fd); /* releases flock held on this partition */
93 /* get partition id from a name */
94 afs_int32 PartitionID(aname)
97 register int code = 0;
101 if (tc == 0) return -1; /* unknown */
103 /* otherwise check for vicepa or /vicepa, or just plain "a" */
105 if (!strncmp(aname, "/vicep", 6)) {
106 strncpy(ascii, aname+6, 2);
108 else return -1; /* bad partition name */
109 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
110 from 0. Do the appropriate conversion */
112 /* one char name, 0..25 */
113 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
114 return ascii[0] - 'a';
117 /* two char name, 26 .. <whatever> */
118 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
119 if (ascii[1] < 'a' || ascii[1] > 'z') return -1; /* just as bad */
120 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
121 if (code > VOLMAXPARTS) return -1;
126 static int ConvertVolume(avol, aname, asize)
130 if (asize < 18) return -1;
131 /* 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 */
132 sprintf(aname, VFORMAT, avol);
136 static int ConvertPartition(apartno, aname, asize)
140 if (asize < 10) return E2BIG;
141 if (apartno < 0) return EINVAL;
142 strcpy(aname, "/vicep");
144 aname[6] = 'a'+apartno;
149 aname[6] = 'a' + (apartno / 26);
150 aname[7] = 'a' + (apartno % 26);
156 /* the only attach function that takes a partition is "...ByName", so we use it */
157 struct Volume *XAttachVolume(error, avolid, apartid, amode)
162 char pbuf[30], vbuf[20];
163 register struct Volume *tv;
165 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
167 return (struct Volume *) 0;
169 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
171 return (struct Volume *) 0;
173 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
177 /* Adapted from the file server; create a root directory for this volume */
178 static ViceCreateRoot(vp)
182 struct acl_accessList * ACL;
184 Inode inodeNumber, nearInode;
185 char buf[SIZEOF_LARGEDISKVNODE];
186 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
187 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
193 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
195 V_pref(vp, nearInode);
196 inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
197 VPartitionPath(V_partition(vp)), nearInode,
198 V_parentId(vp), 1, 1, 0);
199 assert(VALID_INO(inodeNumber));
201 SetSalvageDirHandle(&dir, V_id(vp), vp->device, inodeNumber);
202 did.Volume = V_id(vp);
203 did.Vnode = (VnodeId)1;
206 assert(!(MakeDir(&dir, &did, &did)));
207 DFlush(); /* flush all modified dir buffers out */
208 DZap(&dir); /* Remove all buffers for this dir */
209 length = Length(&dir); /* Remember size of this directory */
211 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
213 /* build a single entry ACL that gives all rights to system:administrators */
214 /* this section of code assumes that access list format is not going to
217 ACL = VVnodeDiskACL(vnode);
218 ACL->size = sizeof(struct acl_accessList);
219 ACL->version = ACL_ACLVERSION;
223 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
224 ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
226 vnode->type = vDirectory;
228 vnode->modeBits = 0777;
229 vnode->linkCount = 2;
230 vnode->length = length;
231 vnode->uniquifier = 1;
232 V_uniquifier(vp) = vnode->uniquifier+1;
233 vnode->dataVersion = 1;
234 VNDISK_SET_INO(vnode, inodeNumber);
235 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
239 vnode->vnodeMagic = vcp->magic;
241 IH_INIT(h, vp->device, V_parentId(vp),
242 vp->vnodeIndex[vLarge].handle->ih_ino);
245 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
247 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
248 assert(code == SIZEOF_LARGEDISKVNODE);
249 FDH_REALLYCLOSE(fdP);
251 V_diskused(vp) = nBlocks(vnode->length);
256 afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
257 struct rx_call *acid;
259 struct diskPartition *partition;
263 code = VolPartitionInfo (acid,pname,partition);
264 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
268 afs_int32 VolPartitionInfo (acid,pname,partition)
269 struct rx_call *acid;
271 struct diskPartition *partition;
273 register struct DiskPartition *dp;
276 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
279 dp = VGetPartition(pname, 0);
281 strncpy(partition->name,dp->name,32);
282 strncpy(partition->devName,dp->devName,32);
283 partition->lock_fd = dp->lock_fd ;
284 partition->free = dp->free;
285 partition->minFree = dp->totalUsable;
289 return VOLSERILLEGAL_PARTITION;
292 /* obliterate a volume completely, and slowly. */
293 afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
294 struct rx_call *acid;
295 afs_int32 apartID, avolID;
299 code = VolNukeVolume (acid, apartID, avolID);
300 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
304 afs_int32 VolNukeVolume (acid, apartID, avolID)
305 struct rx_call *acid;
306 afs_int32 apartID, avolID;
311 register afs_int32 code;
313 char caller[MAXKTCNAMELEN];
315 /* check for access */
316 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
317 if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
319 tp = volutil_PartitionName(apartID);
320 if (!tp) return VOLSERNOVOL;
321 strcpy(partName, tp); /* remember it for later */
322 /* we first try to attach the volume in update mode, so that the file
323 * server doesn't try to use it (and abort) while (or after) we delete it.
324 * If we don't get the volume, that's fine, too. We just won't put it back.
326 tvp = XAttachVolume(&error, avolID, apartID, V_UPDATE);
327 code = nuke(partName, avolID);
328 if (tvp) VDetachVolume(&error, tvp);
332 /* create a new volume, with name aname, on the specified partition (1..n)
333 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
334 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
335 * for the volume id (useful for things like volume restore).
336 * Return the new volume id in *avolid.
338 afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
339 struct rx_call *acid;
349 code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
350 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans,
359 afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
360 struct rx_call *acid;
370 afs_int32 junk; /* discardable error code */
371 register afs_int32 volumeID, doCreateRoot=1;
372 register struct volser_trans *tt;
374 char caller[MAXKTCNAMELEN];
376 if (strlen(aname) > 31) return VOLSERBADNAME;
377 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
378 if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
379 if (error = ConvertPartition(apart, ppath, sizeof(ppath))) return error;/*a standard unix error*/
380 if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
382 if ((volumeID = *avolid) == 0) {
384 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
388 if ((aparent == volumeID) && (atype == readwriteVolume)) {
391 if (aparent == 0) aparent = volumeID;
392 tt = NewTrans(volumeID, apart);
394 Log("1 createvolume: failed to create trans\n");
395 return VOLSERVOLBUSY; /* volume already busy! */
397 vp = VCreateVolume(&error, ppath, volumeID, aparent);
399 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
404 V_uniquifier(vp) = 1;
405 V_creationDate(vp) = V_copyDate(vp);
406 V_inService(vp) = V_blessed(vp) = 1;
408 AssignVolumeName(&V_disk(vp), aname, 0);
411 V_destroyMe(vp) = DESTROY_ME;
413 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
414 VUpdateVolume(&error, vp);
416 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
419 VDetachVolume(&junk, vp); /* rather return the real error code */
424 strcpy(tt->lastProcName,"CreateVolume");
425 tt->rxCallPtr = acid;
426 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
427 tt->rxCallPtr = (struct rx_call *)0;
428 if(TRELE(tt)) return VOLSERTRELE_ERROR;
432 /* delete the volume associated with this transaction */
433 afs_int32 SAFSVolDeleteVolume (acid, atrans)
435 struct rx_call *acid;
439 code = VolDeleteVolume (acid, atrans);
440 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
444 afs_int32 VolDeleteVolume (acid, atrans)
446 struct rx_call *acid;
448 register struct volser_trans *tt;
450 char caller[MAXKTCNAMELEN];
452 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
453 tt = FindTrans(atrans);
454 if (!tt) return ENOENT;
455 if (tt->vflags & VTDeleted) {
456 Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
460 if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
461 strcpy(tt->lastProcName,"DeleteVolume");
462 tt->rxCallPtr = acid;
463 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
464 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
465 tt->rxCallPtr = (struct rx_call *)0;
466 if(TRELE(tt)) return VOLSERTRELE_ERROR;
468 Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
469 return 0; /* vpurgevolume doesn't set an error code */
472 /* make a clone of the volume associated with atrans, possibly giving it a new
473 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
474 * for the clone's id). The new clone is given the name newName. Finally, due to
475 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
476 * the clone operation. This may be useful when making new backup volumes, for instance
477 * since the net result of a clone and a purge generally leaves many inode ref counts
478 * the same, while doing them separately would result in far more iincs and idecs being
479 * peformed (and they are slow operations).
481 afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
482 struct rx_call *acid;
485 afs_int32 *newNumber;
486 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
491 code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
492 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans,
496 AUD_LONG, *newNumber, AUD_END);
500 afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
501 struct rx_call *acid;
504 afs_int32 *newNumber;
505 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
509 register struct Volume *originalvp, *purgevp, *newvp;
511 register struct volser_trans *tt,*ttc;
512 char caller[MAXKTCNAMELEN];
514 if (strlen(newName)>31) return VOLSERBADNAME;
515 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
516 if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
518 originalvp = (Volume *) 0;
519 purgevp = (Volume *) 0;
520 newvp = (Volume *) 0;
521 tt = ttc = (struct volser_trans *) 0;
523 if (!newNumber || !*newNumber)
525 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
530 if (newType != readonlyVolume && newType != backupVolume)
532 tt = FindTrans(atrans);
533 if (!tt) return ENOENT;
534 if (tt->vflags & VTDeleted) {
535 Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
539 ttc = NewTrans(newId,tt->partition);
541 { /* someone is messing with the clone already */
545 strcpy(tt->lastProcName,"Clone");
546 tt->rxCallPtr = acid;
550 purgevp = VAttachVolume(&error, purgeId, V_UPDATE);
552 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
557 purgevp = (struct Volume *) 0;
559 originalvp = tt->volume;
560 if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
561 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
565 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
566 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
572 if (originalvp->device != purgevp->device) {
573 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
577 if (V_type(purgevp) != readonlyVolume) {
578 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
582 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
583 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
587 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
588 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
597 newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
599 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
600 newvp = (Volume *) 0;
603 if (newType == readonlyVolume)
604 V_cloneId(originalvp) = newId;
605 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
607 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
608 CloneVolume(&error, originalvp, newvp, purgevp);
609 purgevp = (struct Volume *) 0; /* clone releases it, maybe even if error */
611 Log("1 Volser: Clone: clone operation failed with code %d\n", error);
615 if (newType == readonlyVolume) {
616 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
617 V_type(newvp) = readonlyVolume;
619 else if (newType == backupVolume) {
620 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
621 V_type(newvp) = backupVolume;
622 V_backupId(originalvp) = newId;
624 strcpy(newvp->header->diskstuff.name,newName);
625 V_creationDate(newvp) = V_copyDate(newvp);
626 ClearVolumeStats(&V_disk(newvp));
627 V_destroyMe(newvp) = DESTROY_ME;
628 V_inService(newvp) = 0;
629 if (newType == backupVolume) {
630 V_backupDate(originalvp) = V_copyDate(newvp);
631 V_backupDate(newvp) = V_copyDate(newvp);
634 VUpdateVolume(&error, newvp);
636 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
640 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
641 newvp = (struct Volume *) 0;
642 VUpdateVolume(&error, originalvp);
644 Log("1 Volser: Clone: original update %d\n", error);
648 tt->rxCallPtr = (struct rx_call *)0;
650 tt = (struct volser_trans *) 0;
651 error = VOLSERTRELE_ERROR;
658 if (purgevp) VDetachVolume(&code, purgevp);
659 if (newvp) VDetachVolume(&code, newvp);
661 tt->rxCallPtr = (struct rx_call *)0;
664 if(ttc) DeleteTrans(ttc);
668 /* reclone this volume into the specified id */
669 afs_int32 SAFSVolReClone (acid, atrans, cloneId)
670 struct rx_call *acid;
676 code = VolReClone (acid, atrans, cloneId);
677 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
681 afs_int32 VolReClone (acid, atrans, cloneId)
682 struct rx_call *acid;
686 register struct Volume *originalvp, *clonevp;
689 register struct volser_trans *tt,*ttc;
690 char caller[MAXKTCNAMELEN];
693 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
694 if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
696 clonevp = originalvp = (Volume *) 0;
697 tt = (struct volser_trans *) 0;
699 tt = FindTrans(atrans);
700 if (!tt) return ENOENT;
701 if (tt->vflags & VTDeleted) {
702 Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
706 ttc = NewTrans(cloneId, tt->partition);
707 if (!ttc){ /* someone is messing with the clone already */
711 strcpy(tt->lastProcName,"ReClone");
712 tt->rxCallPtr = acid;
714 originalvp = tt->volume;
715 if ((V_type(originalvp) == backupVolume) ||
716 (V_type(originalvp) == readonlyVolume)){
717 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
721 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
722 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
728 clonevp = VAttachVolume(&error, cloneId, V_UPDATE);
730 Log("1 Volser: can't attach clone %d\n", cloneId);
734 newType = V_type(clonevp); /* type of the new volume */
736 if (originalvp->device != clonevp->device) {
737 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
741 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
742 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
746 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
747 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
751 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
752 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
759 Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
761 CloneVolume(&error, originalvp, clonevp, clonevp);
763 Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
768 /* fix up volume name and type, CloneVolume just propagated RW's */
769 if (newType == readonlyVolume) {
770 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
771 V_type(clonevp) = readonlyVolume;
773 else if (newType == backupVolume) {
774 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
775 V_type(clonevp) = backupVolume;
776 V_backupId(originalvp) = cloneId;
778 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
780 /* pretend recloned volume is a totally new instance */
781 V_copyDate(clonevp) = time(0);
782 V_creationDate(clonevp) = V_copyDate(clonevp);
783 ClearVolumeStats(&V_disk(clonevp));
784 V_destroyMe(clonevp) = 0;
785 V_inService(clonevp) = 0;
786 if (newType == backupVolume) {
787 V_backupDate(originalvp) = V_copyDate(clonevp);
788 V_backupDate(clonevp) = V_copyDate(clonevp);
790 V_inUse(clonevp) = 0;
791 VUpdateVolume(&error, clonevp);
793 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
797 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
798 clonevp = (struct Volume *) 0;
799 VUpdateVolume(&error, originalvp);
801 Log("1 Volser: Clone: original update %d\n", error);
805 tt->rxCallPtr = (struct rx_call *)0;
807 tt = (struct volser_trans *) 0;
808 error = VOLSERTRELE_ERROR;
815 struct DiskPartition *tpartp = originalvp->partition;
816 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
821 if (clonevp) VDetachVolume(&code, clonevp);
823 tt->rxCallPtr = (struct rx_call *)0;
826 if(ttc) DeleteTrans(ttc);
830 /* create a new transaction, associated with volume and partition. Type of
831 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
832 * See volser.h for definition of iflags (the constants are named IT*).
834 afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
835 struct rx_call *acid;
843 code = VolTransCreate (acid, volume, partition, iflags, ttid);
844 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
848 afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
849 struct rx_call *acid;
855 register struct volser_trans *tt;
857 afs_int32 error, code;
859 char caller[MAXKTCNAMELEN];
861 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
862 if (iflags & ITCreate) mode = V_SECRETLY;
863 else if (iflags & ITBusy) mode = V_CLONE;
864 else if (iflags & ITReadOnly) mode = V_READONLY;
865 else if (iflags & ITOffline) mode = V_UPDATE;
867 Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
871 tt = NewTrans(volume, partition);
873 /* can't create a transaction? put the volume back */
874 Log("1 transcreate: can't create transaction\n");
875 return VOLSERVOLBUSY;
877 tv = XAttachVolume(&error, volume, partition, mode);
880 if (tv) VDetachVolume(&code, tv);
888 strcpy(tt->lastProcName,"TransCreate");
889 if(TRELE(tt)) return VOLSERTRELE_ERROR;
894 /* using aindex as a 0-based index, return the aindex'th volume on this server
895 * Both the volume number and partition number (one-based) are returned.
897 afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
898 struct rx_call *acid;
905 code = VolGetNthVolume (acid, aindex, avolume, apart);
906 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
910 afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
911 struct rx_call *acid;
916 Log("1 Volser: GetNthVolume: Not yet implemented\n");
920 /* return the volume flags (VT* constants in volser.h) associated with this
923 afs_int32 SAFSVolGetFlags (acid, atid, aflags)
924 struct rx_call *acid;
930 code = VolGetFlags (acid, atid, aflags);
931 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
935 afs_int32 VolGetFlags (acid, atid, aflags)
936 struct rx_call *acid;
940 register struct volser_trans *tt;
942 tt = FindTrans(atid);
943 if (!tt) return ENOENT;
944 if (tt->vflags & VTDeleted) {
945 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
949 strcpy(tt->lastProcName,"GetFlags");
950 tt->rxCallPtr = acid;
951 *aflags = tt->vflags;
952 tt->rxCallPtr = (struct rx_call *)0;
953 if(TRELE(tt)) return VOLSERTRELE_ERROR;
958 /* Change the volume flags (VT* constants in volser.h) associated with this
959 * transaction. Effects take place immediately on volume, although volume
960 * remains attached as usual by the transaction.
962 afs_int32 SAFSVolSetFlags (acid, atid, aflags)
963 struct rx_call *acid;
969 code = VolSetFlags (acid, atid, aflags);
970 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
974 afs_int32 VolSetFlags (acid, atid, aflags)
975 struct rx_call *acid;
979 register struct volser_trans *tt;
980 register struct Volume *vp;
982 char caller[MAXKTCNAMELEN];
984 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
986 tt = FindTrans(atid);
987 if (!tt) return ENOENT;
988 if (tt->vflags & VTDeleted) {
989 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
993 strcpy(tt->lastProcName,"SetFlags");
994 tt->rxCallPtr = acid;
995 vp = tt->volume; /* pull volume out of transaction */
997 /* check if we're allowed to make any updates */
998 if (tt->iflags & ITReadOnly) {
1003 /* handle delete-on-salvage flag */
1004 if (aflags & VTDeleteOnSalvage) {
1005 V_destroyMe(tt->volume) = DESTROY_ME;
1008 V_destroyMe(tt->volume) = 0;
1011 if (aflags & VTOutOfService) {
1012 V_inService(vp) = 0;
1015 V_inService(vp) = 1;
1017 VUpdateVolume(&error, vp);
1018 tt->vflags = aflags;
1019 tt->rxCallPtr = (struct rx_call *)0;
1020 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
1025 /* dumpS the volume associated with a particular transaction from a particular
1026 * date. Send the dump to a different transaction (destTrans) on the server
1027 * specified by the destServer structure.
1029 afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1030 struct rx_call *acid;
1031 afs_int32 fromTrans;
1033 struct destServer *destination;
1034 struct restoreCookie *cookie;
1035 afs_int32 destTrans;
1039 code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
1040 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans,
1041 AUD_HOST, destination->destHost,
1042 AUD_LONG, destTrans, AUD_END);
1046 afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1047 struct rx_call *acid;
1048 afs_int32 fromTrans;
1050 struct destServer *destination;
1051 struct restoreCookie *cookie;
1052 afs_int32 destTrans;
1054 register struct volser_trans *tt;
1055 register afs_int32 code;
1056 register struct rx_connection *tcon;
1057 struct rx_call *tcall;
1058 register struct Volume *vp;
1059 struct rx_securityClass *securityObject;
1060 afs_int32 securityIndex;
1061 char caller[MAXKTCNAMELEN];
1063 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1064 /* initialize things */
1065 tcon = (struct rx_connection *) 0;
1066 tt = (struct volser_trans *) 0;
1068 /* find the local transaction */
1069 tt = FindTrans(fromTrans);
1070 if (!tt) return ENOENT;
1071 if (tt->vflags & VTDeleted) {
1072 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1077 strcpy(tt->lastProcName,"Forward");
1079 /* get auth info for the this connection (uses afs from ticket file) */
1080 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1086 /* make an rpc connection to the other server */
1087 tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
1089 tt->rxCallPtr = (struct rx_call *)0;
1093 tcall = rx_NewCall(tcon);
1094 tt->rxCallPtr = tcall;
1095 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1096 code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
1101 /* these next calls implictly call rx_Write when writing out data */
1102 code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
1103 if (code) goto fail;
1104 EndAFSVolRestore(tcall); /* probably doesn't do much */
1105 tt->rxCallPtr = (struct rx_call *)0;
1106 code = rx_EndCall(tcall, 0);
1107 rx_DestroyConnection(tcon); /* done with the connection */
1109 if (code) goto fail;
1110 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1116 rx_EndCall(tcall,0);
1117 rx_DestroyConnection(tcon);
1120 tt->rxCallPtr = (struct rx_call *)0;
1126 /* Start a dump and send it to multiple places simultaneously.
1127 * If this returns an error (eg, return ENOENT), it means that
1128 * none of the releases worked. If this returns 0, that means
1129 * that one or more of the releases worked, and the caller has
1130 * to examine the results array to see which one(s).
1131 * This will only do EITHER incremental or full, not both, so it's
1132 * the caller's responsibility to be sure that all the destinations
1133 * need just an incremental (and from the same time), if that's
1136 afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations,
1137 spare, cookie, results)
1138 struct rx_call *acid;
1139 afs_int32 fromTrans;
1142 manyDests *destinations;
1143 struct restoreCookie *cookie;
1144 manyResults *results;
1146 afs_int32 securityIndex;
1147 struct rx_securityClass *securityObject;
1148 char caller[MAXKTCNAMELEN];
1149 struct volser_trans *tt;
1150 afs_int32 ec, code, *codes;
1151 struct rx_connection **tcons;
1152 struct rx_call **tcalls;
1154 int i, nconns, is_incremental;
1157 memset(results, 0, sizeof(manyResults));
1159 if (!afsconf_SuperUser(tdir, acid, caller))
1160 return VOLSERBAD_ACCESS;/*not a super user*/
1161 tt = FindTrans(fromTrans);
1164 if (tt->vflags & VTDeleted) {
1165 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1170 strcpy(tt->lastProcName, "ForwardMulti");
1172 /* (fromDate == 0) ==> incremental dump */
1173 is_incremental = (fromDate ? 1 : 0);
1175 i= results->manyResults_len = destinations->manyDests_len;
1176 results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
1177 tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
1178 tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
1180 /* get auth info for this connection (uses afs from ticket file) */
1181 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1183 goto fail; /* in order to audit each failure */
1186 /* make connections to all the other servers */
1187 for (i=0; i < destinations->manyDests_len; i++) {
1188 struct replica *dest = &(destinations->manyDests_val[i]);
1189 tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
1190 htons(dest->server.destPort),
1191 VOLSERVICE_ID, securityObject, securityIndex);
1193 codes[i] = ENOTCONN;
1196 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1199 codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
1200 is_incremental,cookie);
1202 rx_EndCall (tcalls[i],0); tcalls[i] = 0;
1203 rx_DestroyConnection(tcons[i]); tcons[i] = 0;
1209 /* these next calls implictly call rx_Write when writing out data */
1210 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1214 for (i--; i >=0 ; i--) {
1215 struct replica *dest = &(destinations->manyDests_val[i]);
1217 if (!code && tcalls[i] && !codes[i]) {
1218 EndAFSVolRestore(tcalls[i]);
1221 ec = rx_EndCall(tcalls[i], 0);
1222 if (!codes[i]) codes[i] = ec;
1225 rx_DestroyConnection(tcons[i]); /* done with the connection */
1228 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]),
1229 AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost,
1230 AUD_LONG, dest->trans, AUD_END);
1236 tt->rxCallPtr = (struct rx_call *)0;
1237 if(TRELE(tt) && !code) /* return the first code if it's set */
1238 return VOLSERTRELE_ERROR;
1244 afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
1245 struct rx_call *acid;
1246 afs_int32 fromTrans;
1251 code = VolDump (acid, fromTrans, fromDate);
1252 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1256 afs_int32 VolDump (acid, fromTrans, fromDate)
1257 struct rx_call *acid;
1258 afs_int32 fromTrans;
1262 register struct volser_trans *tt;
1263 char caller[MAXKTCNAMELEN];
1265 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1266 tt = FindTrans(fromTrans);
1267 if (!tt) return ENOENT;
1268 if (tt->vflags & VTDeleted) {
1269 Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
1273 strcpy(tt->lastProcName,"Dump");
1274 tt->rxCallPtr = acid;
1275 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1276 if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
1277 tt->rxCallPtr = (struct rx_call *)0;
1279 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1285 * Ha! No more helper process!
1287 afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
1288 struct rx_call *acid;
1291 struct restoreCookie *cookie;
1295 code = VolRestore (acid, atrans, aflags,cookie);
1296 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1300 afs_int32 VolRestore (acid, atrans, aflags,cookie)
1301 struct rx_call *acid;
1304 struct restoreCookie *cookie;
1306 register struct volser_trans *tt;
1307 register afs_int32 code,tcode;
1308 char caller[MAXKTCNAMELEN];
1310 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1311 tt = FindTrans(atrans);
1312 if (!tt) return ENOENT;
1313 if (tt->vflags & VTDeleted) {
1314 Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
1318 strcpy(tt->lastProcName,"Restore");
1319 tt->rxCallPtr = acid;
1320 code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie); /* last is incrementalp */
1321 FSYNC_askfs(tt->volid, (char *) 0, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
1323 tt->rxCallPtr = (struct rx_call *)0;
1326 return (code? code : tcode);
1329 /* end a transaction, returning the transaction's final error code in rcode */
1330 afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
1331 struct rx_call *acid;
1332 afs_int32 destTrans;
1337 code = VolEndTrans (acid, destTrans, rcode);
1338 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1342 afs_int32 VolEndTrans (acid, destTrans, rcode)
1343 struct rx_call *acid;
1344 afs_int32 destTrans;
1347 register struct volser_trans *tt;
1348 char caller[MAXKTCNAMELEN];
1350 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1351 tt = FindTrans(destTrans);
1352 if (!tt) {return ENOENT;}
1353 *rcode = tt->returnCode;
1354 DeleteTrans(tt); /* this does an implicit TRELE */
1359 afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
1360 struct rx_call *acid;
1366 code = VolSetForwarding (acid, atid, anewsite);
1367 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
1371 afs_int32 VolSetForwarding (acid, atid, anewsite)
1372 struct rx_call *acid;
1377 register struct volser_trans *tt;
1378 char caller[MAXKTCNAMELEN];
1380 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1381 tt = FindTrans(atid);
1382 if (!tt) return ENOENT;
1383 if (tt->vflags & VTDeleted) {
1384 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
1388 strcpy(tt->lastProcName,"SetForwarding");
1389 tt->rxCallPtr = acid;
1390 FSYNC_askfs(tt->volid, (char *) 0, FSYNC_MOVEVOLUME, anewsite);
1391 tt->rxCallPtr = (struct rx_call *)0;
1392 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1397 afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
1398 struct rx_call *acid;
1400 register struct volser_status *astatus;
1404 code = VolGetStatus (acid, atrans, astatus);
1405 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1409 afs_int32 VolGetStatus (acid, atrans, astatus)
1410 struct rx_call *acid;
1412 register struct volser_status *astatus;
1414 register struct Volume *tv;
1415 register struct VolumeDiskData *td;
1416 struct volser_trans *tt;
1419 tt = FindTrans(atrans);
1420 if (!tt) return ENOENT;
1421 if (tt->vflags & VTDeleted) {
1422 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
1426 strcpy(tt->lastProcName,"GetStatus");
1427 tt->rxCallPtr = acid;
1430 tt->rxCallPtr = (struct rx_call *)0;
1435 td = &tv->header->diskstuff;
1436 astatus->volID = td->id;
1437 astatus->nextUnique = td->uniquifier;
1438 astatus->type = td->type;
1439 astatus->parentID = td->parentId;
1440 astatus->cloneID = td->cloneId;
1441 astatus->backupID = td->backupId;
1442 astatus->restoredFromID = td->restoredFromId;
1443 astatus->maxQuota = td->maxquota;
1444 astatus->minQuota = td->minquota;
1445 astatus->owner = td->owner;
1446 astatus->creationDate = td->creationDate;
1447 astatus->accessDate = td->accessDate;
1448 astatus->updateDate = td->updateDate;
1449 astatus->expirationDate = td->expirationDate;
1450 astatus->backupDate = td->backupDate;
1451 astatus->copyDate = td->copyDate;
1452 tt->rxCallPtr = (struct rx_call *)0;
1453 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1458 afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
1459 struct rx_call *acid;
1461 register struct volintInfo *astatus;
1465 code = VolSetInfo (acid, atrans, astatus);
1466 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1470 afs_int32 VolSetInfo (acid, atrans, astatus)
1471 struct rx_call *acid;
1473 register struct volintInfo *astatus;
1475 register struct Volume *tv;
1476 register struct VolumeDiskData *td;
1477 struct volser_trans *tt;
1478 char caller[MAXKTCNAMELEN];
1481 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1482 tt = FindTrans(atrans);
1483 if (!tt) return ENOENT;
1484 if (tt->vflags & VTDeleted) {
1485 Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
1489 strcpy(tt->lastProcName,"SetStatus");
1490 tt->rxCallPtr = acid;
1493 tt->rxCallPtr = (struct rx_call *)0;
1498 td = &tv->header->diskstuff;
1500 * Add more fields as necessary
1502 if (astatus->maxquota != -1)
1503 td->maxquota = astatus->maxquota;
1504 if (astatus->dayUse != -1)
1505 td->dayUse = astatus->dayUse;
1506 VUpdateVolume(&error, tv);
1507 tt->rxCallPtr = (struct rx_call *)0;
1508 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1513 afs_int32 SAFSVolGetName (acid, atrans, aname)
1514 struct rx_call *acid;
1520 code = VolGetName (acid, atrans, aname);
1521 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1525 afs_int32 VolGetName (acid, atrans, aname)
1526 struct rx_call *acid;
1530 register struct Volume *tv;
1531 register struct VolumeDiskData *td;
1532 struct volser_trans *tt;
1536 tt = FindTrans(atrans);
1537 if (!tt) return ENOENT;
1538 if (tt->vflags & VTDeleted) {
1539 Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
1543 strcpy(tt->lastProcName,"GetName");
1544 tt->rxCallPtr = acid;
1547 tt->rxCallPtr = (struct rx_call *)0;
1552 td = &tv->header->diskstuff;
1553 len = strlen(td->name)+1; /* don't forget the null */
1555 tt->rxCallPtr = (struct rx_call *)0;
1559 *aname = (char *)malloc(len);
1560 strcpy(*aname, td->name);
1561 tt->rxCallPtr = (struct rx_call *)0;
1562 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1566 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1568 afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
1569 struct rx_call *acid;
1571 afs_int32 parentId, cloneId;
1578 /*return a list of all partitions on the server. The non mounted
1579 *partitions are returned as -1 in the corresponding slot in partIds*/
1580 afs_int32 SAFSVolListPartitions (acid, partIds)
1581 struct rx_call *acid;
1582 struct pIDs *partIds;
1586 code = VolListPartitions (acid, partIds);
1587 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1591 afs_int32 VolListPartitions (acid, partIds)
1592 struct rx_call *acid;
1593 struct pIDs *partIds;
1599 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1601 /* Just return attached partitions. */
1603 for (i=0; i<26; i++) {
1604 namehead[6] = i + 'a';
1605 if (VGetPartition(namehead, 0))
1606 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1612 /*return a list of all partitions on the server. The non mounted
1613 *partitions are returned as -1 in the corresponding slot in partIds*/
1614 afs_int32 SAFSVolXListPartitions (acid, pEntries)
1615 struct rx_call *acid;
1616 struct partEntries *pEntries;
1620 code = XVolListPartitions (acid, pEntries);
1621 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1625 afs_int32 XVolListPartitions (acid, pEntries)
1626 struct rx_call *acid;
1627 struct partEntries *pEntries;
1629 struct stat rbuf, pbuf;
1631 struct partList partList;
1632 struct DiskPartition *dp;
1635 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1637 /* Only report attached partitions */
1638 for(i = 0 ; i < VOLMAXPARTS; i++){
1640 namehead[6] = i + 'a';
1644 namehead[6] = 'a' + (k/26);
1645 namehead[7] = 'a' + (k%26);
1648 dp = VGetPartition(namehead, 0);
1650 partList.partId[j++] = i;
1652 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1653 memcpy((char *)pEntries->partEntries_val, (char *)&partList, j * sizeof(int));
1654 pEntries->partEntries_len = j;
1659 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1660 afs_int32 ExtractVolId(vname)
1664 char name[VOLSER_MAXVOLNAME +1];
1668 while(name[i] == 'V' || name[i] == '0')
1671 name[11] = '\0'; /* smash the "." */
1672 return(atol(&name[i]));
1675 /*return the name of the next volume header in the directory associated with dirp and dp.
1676 *the volume id is returned in volid, and volume header name is returned in volname*/
1677 GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
1681 dp = readdir(dirp);/*read next entry in the directory */
1684 if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
1685 *volid = ExtractVolId(dp->d_name);
1686 strcpy(volname,dp->d_name);
1687 return 0;/*return the name of the file representing a volume */
1691 return 0;/*volname doesnot represent a volume*/
1694 else {strcpy(volname,"EOD"); return 0;/*end of directory */}
1698 /*return the header information about the <volid> */
1699 afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
1700 struct rx_call *acid;
1701 afs_int32 volumeId, partid;
1702 volEntries *volumeInfo;
1706 code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
1707 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1711 afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
1712 struct rx_call *acid;
1713 afs_int32 volumeId, partid;
1714 volEntries *volumeInfo;
1716 register struct Volume *tv;
1717 struct DiskPartition *partP;
1718 struct volser_trans *ttc;
1719 char pname[9], volname[20];
1720 afs_int32 error = 0;
1726 volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
1727 pntr = volumeInfo->volEntries_val;
1728 volumeInfo->volEntries_len = 1;
1729 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
1730 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1731 dirp = opendir(VPartitionPath(partP));
1732 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
1734 ttc = (struct volser_trans *) 0;
1735 tv = (Volume *) 0; /* volume not attached */
1737 while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
1739 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
1740 GetNextVol(dirp, volname, &volid);
1741 continue; /*back to while loop */
1744 if(volid == volumeId) { /*copy other things too */
1746 IOMGR_Poll(); /*make sure that the client doesnot time out*/
1747 ttc = NewTrans(volid,partid);
1749 pntr->status = VBUSY;
1750 pntr->volid = volid;
1753 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
1755 pntr->status = 0; /*things are messed up */
1756 strcpy(pntr->name,volname);
1757 pntr->volid = volid;
1758 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
1761 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
1762 /*this volume will be salvaged */
1764 strcpy(pntr->name,volname);
1765 pntr->volid = volid;
1766 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
1770 if(tv->header->diskstuff.needsSalvaged){
1771 /*this volume will be salvaged */
1773 strcpy(pntr->name,volname);
1774 pntr->volid = volid;
1775 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
1779 /*read in the relevant info */
1780 pntr->status = VOK ; /*its ok */
1781 pntr->volid = tv->header->diskstuff.id;
1782 strcpy(pntr->name,tv->header->diskstuff.name);
1783 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
1784 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
1785 pntr->backupID = tv->header->diskstuff.backupId;
1786 pntr->parentID = tv->header->diskstuff.parentId;
1787 pntr->copyDate = tv->header->diskstuff.copyDate;
1788 pntr->inUse = tv->header->diskstuff.inUse;
1789 pntr->size = tv->header->diskstuff.diskused;
1790 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1791 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1792 pntr->maxquota = tv->header->diskstuff.maxquota;
1793 pntr->filecount = tv->header->diskstuff.filecount;
1794 now = FT_ApproxTime();
1795 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1798 pntr->dayUse = tv->header->diskstuff.dayUse;
1799 pntr->creationDate = tv->header->diskstuff.creationDate;
1800 pntr->accessDate = tv->header->diskstuff.accessDate;
1801 pntr->updateDate = tv->header->diskstuff.updateDate;
1802 pntr->backupDate = tv->header->diskstuff.backupDate;
1803 pntr->spare0 = tv->header->diskstuff.minquota;
1804 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
1805 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
1806 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
1807 (long) tv->header->diskstuff.weekUse[6];
1808 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
1809 VDetachVolume(&error,tv);/*free the volume */
1812 pntr->status = 0; /*things are messed up */
1813 strcpy(pntr->name,volname);
1814 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
1818 GetNextVol(dirp, volname, &volid);
1822 VDetachVolume(&error, tv);
1827 ttc = (struct volser_trans *) 0;
1835 /*------------------------------------------------------------------------
1836 * EXPORTED SAFSVolXListOneVolume
1839 * Returns extended info on volume a_volID on partition a_partID.
1842 * a_rxCidP : Pointer to the Rx call we're performing.
1843 * a_partID : Partition for which we want the extended list.
1844 * a_volID : Volume ID we wish to know about.
1845 * a_volumeXInfoP : Ptr to the extended info blob.
1848 * 0 Successful operation
1849 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1852 * Nothing interesting.
1856 *------------------------------------------------------------------------*/
1858 afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1859 struct rx_call *a_rxCidP;
1862 volXEntries *a_volumeXInfoP;
1866 code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1867 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1871 afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1872 struct rx_call *a_rxCidP;
1875 volXEntries *a_volumeXInfoP;
1877 { /*SAFSVolXListOneVolume*/
1879 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
1880 register struct Volume *tv; /*Volume ptr*/
1881 struct volser_trans *ttc; /*Volume transaction ptr*/
1882 struct DiskPartition *partP; /*Ptr to partition */
1883 char pname[9], volname[20]; /*Partition, volume names*/
1884 afs_int32 error; /*Error code*/
1885 afs_int32 code; /*Return code*/
1886 DIR *dirp; /*Partition directory ptr*/
1887 afs_int32 currVolID; /*Current volume ID*/
1888 int found = 0; /*Did we find the volume we need?*/
1889 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
1890 int numStatBytes; /*Num stat bytes to copy per volume*/
1894 * Set up our pointers for action, marking our structure to hold exactly
1895 * one entry. Also, assume we'll fail in our quest.
1897 a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
1898 xInfoP = a_volumeXInfoP->volXEntries_val;
1899 a_volumeXInfoP->volXEntries_len = 1;
1903 * If the partition name we've been given is bad, bogue out.
1905 if (GetPartName(a_partID, pname))
1906 return(VOLSERILLEGAL_PARTITION);
1909 * Open the directory representing the given AFS parttion. If we can't
1912 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1913 dirp = opendir(VPartitionPath(partP));
1915 return(VOLSERILLEGAL_PARTITION);
1918 * Sweep through the partition directory, looking for the desired entry.
1919 * First, of course, figure out how many stat bytes to copy out of each
1922 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
1923 (4*VOLINT_STATS_NUM_TIME_FIELDS));
1924 strcpy(volname, "");
1925 ttc = (struct volser_trans *)0; /*No transaction yet*/
1926 tv = (Volume *)0; /*Volume not yet attached*/
1928 while (strcmp(volname,"EOD") && !found) {
1930 * If this is not a volume, move on to the next entry in the
1931 * partition's directory.
1933 if (!strcmp(volname,"")) {
1934 GetNextVol(dirp, volname, &currVolID);
1938 if (currVolID == a_volID) {
1940 * We found the volume entry we're interested. Pull out the
1941 * extended information, remembering to poll (so that the client
1942 * doesn't time out) and to set up a transaction on the volume.
1946 ttc = NewTrans(currVolID, a_partID);
1949 * Couldn't get a transaction on this volume; let our caller
1952 xInfoP->status = VBUSY;
1953 xInfoP->volid = currVolID;
1958 * Attach the volume, give up on the volume if we can't.
1960 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1962 xInfoP->status = 0; /*things are messed up */
1963 strcpy(xInfoP->name, volname);
1964 xInfoP->volid = currVolID;
1965 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
1971 * Also bag out on this volume if it's been marked as needing a
1972 * salvage or to-be-destroyed.
1974 volDiskDataP = &(tv->header->diskstuff);
1975 if (volDiskDataP->destroyMe == DESTROY_ME) {
1977 strcpy(xInfoP->name, volname);
1978 xInfoP->volid = currVolID;
1979 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
1983 if (volDiskDataP->needsSalvaged) {
1985 strcpy(xInfoP->name, volname);
1986 xInfoP->volid = currVolID;
1987 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
1993 * Pull out the desired info and stuff it into the area we'll be
1994 * returning to our caller.
1996 strcpy(xInfoP->name,volDiskDataP->name);
1997 xInfoP->volid = volDiskDataP->id;
1998 xInfoP->type = volDiskDataP->type;
1999 xInfoP->backupID = volDiskDataP->backupId;
2000 xInfoP->parentID = volDiskDataP->parentId;
2001 xInfoP->cloneID = volDiskDataP->cloneId;
2002 xInfoP->status = VOK;
2003 xInfoP->copyDate = volDiskDataP->copyDate;
2004 xInfoP->inUse = volDiskDataP->inUse;
2005 xInfoP->creationDate = volDiskDataP->creationDate;
2006 xInfoP->accessDate = volDiskDataP->accessDate;
2007 xInfoP->updateDate = volDiskDataP->updateDate;
2008 xInfoP->backupDate = volDiskDataP->backupDate;
2009 now = FT_ApproxTime();
2010 if (now - volDiskDataP->dayUseDate > OneDay)
2013 xInfoP->dayUse = volDiskDataP->dayUse;
2014 xInfoP->filecount = volDiskDataP->filecount;
2015 xInfoP->maxquota = volDiskDataP->maxquota;
2016 xInfoP->size = volDiskDataP->diskused;
2019 * Copy out the stat fields in a single operation.
2021 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2024 * We're done copying. Detach the volume and iterate (at this
2025 * point, since we found our volume, we'll then drop out of the
2028 VDetachVolume(&error, tv);
2032 strcpy(xInfoP->name, volname);
2033 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2039 * At this point, we're golden.
2042 } /*Found desired volume*/
2043 GetNextVol(dirp, volname, &currVolID);
2047 * Drop the transaction we have for this volume.
2051 VDetachVolume(&error, tv);
2056 ttc = (struct volser_trans *)0;
2060 * Clean up before going to dinner: close the partition directory,
2061 * return the proper value.
2066 } /*SAFSVolXListOneVolume*/
2068 /*returns all the volumes on partition partid. If flags = 1 then all the
2069 * relevant info about the volumes is also returned */
2070 afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
2071 struct rx_call *acid;
2072 afs_int32 flags, partid;
2073 volEntries *volumeInfo;
2077 code = VolListVolumes (acid, partid, flags, volumeInfo);
2078 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2082 afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
2083 struct rx_call *acid;
2084 afs_int32 flags, partid;
2085 volEntries *volumeInfo;
2087 register struct Volume *tv;
2088 struct DiskPartition *partP;
2089 struct volser_trans *ttc;
2090 afs_int32 allocSize = 1000;/*to be changed to a larger figure */
2091 char pname[9], volname[20];
2092 afs_int32 error = 0;
2097 volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2098 pntr = volumeInfo->volEntries_val;
2099 volumeInfo->volEntries_len = 0;
2100 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
2101 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2102 dirp = opendir(VPartitionPath(partP));
2103 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2105 while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
2106 ttc = (struct volser_trans *) 0; /* new one for each pass */
2107 tv = (Volume *) 0; /* volume not attached */
2109 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
2110 GetNextVol(dirp, volname, &volid);
2111 continue; /*back to while loop */
2114 if(flags) { /*copy other things too */
2115 IOMGR_Poll(); /*make sure that the client doesnot time out*/
2116 ttc = NewTrans(volid,partid);
2118 pntr->status = VBUSY;
2119 pntr->volid = volid;
2122 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
2124 pntr->status = 0; /*things are messed up */
2125 strcpy(pntr->name,volname);
2126 pntr->volid = volid;
2127 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
2130 if(tv->header->diskstuff.needsSalvaged){
2131 /*this volume will be salvaged */
2133 strcpy(pntr->name,volname);
2134 pntr->volid = volid;
2135 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
2139 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
2140 /*this volume will be salvaged */
2143 /*read in the relevant info */
2144 pntr->status = VOK ; /*its ok */
2145 pntr->volid = tv->header->diskstuff.id;
2146 strcpy(pntr->name,tv->header->diskstuff.name);
2147 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
2148 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
2149 pntr->backupID = tv->header->diskstuff.backupId;
2150 pntr->parentID = tv->header->diskstuff.parentId;
2151 pntr->copyDate = tv->header->diskstuff.copyDate;
2152 pntr->inUse = tv->header->diskstuff.inUse;
2153 pntr->size = tv->header->diskstuff.diskused;
2154 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2155 pntr->maxquota = tv->header->diskstuff.maxquota;
2156 pntr->filecount = tv->header->diskstuff.filecount;
2157 now = FT_ApproxTime();
2158 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2161 pntr->dayUse = tv->header->diskstuff.dayUse;
2162 pntr->creationDate = tv->header->diskstuff.creationDate;
2163 pntr->accessDate = tv->header->diskstuff.accessDate;
2164 pntr->updateDate = tv->header->diskstuff.updateDate;
2165 pntr->backupDate = tv->header->diskstuff.backupDate;
2166 pntr->spare0 = tv->header->diskstuff.minquota;
2167 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
2168 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
2169 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
2170 (long) tv->header->diskstuff.weekUse[6];
2171 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
2172 VDetachVolume(&error,tv);/*free the volume */
2175 pntr->status = 0; /*things are messed up */
2176 strcpy(pntr->name,volname);
2177 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
2181 pntr->volid = volid;
2182 /*just volids are needed*/
2188 ttc = (struct volser_trans *) 0;
2191 volumeInfo->volEntries_len += 1;
2192 if((allocSize - volumeInfo->volEntries_len) < 5) {
2193 /*running out of space, allocate more space */
2194 allocSize = (allocSize *3)/2;
2195 pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
2196 allocSize * sizeof(volintInfo));
2199 VDetachVolume(&error, tv);
2204 ttc = (struct volser_trans *) 0;
2207 return VOLSERNO_MEMORY;
2209 volumeInfo->volEntries_val = pntr; /* point to new block */
2210 /* set pntr to the right position */
2211 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2217 VDetachVolume(&error, tv);
2222 ttc = (struct volser_trans *) 0;
2224 GetNextVol(dirp, volname, &volid);
2234 /*------------------------------------------------------------------------
2235 * EXPORTED SAFSVolXListVolumes
2238 * Returns all the volumes on partition a_partID. If a_flags
2239 * is set to 1, then all the relevant extended volume information
2243 * a_rxCidP : Pointer to the Rx call we're performing.
2244 * a_partID : Partition for which we want the extended list.
2245 * a_flags : Various flags.
2246 * a_volumeXInfoP : Ptr to the extended info blob.
2249 * 0 Successful operation
2250 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2251 * VOLSERNO_MEMORY if we ran out of memory allocating
2255 * Nothing interesting.
2259 *------------------------------------------------------------------------*/
2261 afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2262 struct rx_call *a_rxCidP;
2265 volXEntries *a_volumeXInfoP;
2269 code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2270 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2274 afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2275 struct rx_call *a_rxCidP;
2278 volXEntries *a_volumeXInfoP;
2280 { /*SAFSVolXListVolumes*/
2282 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
2283 register struct Volume *tv; /*Volume ptr*/
2284 struct DiskPartition *partP; /*Ptr to partition*/
2285 struct volser_trans *ttc; /*Volume transaction ptr*/
2286 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2287 char pname[9], volname[20]; /*Partition, volume names*/
2288 afs_int32 error = 0; /*Return code*/
2289 DIR *dirp; /*Partition directory ptr*/
2290 afs_int32 volid; /*Current volume ID*/
2291 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
2292 int numStatBytes; /*Num stat bytes to copy per volume*/
2296 * Allocate a large array of extended volume info structures, then
2297 * set it up for action.
2299 a_volumeXInfoP->volXEntries_val =
2300 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2301 xInfoP = a_volumeXInfoP->volXEntries_val;
2302 a_volumeXInfoP->volXEntries_len = 0;
2305 * If the partition name we've been given is bad, bogue out.
2307 if (GetPartName(a_partID, pname))
2308 return(VOLSERILLEGAL_PARTITION);
2311 * Open the directory representing the given AFS parttion. If we can't
2314 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2315 dirp = opendir(VPartitionPath(partP));
2317 return (VOLSERILLEGAL_PARTITION);
2320 * Sweep through the partition directory, acting on each entry. First,
2321 * of course, figure out how many stat bytes to copy out of each volume.
2323 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
2324 (4*VOLINT_STATS_NUM_TIME_FIELDS));
2326 while (strcmp(volname, "EOD")) {
2327 ttc = (struct volser_trans *)0; /*New one for each pass*/
2328 tv = (Volume *)0; /*Volume not yet attached*/
2331 * If this is not a volume, move on to the next entry in the
2332 * partition's directory.
2334 if(!strcmp(volname,"")) {
2335 GetNextVol(dirp, volname, &volid);
2341 * Full info about the volume desired. Poll to make sure the
2342 * client doesn't time out, then start up a new transaction.
2345 ttc = NewTrans(volid,a_partID);
2348 * Couldn't get a transaction on this volume; let our caller
2351 xInfoP->status = VBUSY;
2352 xInfoP->volid = volid;
2357 * Attach the volume, give up on this volume if we can't.
2359 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2361 xInfoP->status = 0; /*things are messed up */
2362 strcpy(xInfoP->name, volname);
2363 xInfoP->volid = volid;
2364 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2370 * Also bag out on this volume if it's been marked as needing a
2371 * salvage or to-be-destroyed.
2373 volDiskDataP = &(tv->header->diskstuff);
2374 if (volDiskDataP->needsSalvaged) {
2376 strcpy(xInfoP->name, volname);
2377 xInfoP->volid = volid;
2378 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
2383 if (volDiskDataP->destroyMe == DESTROY_ME)
2387 * Pull out the desired info and stuff it into the area we'll be
2388 * returning to our caller.
2390 strcpy(xInfoP->name,volDiskDataP->name);
2391 xInfoP->volid = volDiskDataP->id;
2392 xInfoP->type = volDiskDataP->type;
2393 xInfoP->backupID = volDiskDataP->backupId;
2394 xInfoP->parentID = volDiskDataP->parentId;
2395 xInfoP->cloneID = volDiskDataP->cloneId;
2396 xInfoP->status = VOK;
2397 xInfoP->copyDate = volDiskDataP->copyDate;
2398 xInfoP->inUse = volDiskDataP->inUse;
2399 xInfoP->creationDate = volDiskDataP->creationDate;
2400 xInfoP->accessDate = volDiskDataP->accessDate;
2401 xInfoP->updateDate = volDiskDataP->updateDate;
2402 xInfoP->backupDate = volDiskDataP->backupDate;
2403 now = FT_ApproxTime();
2404 if (now - volDiskDataP->dayUseDate > OneDay)
2407 xInfoP->dayUse = volDiskDataP->dayUse;
2408 xInfoP->filecount = volDiskDataP->filecount;
2409 xInfoP->maxquota = volDiskDataP->maxquota;
2410 xInfoP->size = volDiskDataP->diskused;
2413 * Copy out the stat fields in a single operation.
2415 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2418 * We're done copying. Detach the volume and iterate.
2420 VDetachVolume(&error, tv);
2424 strcpy(xInfoP->name, volname);
2425 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2429 } /*Full contents desired*/
2432 * Just volume IDs are needed.
2434 xInfoP->volid = volid;
2438 * Drop the transaction we have for this volume.
2442 ttc = (struct volser_trans *) 0;
2446 * Bump the pointer in the data area we're building, along with
2447 * the count of the number of entries it contains.
2450 (a_volumeXInfoP->volXEntries_len)++;
2451 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2453 * We're running out of space in the area we've built. Grow it.
2455 allocSize = (allocSize * 3)/2;
2456 xInfoP = (volintXInfo *)
2457 realloc((char *) a_volumeXInfoP->volXEntries_val,
2458 (allocSize * sizeof(volintXInfo)));
2459 if (xInfoP == NULL) {
2461 * Bummer, no memory. Bag it, tell our caller what went wrong.
2464 VDetachVolume(&error, tv);
2469 ttc = (struct volser_trans *) 0;
2472 return(VOLSERNO_MEMORY);
2476 * Memory reallocation worked. Correct our pointers so they
2477 * now point to the new block and the current open position within
2480 a_volumeXInfoP->volXEntries_val = xInfoP;
2481 xInfoP = a_volumeXInfoP->volXEntries_val +
2482 a_volumeXInfoP->volXEntries_len;
2483 } /*Need more space*/
2487 * Detach our current volume and the transaction on it, then move on
2488 * to the next volume in the partition directory.
2491 VDetachVolume(&error, tv);
2496 ttc = (struct volser_trans *) 0;
2498 GetNextVol(dirp, volname, &volid);
2499 } /*Sweep through the partition directory*/
2502 * We've examined all entries in the partition directory. Close it,
2503 * delete our transaction (if any), and go home happy.
2510 } /*SAFSVolXListVolumes*/
2512 /*this call is used to monitor the status of volser for debugging purposes.
2513 *information about all the active transactions is returned in transInfo*/
2514 afs_int32 SAFSVolMonitor (acid,transInfo)
2515 struct rx_call *acid;
2516 transDebugEntries *transInfo;
2520 code = VolMonitor (acid,transInfo);
2521 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2525 afs_int32 VolMonitor (acid,transInfo)
2526 struct rx_call *acid;
2527 transDebugEntries *transInfo;
2529 transDebugInfo *pntr;
2530 afs_int32 allocSize = 50;
2531 struct volser_trans *tt, *allTrans;
2533 transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2534 pntr = transInfo->transDebugEntries_val;
2535 transInfo->transDebugEntries_len = 0;
2536 allTrans = TransList();
2537 if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
2538 for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
2539 pntr->tid = tt->tid;
2540 pntr->time = tt->time;
2541 pntr->creationTime = tt->creationTime;
2542 pntr->returnCode = tt->returnCode;
2543 pntr->volid = tt->volid;
2544 pntr->partition = tt->partition;
2545 pntr->iflags = tt->iflags;
2546 pntr->vflags = tt->vflags;
2547 pntr->tflags = tt->tflags;
2548 strcpy(pntr->lastProcName,tt->lastProcName);
2549 pntr->callValid = 0;
2550 if(tt->rxCallPtr) { /*record call related info */
2551 pntr->callValid = 1;
2552 pntr->readNext = tt->rxCallPtr->rnext;
2553 pntr->transmitNext = tt->rxCallPtr->tnext;
2554 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2555 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2558 transInfo->transDebugEntries_len += 1;
2559 if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
2560 allocSize = (allocSize *3)/2;
2561 pntr = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
2562 transInfo->transDebugEntries_val = pntr;
2563 pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
2564 /*set pntr to right position*/
2572 afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2573 struct rx_call *acid;
2574 afs_int32 type, pId, cloneId, backupId, atid;
2579 code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
2580 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid,
2585 AUD_LONG, backupId, AUD_END);
2589 afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2590 struct rx_call *acid;
2591 afs_int32 type, pId, cloneId, backupId, atid;
2595 afs_int32 error = 0;
2596 register struct volser_trans *tt;
2597 char caller[MAXKTCNAMELEN];
2599 if (strlen(name)>31) return VOLSERBADNAME;
2600 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2601 /* find the trans */
2602 tt = FindTrans(atid);
2603 if (!tt) return ENOENT;
2604 if (tt->vflags & VTDeleted) {
2605 Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
2609 strcpy(tt->lastProcName,"SetIdsTypes");
2610 tt->rxCallPtr = acid;
2614 V_backupId(tv) = backupId;
2615 V_cloneId(tv) = cloneId;
2616 V_parentId(tv) = pId;
2617 strcpy((&V_disk(tv))->name,name);
2618 VUpdateVolume(&error, tv);
2620 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2624 tt->rxCallPtr = (struct rx_call *)0;
2625 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2629 tt->rxCallPtr = (struct rx_call *)0;
2630 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2634 afs_int32 SAFSVolSetDate (acid,atid,cdate)
2635 struct rx_call *acid;
2636 afs_int32 atid, cdate;
2640 code = VolSetDate (acid,atid,cdate);
2641 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
2645 afs_int32 VolSetDate (acid,atid,cdate)
2646 struct rx_call *acid;
2647 afs_int32 atid, cdate;
2650 afs_int32 error = 0;
2651 register struct volser_trans *tt;
2652 char caller[MAXKTCNAMELEN];
2654 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2655 /* find the trans */
2656 tt = FindTrans(atid);
2657 if (!tt) return ENOENT;
2658 if (tt->vflags & VTDeleted) {
2659 Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
2663 strcpy(tt->lastProcName,"SetDate");
2664 tt->rxCallPtr = acid;
2667 V_creationDate(tv) = cdate;
2668 VUpdateVolume(&error, tv);
2670 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2674 tt->rxCallPtr = (struct rx_call *)0;
2675 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2679 tt->rxCallPtr = (struct rx_call *)0;
2680 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2684 /* GetPartName - map partid (a decimal number) into pname (a string)
2685 * Since for NT we actually want to return the drive name, we map through the
2688 static int GetPartName(afs_int32 partid, char *pname)
2693 strcpy(pname,"/vicep");
2694 pname[6] = 'a' + partid;
2697 } else if (partid < VOLMAXPARTS) {
2698 strcpy(pname,"/vicep");
2700 pname[6] = 'a' + (partid / 26);
2701 pname[7] = 'a' + (partid % 26);