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 <afs/param.h>
12 #include <sys/types.h>
19 #include <netinet/in.h>
27 #include <afs/afsint.h>
29 #include <afs/assert.h>
30 #include <afs/prs_fs.h>
35 #include <afs/cellconfig.h>
38 #include <afs/ihandle.h>
40 #include <afs/ntops.h>
42 #include <afs/vnode.h>
43 #include <afs/volume.h>
44 #include <afs/partition.h>
46 #include <afs/fssync.h>
48 #include "afs/audit.h"
53 extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
54 extern struct rx_securityClass *rxnull_NewServerSecurityObject();
55 extern struct rx_service *rx_NewService();
56 extern struct rx_securityClass *rxnull_NewClientSecurityObject();
57 extern struct afsconf_dir *tdir;
58 extern char *volutil_PartitionName();
60 /* Forward declarations */
61 static int GetPartName(afs_int32 partid, char *pname);
63 #define OneDay (24*60*60)
70 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
71 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
72 afs_int32 VolForwardMultiple();
73 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
74 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
75 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
77 /* this call unlocks all of the partition locks we've set */
79 register struct DiskPartition *tp;
80 for(tp = DiskPartitionList; tp; tp = tp->next) {
81 if (tp->lock_fd != -1) {
82 close(tp->lock_fd); /* releases flock held on this partition */
89 /* get partition id from a name */
90 afs_int32 PartitionID(aname)
93 register int code = 0;
97 if (tc == 0) return -1; /* unknown */
99 /* otherwise check for vicepa or /vicepa, or just plain "a" */
101 if (!strncmp(aname, "/vicep", 6)) {
102 strncpy(ascii, aname+6, 2);
104 else return -1; /* bad partition name */
105 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
106 from 0. Do the appropriate conversion */
108 /* one char name, 0..25 */
109 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
110 return ascii[0] - 'a';
113 /* two char name, 26 .. <whatever> */
114 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
115 if (ascii[1] < 'a' || ascii[1] > 'z') return -1; /* just as bad */
116 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
117 if (code > VOLMAXPARTS) return -1;
122 static int ConvertVolume(avol, aname, asize)
126 if (asize < 18) return -1;
127 /* 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 */
128 sprintf(aname, VFORMAT, avol);
132 static int ConvertPartition(apartno, aname, asize)
136 if (asize < 10) return E2BIG;
137 if (apartno < 0) return EINVAL;
138 strcpy(aname, "/vicep");
140 aname[6] = 'a'+apartno;
145 aname[6] = 'a' + (apartno / 26);
146 aname[7] = 'a' + (apartno % 26);
152 /* the only attach function that takes a partition is "...ByName", so we use it */
153 struct Volume *XAttachVolume(error, avolid, apartid, amode)
158 char pbuf[30], vbuf[20];
159 register struct Volume *tv;
161 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
163 return (struct Volume *) 0;
165 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
167 return (struct Volume *) 0;
169 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
173 /* Adapted from the file server; create a root directory for this volume */
174 static ViceCreateRoot(vp)
178 struct acl_accessList * ACL;
180 Inode inodeNumber, nearInode;
181 char buf[SIZEOF_LARGEDISKVNODE];
182 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
183 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
189 bzero(vnode, SIZEOF_LARGEDISKVNODE);
191 V_pref(vp, nearInode);
192 inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
193 VPartitionPath(V_partition(vp)), nearInode,
194 V_parentId(vp), 1, 1, 0);
195 assert(VALID_INO(inodeNumber));
197 SetSalvageDirHandle(&dir, V_id(vp), vp->device, inodeNumber);
198 did.Volume = V_id(vp);
199 did.Vnode = (VnodeId)1;
202 assert(!(MakeDir(&dir, &did, &did)));
203 DFlush(); /* flush all modified dir buffers out */
204 DZap(&dir); /* Remove all buffers for this dir */
205 length = Length(&dir); /* Remember size of this directory */
207 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
209 /* build a single entry ACL that gives all rights to system:administrators */
210 /* this section of code assumes that access list format is not going to
213 ACL = VVnodeDiskACL(vnode);
214 ACL->size = sizeof(struct acl_accessList);
215 ACL->version = ACL_ACLVERSION;
219 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
220 ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
222 vnode->type = vDirectory;
224 vnode->modeBits = 0777;
225 vnode->linkCount = 2;
226 vnode->length = length;
227 vnode->uniquifier = 1;
228 V_uniquifier(vp) = vnode->uniquifier+1;
229 vnode->dataVersion = 1;
230 VNDISK_SET_INO(vnode, inodeNumber);
231 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
235 vnode->vnodeMagic = vcp->magic;
237 IH_INIT(h, vp->device, V_parentId(vp),
238 vp->vnodeIndex[vLarge].handle->ih_ino);
241 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
243 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
244 assert(code == SIZEOF_LARGEDISKVNODE);
245 FDH_REALLYCLOSE(fdP);
247 V_diskused(vp) = nBlocks(vnode->length);
252 afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
253 struct rx_call *acid;
255 struct diskPartition *partition;
259 code = VolPartitionInfo (acid,pname,partition);
260 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
264 afs_int32 VolPartitionInfo (acid,pname,partition)
265 struct rx_call *acid;
267 struct diskPartition *partition;
269 register struct DiskPartition *dp;
272 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
275 dp = VGetPartition(pname, 0);
277 strncpy(partition->name,dp->name,32);
278 strncpy(partition->devName,dp->devName,32);
279 partition->lock_fd = dp->lock_fd ;
280 partition->free = dp->free;
281 partition->minFree = dp->totalUsable;
285 return VOLSERILLEGAL_PARTITION;
288 /* obliterate a volume completely, and slowly. */
289 afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
290 struct rx_call *acid;
291 afs_int32 apartID, avolID;
295 code = VolNukeVolume (acid, apartID, avolID);
296 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
300 afs_int32 VolNukeVolume (acid, apartID, avolID)
301 struct rx_call *acid;
302 afs_int32 apartID, avolID;
307 register afs_int32 code;
309 char caller[MAXKTCNAMELEN];
311 /* check for access */
312 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
313 if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
315 tp = volutil_PartitionName(apartID);
316 if (!tp) return VOLSERNOVOL;
317 strcpy(partName, tp); /* remember it for later */
318 /* we first try to attach the volume in update mode, so that the file
319 * server doesn't try to use it (and abort) while (or after) we delete it.
320 * If we don't get the volume, that's fine, too. We just won't put it back.
322 tvp = XAttachVolume(&error, avolID, apartID, V_UPDATE);
323 code = nuke(partName, avolID);
324 if (tvp) VDetachVolume(&error, tvp);
328 /* create a new volume, with name aname, on the specified partition (1..n)
329 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
330 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
331 * for the volume id (useful for things like volume restore).
332 * Return the new volume id in *avolid.
334 afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
335 struct rx_call *acid;
345 code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
346 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans,
355 afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
356 struct rx_call *acid;
366 afs_int32 junk; /* discardable error code */
367 register afs_int32 volumeID, doCreateRoot=1;
368 register struct volser_trans *tt;
370 char caller[MAXKTCNAMELEN];
372 if (strlen(aname) > 31) return VOLSERBADNAME;
373 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
374 if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
375 if (error = ConvertPartition(apart, ppath, sizeof(ppath))) return error;/*a standard unix error*/
376 if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
378 if ((volumeID = *avolid) == 0) {
380 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
384 if ((aparent == volumeID) && (atype == readwriteVolume)) {
387 if (aparent == 0) aparent = volumeID;
388 tt = NewTrans(volumeID, apart);
390 Log("1 createvolume: failed to create trans\n");
391 return VOLSERVOLBUSY; /* volume already busy! */
393 vp = VCreateVolume(&error, ppath, volumeID, aparent);
395 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
400 V_uniquifier(vp) = 1;
401 V_creationDate(vp) = V_copyDate(vp);
402 V_inService(vp) = V_blessed(vp) = 1;
404 AssignVolumeName(&V_disk(vp), aname, 0);
407 V_destroyMe(vp) = DESTROY_ME;
409 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
410 VUpdateVolume(&error, vp);
412 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
415 VDetachVolume(&junk, vp); /* rather return the real error code */
420 strcpy(tt->lastProcName,"CreateVolume");
421 tt->rxCallPtr = acid;
422 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
423 tt->rxCallPtr = (struct rx_call *)0;
424 if(TRELE(tt)) return VOLSERTRELE_ERROR;
428 /* delete the volume associated with this transaction */
429 afs_int32 SAFSVolDeleteVolume (acid, atrans)
431 struct rx_call *acid;
435 code = VolDeleteVolume (acid, atrans);
436 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
440 afs_int32 VolDeleteVolume (acid, atrans)
442 struct rx_call *acid;
444 register struct volser_trans *tt;
446 char caller[MAXKTCNAMELEN];
448 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
449 tt = FindTrans(atrans);
450 if (!tt) return ENOENT;
451 if (tt->vflags & VTDeleted) {
452 Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
456 if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
457 strcpy(tt->lastProcName,"DeleteVolume");
458 tt->rxCallPtr = acid;
459 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
460 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
461 tt->rxCallPtr = (struct rx_call *)0;
462 if(TRELE(tt)) return VOLSERTRELE_ERROR;
464 Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
465 return 0; /* vpurgevolume doesn't set an error code */
468 /* make a clone of the volume associated with atrans, possibly giving it a new
469 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
470 * for the clone's id). The new clone is given the name newName. Finally, due to
471 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
472 * the clone operation. This may be useful when making new backup volumes, for instance
473 * since the net result of a clone and a purge generally leaves many inode ref counts
474 * the same, while doing them separately would result in far more iincs and idecs being
475 * peformed (and they are slow operations).
477 afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
478 struct rx_call *acid;
481 afs_int32 *newNumber;
482 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
487 code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
488 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans,
492 AUD_LONG, *newNumber, AUD_END);
496 afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
497 struct rx_call *acid;
500 afs_int32 *newNumber;
501 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
505 register struct Volume *originalvp, *purgevp, *newvp;
507 register struct volser_trans *tt,*ttc;
508 char caller[MAXKTCNAMELEN];
510 if (strlen(newName)>31) return VOLSERBADNAME;
511 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
512 if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
514 originalvp = (Volume *) 0;
515 purgevp = (Volume *) 0;
516 newvp = (Volume *) 0;
517 tt = ttc = (struct volser_trans *) 0;
519 if (!newNumber || !*newNumber)
521 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
526 if (newType != readonlyVolume && newType != backupVolume)
528 tt = FindTrans(atrans);
529 if (!tt) return ENOENT;
530 if (tt->vflags & VTDeleted) {
531 Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
535 ttc = NewTrans(newId,tt->partition);
537 { /* someone is messing with the clone already */
541 strcpy(tt->lastProcName,"Clone");
542 tt->rxCallPtr = acid;
546 purgevp = VAttachVolume(&error, purgeId, V_UPDATE);
548 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
553 purgevp = (struct Volume *) 0;
555 originalvp = tt->volume;
556 if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
557 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
561 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
562 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
568 if (originalvp->device != purgevp->device) {
569 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
573 if (V_type(purgevp) != readonlyVolume) {
574 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
578 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
579 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
583 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
584 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
593 newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
595 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
596 newvp = (Volume *) 0;
599 if (newType == readonlyVolume)
600 V_cloneId(originalvp) = newId;
601 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
603 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
604 CloneVolume(&error, originalvp, newvp, purgevp);
605 purgevp = (struct Volume *) 0; /* clone releases it, maybe even if error */
607 Log("1 Volser: Clone: clone operation failed with code %d\n", error);
611 if (newType == readonlyVolume) {
612 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
613 V_type(newvp) = readonlyVolume;
615 else if (newType == backupVolume) {
616 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
617 V_type(newvp) = backupVolume;
618 V_backupId(originalvp) = newId;
620 strcpy(newvp->header->diskstuff.name,newName);
621 V_creationDate(newvp) = V_copyDate(newvp);
622 ClearVolumeStats(&V_disk(newvp));
623 V_destroyMe(newvp) = DESTROY_ME;
624 V_inService(newvp) = 0;
626 VUpdateVolume(&error, newvp);
628 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
632 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
633 newvp = (struct Volume *) 0;
634 VUpdateVolume(&error, originalvp);
636 Log("1 Volser: Clone: original update %d\n", error);
640 tt->rxCallPtr = (struct rx_call *)0;
642 tt = (struct volser_trans *) 0;
643 error = VOLSERTRELE_ERROR;
650 if (purgevp) VDetachVolume(&code, purgevp);
651 if (newvp) VDetachVolume(&code, newvp);
653 tt->rxCallPtr = (struct rx_call *)0;
656 if(ttc) DeleteTrans(ttc);
660 /* reclone this volume into the specified id */
661 afs_int32 SAFSVolReClone (acid, atrans, cloneId)
662 struct rx_call *acid;
668 code = VolReClone (acid, atrans, cloneId);
669 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
673 afs_int32 VolReClone (acid, atrans, cloneId)
674 struct rx_call *acid;
678 register struct Volume *originalvp, *clonevp;
681 register struct volser_trans *tt,*ttc;
682 char caller[MAXKTCNAMELEN];
685 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
686 if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
688 clonevp = originalvp = (Volume *) 0;
689 tt = (struct volser_trans *) 0;
691 tt = FindTrans(atrans);
692 if (!tt) return ENOENT;
693 if (tt->vflags & VTDeleted) {
694 Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
698 ttc = NewTrans(cloneId, tt->partition);
699 if (!ttc){ /* someone is messing with the clone already */
703 strcpy(tt->lastProcName,"ReClone");
704 tt->rxCallPtr = acid;
706 originalvp = tt->volume;
707 if ((V_type(originalvp) == backupVolume) ||
708 (V_type(originalvp) == readonlyVolume)){
709 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
713 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
714 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
720 clonevp = VAttachVolume(&error, cloneId, V_UPDATE);
722 Log("1 Volser: can't attach clone %d\n", cloneId);
726 newType = V_type(clonevp); /* type of the new volume */
728 if (originalvp->device != clonevp->device) {
729 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
733 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
734 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
738 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
739 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
743 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
744 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
751 Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
753 CloneVolume(&error, originalvp, clonevp, clonevp);
755 Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
760 /* fix up volume name and type, CloneVolume just propagated RW's */
761 if (newType == readonlyVolume) {
762 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
763 V_type(clonevp) = readonlyVolume;
765 else if (newType == backupVolume) {
766 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
767 V_type(clonevp) = backupVolume;
768 V_backupId(originalvp) = cloneId;
770 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
772 /* pretend recloned volume is a totally new instance */
773 V_copyDate(clonevp) = time(0);
774 V_creationDate(clonevp) = V_copyDate(clonevp);
775 ClearVolumeStats(&V_disk(clonevp));
776 V_destroyMe(clonevp) = 0;
777 V_inService(clonevp) = 0;
778 V_inUse(clonevp) = 0;
779 VUpdateVolume(&error, clonevp);
781 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
785 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
786 clonevp = (struct Volume *) 0;
787 VUpdateVolume(&error, originalvp);
789 Log("1 Volser: Clone: original update %d\n", error);
793 tt->rxCallPtr = (struct rx_call *)0;
795 tt = (struct volser_trans *) 0;
796 error = VOLSERTRELE_ERROR;
803 struct DiskPartition *tpartp = originalvp->partition;
804 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
809 if (clonevp) VDetachVolume(&code, clonevp);
811 tt->rxCallPtr = (struct rx_call *)0;
814 if(ttc) DeleteTrans(ttc);
818 /* create a new transaction, associated with volume and partition. Type of
819 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
820 * See volser.h for definition of iflags (the constants are named IT*).
822 afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
823 struct rx_call *acid;
831 code = VolTransCreate (acid, volume, partition, iflags, ttid);
832 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
836 afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
837 struct rx_call *acid;
843 register struct volser_trans *tt;
845 afs_int32 error, code;
847 char caller[MAXKTCNAMELEN];
849 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
850 if (iflags & ITCreate) mode = V_SECRETLY;
851 else if (iflags & ITBusy) mode = V_CLONE;
852 else if (iflags & ITReadOnly) mode = V_READONLY;
853 else if (iflags & ITOffline) mode = V_UPDATE;
855 Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
859 tt = NewTrans(volume, partition);
861 /* can't create a transaction? put the volume back */
862 Log("1 transcreate: can't create transaction\n");
863 return VOLSERVOLBUSY;
865 tv = XAttachVolume(&error, volume, partition, mode);
868 if (tv) VDetachVolume(&code, tv);
876 strcpy(tt->lastProcName,"TransCreate");
877 if(TRELE(tt)) return VOLSERTRELE_ERROR;
882 /* using aindex as a 0-based index, return the aindex'th volume on this server
883 * Both the volume number and partition number (one-based) are returned.
885 afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
886 struct rx_call *acid;
893 code = VolGetNthVolume (acid, aindex, avolume, apart);
894 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
898 afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
899 struct rx_call *acid;
904 Log("1 Volser: GetNthVolume: Not yet implemented\n");
908 /* return the volume flags (VT* constants in volser.h) associated with this
911 afs_int32 SAFSVolGetFlags (acid, atid, aflags)
912 struct rx_call *acid;
918 code = VolGetFlags (acid, atid, aflags);
919 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
923 afs_int32 VolGetFlags (acid, atid, aflags)
924 struct rx_call *acid;
928 register struct volser_trans *tt;
930 tt = FindTrans(atid);
931 if (!tt) return ENOENT;
932 if (tt->vflags & VTDeleted) {
933 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
937 strcpy(tt->lastProcName,"GetFlags");
938 tt->rxCallPtr = acid;
939 *aflags = tt->vflags;
940 tt->rxCallPtr = (struct rx_call *)0;
941 if(TRELE(tt)) return VOLSERTRELE_ERROR;
946 /* Change the volume flags (VT* constants in volser.h) associated with this
947 * transaction. Effects take place immediately on volume, although volume
948 * remains attached as usual by the transaction.
950 afs_int32 SAFSVolSetFlags (acid, atid, aflags)
951 struct rx_call *acid;
957 code = VolSetFlags (acid, atid, aflags);
958 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
962 afs_int32 VolSetFlags (acid, atid, aflags)
963 struct rx_call *acid;
967 register struct volser_trans *tt;
968 register struct Volume *vp;
970 char caller[MAXKTCNAMELEN];
972 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
974 tt = FindTrans(atid);
975 if (!tt) return ENOENT;
976 if (tt->vflags & VTDeleted) {
977 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
981 strcpy(tt->lastProcName,"SetFlags");
982 tt->rxCallPtr = acid;
983 vp = tt->volume; /* pull volume out of transaction */
985 /* check if we're allowed to make any updates */
986 if (tt->iflags & ITReadOnly) {
991 /* handle delete-on-salvage flag */
992 if (aflags & VTDeleteOnSalvage) {
993 V_destroyMe(tt->volume) = DESTROY_ME;
996 V_destroyMe(tt->volume) = 0;
999 if (aflags & VTOutOfService) {
1000 V_inService(vp) = 0;
1003 V_inService(vp) = 1;
1005 VUpdateVolume(&error, vp);
1006 tt->vflags = aflags;
1007 tt->rxCallPtr = (struct rx_call *)0;
1008 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
1013 /* dumpS the volume associated with a particular transaction from a particular
1014 * date. Send the dump to a different transaction (destTrans) on the server
1015 * specified by the destServer structure.
1017 afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1018 struct rx_call *acid;
1019 afs_int32 fromTrans;
1021 struct destServer *destination;
1022 struct restoreCookie *cookie;
1023 afs_int32 destTrans;
1027 code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
1028 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans,
1029 AUD_HOST, destination->destHost,
1030 AUD_LONG, destTrans, AUD_END);
1034 afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1035 struct rx_call *acid;
1036 afs_int32 fromTrans;
1038 struct destServer *destination;
1039 struct restoreCookie *cookie;
1040 afs_int32 destTrans;
1042 register struct volser_trans *tt;
1043 register afs_int32 code;
1044 register struct rx_connection *tcon;
1045 struct rx_call *tcall;
1046 register struct Volume *vp;
1047 struct rx_securityClass *securityObject;
1048 afs_int32 securityIndex;
1049 char caller[MAXKTCNAMELEN];
1051 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1052 /* initialize things */
1053 tcon = (struct rx_connection *) 0;
1054 tt = (struct volser_trans *) 0;
1056 /* find the local transaction */
1057 tt = FindTrans(fromTrans);
1058 if (!tt) return ENOENT;
1059 if (tt->vflags & VTDeleted) {
1060 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1065 strcpy(tt->lastProcName,"Forward");
1067 /* get auth info for the this connection (uses afs from ticket file) */
1068 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1074 /* make an rpc connection to the other server */
1075 tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
1077 tt->rxCallPtr = (struct rx_call *)0;
1081 tcall = rx_NewCall(tcon);
1082 tt->rxCallPtr = tcall;
1083 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1084 code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
1089 /* these next calls implictly call rx_Write when writing out data */
1090 code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
1091 if (code) goto fail;
1092 EndAFSVolRestore(tcall); /* probably doesn't do much */
1093 tt->rxCallPtr = (struct rx_call *)0;
1094 code = rx_EndCall(tcall, 0);
1095 rx_DestroyConnection(tcon); /* done with the connection */
1097 if (code) goto fail;
1098 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1104 rx_EndCall(tcall,0);
1105 rx_DestroyConnection(tcon);
1108 tt->rxCallPtr = (struct rx_call *)0;
1114 /* Start a dump and send it to multiple places simultaneously.
1115 * If this returns an error (eg, return ENOENT), it means that
1116 * none of the releases worked. If this returns 0, that means
1117 * that one or more of the releases worked, and the caller has
1118 * to examine the results array to see which one(s).
1119 * This will only do EITHER incremental or full, not both, so it's
1120 * the caller's responsibility to be sure that all the destinations
1121 * need just an incremental (and from the same time), if that's
1124 afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations,
1125 spare, cookie, results)
1126 struct rx_call *acid;
1127 afs_int32 fromTrans;
1130 manyDests *destinations;
1131 struct restoreCookie *cookie;
1132 manyResults *results;
1134 afs_int32 securityIndex;
1135 struct rx_securityClass *securityObject;
1136 char caller[MAXKTCNAMELEN];
1137 struct volser_trans *tt;
1138 afs_int32 ec, code, *codes;
1139 struct rx_connection **tcons;
1140 struct rx_call **tcalls;
1142 int i, nconns, is_incremental;
1145 bzero(results, sizeof(manyResults));
1147 if (!afsconf_SuperUser(tdir, acid, caller))
1148 return VOLSERBAD_ACCESS;/*not a super user*/
1149 tt = FindTrans(fromTrans);
1152 if (tt->vflags & VTDeleted) {
1153 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1158 strcpy(tt->lastProcName, "ForwardMulti");
1160 /* (fromDate == 0) ==> incremental dump */
1161 is_incremental = (fromDate ? 1 : 0);
1163 i= results->manyResults_len = destinations->manyDests_len;
1164 results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
1165 tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
1166 tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
1168 /* get auth info for this connection (uses afs from ticket file) */
1169 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1171 goto fail; /* in order to audit each failure */
1174 /* make connections to all the other servers */
1175 for (i=0; i < destinations->manyDests_len; i++) {
1176 struct replica *dest = &(destinations->manyDests_val[i]);
1177 tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
1178 htons(dest->server.destPort),
1179 VOLSERVICE_ID, securityObject, securityIndex);
1181 codes[i] = ENOTCONN;
1184 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1187 codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
1188 is_incremental,cookie);
1190 rx_EndCall (tcalls[i],0); tcalls[i] = 0;
1191 rx_DestroyConnection(tcons[i]); tcons[i] = 0;
1197 /* these next calls implictly call rx_Write when writing out data */
1198 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1202 for (i--; i >=0 ; i--) {
1203 struct replica *dest = &(destinations->manyDests_val[i]);
1205 if (!code && tcalls[i] && !codes[i]) {
1206 EndAFSVolRestore(tcalls[i]);
1209 ec = rx_EndCall(tcalls[i], 0);
1210 if (!codes[i]) codes[i] = ec;
1213 rx_DestroyConnection(tcons[i]); /* done with the connection */
1216 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]),
1217 AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost,
1218 AUD_LONG, dest->trans, AUD_END);
1224 tt->rxCallPtr = (struct rx_call *)0;
1225 if(TRELE(tt) && !code) /* return the first code if it's set */
1226 return VOLSERTRELE_ERROR;
1232 afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
1233 struct rx_call *acid;
1234 afs_int32 fromTrans;
1239 code = VolDump (acid, fromTrans, fromDate);
1240 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1244 afs_int32 VolDump (acid, fromTrans, fromDate)
1245 struct rx_call *acid;
1246 afs_int32 fromTrans;
1250 register struct volser_trans *tt;
1251 char caller[MAXKTCNAMELEN];
1253 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1254 tt = FindTrans(fromTrans);
1255 if (!tt) return ENOENT;
1256 if (tt->vflags & VTDeleted) {
1257 Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
1261 strcpy(tt->lastProcName,"Dump");
1262 tt->rxCallPtr = acid;
1263 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1264 if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
1265 tt->rxCallPtr = (struct rx_call *)0;
1267 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1273 * Ha! No more helper process!
1275 afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
1276 struct rx_call *acid;
1279 struct restoreCookie *cookie;
1283 code = VolRestore (acid, atrans, aflags,cookie);
1284 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1288 afs_int32 VolRestore (acid, atrans, aflags,cookie)
1289 struct rx_call *acid;
1292 struct restoreCookie *cookie;
1294 register struct volser_trans *tt;
1295 register afs_int32 code,tcode;
1296 char caller[MAXKTCNAMELEN];
1298 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1299 tt = FindTrans(atrans);
1300 if (!tt) return ENOENT;
1301 if (tt->vflags & VTDeleted) {
1302 Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
1306 strcpy(tt->lastProcName,"Restore");
1307 tt->rxCallPtr = acid;
1308 code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie); /* last is incrementalp */
1309 FSYNC_askfs(tt->volid, (char *) 0, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
1311 tt->rxCallPtr = (struct rx_call *)0;
1314 return (code? code : tcode);
1317 /* end a transaction, returning the transaction's final error code in rcode */
1318 afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
1319 struct rx_call *acid;
1320 afs_int32 destTrans;
1325 code = VolEndTrans (acid, destTrans, rcode);
1326 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1330 afs_int32 VolEndTrans (acid, destTrans, rcode)
1331 struct rx_call *acid;
1332 afs_int32 destTrans;
1335 register struct volser_trans *tt;
1336 char caller[MAXKTCNAMELEN];
1338 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1339 tt = FindTrans(destTrans);
1340 if (!tt) {return ENOENT;}
1341 *rcode = tt->returnCode;
1342 DeleteTrans(tt); /* this does an implicit TRELE */
1347 afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
1348 struct rx_call *acid;
1354 code = VolSetForwarding (acid, atid, anewsite);
1355 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
1359 afs_int32 VolSetForwarding (acid, atid, anewsite)
1360 struct rx_call *acid;
1365 register struct volser_trans *tt;
1366 char caller[MAXKTCNAMELEN];
1368 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1369 tt = FindTrans(atid);
1370 if (!tt) return ENOENT;
1371 if (tt->vflags & VTDeleted) {
1372 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
1376 strcpy(tt->lastProcName,"SetForwarding");
1377 tt->rxCallPtr = acid;
1378 FSYNC_askfs(tt->volid, (char *) 0, FSYNC_MOVEVOLUME, anewsite);
1379 tt->rxCallPtr = (struct rx_call *)0;
1380 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1385 afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
1386 struct rx_call *acid;
1388 register struct volser_status *astatus;
1392 code = VolGetStatus (acid, atrans, astatus);
1393 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1397 afs_int32 VolGetStatus (acid, atrans, astatus)
1398 struct rx_call *acid;
1400 register struct volser_status *astatus;
1402 register struct Volume *tv;
1403 register struct VolumeDiskData *td;
1404 struct volser_trans *tt;
1407 tt = FindTrans(atrans);
1408 if (!tt) return ENOENT;
1409 if (tt->vflags & VTDeleted) {
1410 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
1414 strcpy(tt->lastProcName,"GetStatus");
1415 tt->rxCallPtr = acid;
1418 tt->rxCallPtr = (struct rx_call *)0;
1423 td = &tv->header->diskstuff;
1424 astatus->volID = td->id;
1425 astatus->nextUnique = td->uniquifier;
1426 astatus->type = td->type;
1427 astatus->parentID = td->parentId;
1428 astatus->cloneID = td->cloneId;
1429 astatus->backupID = td->backupId;
1430 astatus->restoredFromID = td->restoredFromId;
1431 astatus->maxQuota = td->maxquota;
1432 astatus->minQuota = td->minquota;
1433 astatus->owner = td->owner;
1434 astatus->creationDate = td->creationDate;
1435 astatus->accessDate = td->accessDate;
1436 astatus->updateDate = td->updateDate;
1437 astatus->expirationDate = td->expirationDate;
1438 astatus->backupDate = td->backupDate;
1439 astatus->copyDate = td->copyDate;
1440 tt->rxCallPtr = (struct rx_call *)0;
1441 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1446 afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
1447 struct rx_call *acid;
1449 register struct volintInfo *astatus;
1453 code = VolSetInfo (acid, atrans, astatus);
1454 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1458 afs_int32 VolSetInfo (acid, atrans, astatus)
1459 struct rx_call *acid;
1461 register struct volintInfo *astatus;
1463 register struct Volume *tv;
1464 register struct VolumeDiskData *td;
1465 struct volser_trans *tt;
1466 char caller[MAXKTCNAMELEN];
1469 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1470 tt = FindTrans(atrans);
1471 if (!tt) return ENOENT;
1472 if (tt->vflags & VTDeleted) {
1473 Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
1477 strcpy(tt->lastProcName,"SetStatus");
1478 tt->rxCallPtr = acid;
1481 tt->rxCallPtr = (struct rx_call *)0;
1486 td = &tv->header->diskstuff;
1488 * Add more fields as necessary
1490 if (astatus->maxquota != -1)
1491 td->maxquota = astatus->maxquota;
1492 if (astatus->dayUse != -1)
1493 td->dayUse = astatus->dayUse;
1494 VUpdateVolume(&error, tv);
1495 tt->rxCallPtr = (struct rx_call *)0;
1496 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1501 afs_int32 SAFSVolGetName (acid, atrans, aname)
1502 struct rx_call *acid;
1508 code = VolGetName (acid, atrans, aname);
1509 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1513 afs_int32 VolGetName (acid, atrans, aname)
1514 struct rx_call *acid;
1518 register struct Volume *tv;
1519 register struct VolumeDiskData *td;
1520 struct volser_trans *tt;
1524 tt = FindTrans(atrans);
1525 if (!tt) return ENOENT;
1526 if (tt->vflags & VTDeleted) {
1527 Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
1531 strcpy(tt->lastProcName,"GetName");
1532 tt->rxCallPtr = acid;
1535 tt->rxCallPtr = (struct rx_call *)0;
1540 td = &tv->header->diskstuff;
1541 len = strlen(td->name)+1; /* don't forget the null */
1543 tt->rxCallPtr = (struct rx_call *)0;
1547 *aname = (char *)malloc(len);
1548 strcpy(*aname, td->name);
1549 tt->rxCallPtr = (struct rx_call *)0;
1550 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1554 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1556 afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
1557 struct rx_call *acid;
1559 afs_int32 parentId, cloneId;
1566 /*return a list of all partitions on the server. The non mounted
1567 *partitions are returned as -1 in the corresponding slot in partIds*/
1568 afs_int32 SAFSVolListPartitions (acid, partIds)
1569 struct rx_call *acid;
1570 struct pIDs *partIds;
1574 code = VolListPartitions (acid, partIds);
1575 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1579 afs_int32 VolListPartitions (acid, partIds)
1580 struct rx_call *acid;
1581 struct pIDs *partIds;
1583 struct stat rbuf, pbuf;
1588 /* Just return attached partitions. */
1589 strcpy(namehead, "/vicep");
1591 for (i=0; i<26; i++) {
1592 namehead[6] = i + 'a';
1593 if (VGetPartition(namehead, 0))
1594 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1597 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1598 code = stat("/",&rbuf); /*interested in buf->st_dev*/
1601 for(i = 0 ; i < 26 ; i++){
1603 namehead[6] = i + 'a';
1605 code = stat(namehead,&pbuf);
1607 if(rbuf.st_dev != pbuf.st_dev) /*the partition is mounted */
1608 partIds->partIds[i] = i ;
1609 else partIds->partIds[i ] = -1;
1611 else partIds->partIds[i ] = -1;
1619 /*return a list of all partitions on the server. The non mounted
1620 *partitions are returned as -1 in the corresponding slot in partIds*/
1621 afs_int32 SAFSVolXListPartitions (acid, pEntries)
1622 struct rx_call *acid;
1623 struct partEntries *pEntries;
1627 code = XVolListPartitions (acid, pEntries);
1628 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1632 afs_int32 XVolListPartitions (acid, pEntries)
1633 struct rx_call *acid;
1634 struct partEntries *pEntries;
1636 struct stat rbuf, pbuf;
1638 struct partList partList;
1639 int code, i, j=0, k;
1641 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1643 for(i = 0 ; i < VOLMAXPARTS; i++){
1645 namehead[6] = i + 'a';
1649 namehead[6] = 'a' + (k/26);
1650 namehead[7] = 'a' + (k%26);
1653 code = VGetPartition(namehead, 0);
1655 partList.partId[j++] = i;
1657 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1658 bcopy((char *)&partList, (char *)pEntries->partEntries_val, j * sizeof(int));
1659 pEntries->partEntries_len = j;
1661 code = stat("/",&rbuf); /*interested in buf->st_dev*/
1662 for(i = 0 ; i < VOLMAXPARTS; i++){
1664 namehead[6] = i + 'a';
1668 namehead[6] = 'a' + (k/26);
1669 namehead[7] = 'a' + (k%26);
1672 code = stat(namehead,&pbuf);
1674 if(rbuf.st_dev != pbuf.st_dev) /*the partition is mounted */
1675 partList.partId[j++] = i;
1678 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1679 bcopy((char *)&partList, (char *)pEntries->partEntries_val, j * sizeof(int));
1680 pEntries->partEntries_len = j;
1686 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1687 afs_int32 ExtractVolId(vname)
1691 char name[VOLSER_MAXVOLNAME +1];
1695 while(name[i] == 'V' || name[i] == '0')
1698 name[11] = '\0'; /* smash the "." */
1699 return(atol(&name[i]));
1702 /*return the name of the next volume header in the directory associated with dirp and dp.
1703 *the volume id is returned in volid, and volume header name is returned in volname*/
1704 GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
1708 dp = readdir(dirp);/*read next entry in the directory */
1711 if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
1712 *volid = ExtractVolId(dp->d_name);
1713 strcpy(volname,dp->d_name);
1714 return 0;/*return the name of the file representing a volume */
1718 return 0;/*volname doesnot represent a volume*/
1721 else {strcpy(volname,"EOD"); return 0;/*end of directory */}
1725 /*return the header information about the <volid> */
1726 afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
1727 struct rx_call *acid;
1728 afs_int32 volumeId, partid;
1729 volEntries *volumeInfo;
1733 code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
1734 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1738 afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
1739 struct rx_call *acid;
1740 afs_int32 volumeId, partid;
1741 volEntries *volumeInfo;
1743 register struct Volume *tv;
1744 struct DiskPartition *partP;
1745 struct volser_trans *ttc;
1746 char pname[9], volname[20];
1747 afs_int32 error = 0;
1753 volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
1754 pntr = volumeInfo->volEntries_val;
1755 volumeInfo->volEntries_len = 1;
1756 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
1757 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1758 dirp = opendir(VPartitionPath(partP));
1759 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
1761 ttc = (struct volser_trans *) 0;
1762 tv = (Volume *) 0; /* volume not attached */
1764 while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
1766 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
1767 GetNextVol(dirp, volname, &volid);
1768 continue; /*back to while loop */
1771 if(volid == volumeId) { /*copy other things too */
1773 IOMGR_Poll(); /*make sure that the client doesnot time out*/
1774 ttc = NewTrans(volid,partid);
1776 pntr->status = VBUSY;
1777 pntr->volid = volid;
1780 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
1782 pntr->status = 0; /*things are messed up */
1783 strcpy(pntr->name,volname);
1784 pntr->volid = volid;
1785 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
1788 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
1789 /*this volume will be salvaged */
1791 strcpy(pntr->name,volname);
1792 pntr->volid = volid;
1793 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
1797 if(tv->header->diskstuff.needsSalvaged){
1798 /*this volume will be salvaged */
1800 strcpy(pntr->name,volname);
1801 pntr->volid = volid;
1802 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
1806 /*read in the relevant info */
1807 pntr->status = VOK ; /*its ok */
1808 pntr->volid = tv->header->diskstuff.id;
1809 strcpy(pntr->name,tv->header->diskstuff.name);
1810 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
1811 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
1812 pntr->backupID = tv->header->diskstuff.backupId;
1813 pntr->parentID = tv->header->diskstuff.parentId;
1814 pntr->copyDate = tv->header->diskstuff.copyDate;
1815 pntr->inUse = tv->header->diskstuff.inUse;
1816 pntr->size = tv->header->diskstuff.diskused;
1817 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1818 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1819 pntr->maxquota = tv->header->diskstuff.maxquota;
1820 pntr->filecount = tv->header->diskstuff.filecount;
1821 now = FT_ApproxTime();
1822 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1825 pntr->dayUse = tv->header->diskstuff.dayUse;
1826 pntr->creationDate = tv->header->diskstuff.creationDate;
1827 pntr->accessDate = tv->header->diskstuff.accessDate;
1828 pntr->updateDate = tv->header->diskstuff.updateDate;
1829 pntr->backupDate = tv->header->diskstuff.backupDate;
1830 pntr->spare0 = tv->header->diskstuff.minquota;
1831 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
1832 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
1833 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
1834 (long) tv->header->diskstuff.weekUse[6];
1835 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
1836 VDetachVolume(&error,tv);/*free the volume */
1839 pntr->status = 0; /*things are messed up */
1840 strcpy(pntr->name,volname);
1841 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
1845 GetNextVol(dirp, volname, &volid);
1849 VDetachVolume(&error, tv);
1854 ttc = (struct volser_trans *) 0;
1862 /*------------------------------------------------------------------------
1863 * EXPORTED SAFSVolXListOneVolume
1866 * Returns extended info on volume a_volID on partition a_partID.
1869 * a_rxCidP : Pointer to the Rx call we're performing.
1870 * a_partID : Partition for which we want the extended list.
1871 * a_volID : Volume ID we wish to know about.
1872 * a_volumeXInfoP : Ptr to the extended info blob.
1875 * 0 Successful operation
1876 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1879 * Nothing interesting.
1883 *------------------------------------------------------------------------*/
1885 afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1886 struct rx_call *a_rxCidP;
1889 volXEntries *a_volumeXInfoP;
1893 code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1894 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1898 afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1899 struct rx_call *a_rxCidP;
1902 volXEntries *a_volumeXInfoP;
1904 { /*SAFSVolXListOneVolume*/
1906 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
1907 register struct Volume *tv; /*Volume ptr*/
1908 struct volser_trans *ttc; /*Volume transaction ptr*/
1909 struct DiskPartition *partP; /*Ptr to partition */
1910 char pname[9], volname[20]; /*Partition, volume names*/
1911 afs_int32 error; /*Error code*/
1912 afs_int32 code; /*Return code*/
1913 DIR *dirp; /*Partition directory ptr*/
1914 afs_int32 currVolID; /*Current volume ID*/
1915 int found = 0; /*Did we find the volume we need?*/
1916 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
1917 int numStatBytes; /*Num stat bytes to copy per volume*/
1921 * Set up our pointers for action, marking our structure to hold exactly
1922 * one entry. Also, assume we'll fail in our quest.
1924 a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
1925 xInfoP = a_volumeXInfoP->volXEntries_val;
1926 a_volumeXInfoP->volXEntries_len = 1;
1930 * If the partition name we've been given is bad, bogue out.
1932 if (GetPartName(a_partID, pname))
1933 return(VOLSERILLEGAL_PARTITION);
1936 * Open the directory representing the given AFS parttion. If we can't
1939 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1940 dirp = opendir(VPartitionPath(partP));
1942 return(VOLSERILLEGAL_PARTITION);
1945 * Sweep through the partition directory, looking for the desired entry.
1946 * First, of course, figure out how many stat bytes to copy out of each
1949 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
1950 (4*VOLINT_STATS_NUM_TIME_FIELDS));
1951 strcpy(volname, "");
1952 ttc = (struct volser_trans *)0; /*No transaction yet*/
1953 tv = (Volume *)0; /*Volume not yet attached*/
1955 while (strcmp(volname,"EOD") && !found) {
1957 * If this is not a volume, move on to the next entry in the
1958 * partition's directory.
1960 if (!strcmp(volname,"")) {
1961 GetNextVol(dirp, volname, &currVolID);
1965 if (currVolID == a_volID) {
1967 * We found the volume entry we're interested. Pull out the
1968 * extended information, remembering to poll (so that the client
1969 * doesn't time out) and to set up a transaction on the volume.
1973 ttc = NewTrans(currVolID, a_partID);
1976 * Couldn't get a transaction on this volume; let our caller
1979 xInfoP->status = VBUSY;
1980 xInfoP->volid = currVolID;
1985 * Attach the volume, give up on the volume if we can't.
1987 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1989 xInfoP->status = 0; /*things are messed up */
1990 strcpy(xInfoP->name, volname);
1991 xInfoP->volid = currVolID;
1992 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
1998 * Also bag out on this volume if it's been marked as needing a
1999 * salvage or to-be-destroyed.
2001 volDiskDataP = &(tv->header->diskstuff);
2002 if (volDiskDataP->destroyMe == DESTROY_ME) {
2004 strcpy(xInfoP->name, volname);
2005 xInfoP->volid = currVolID;
2006 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
2010 if (volDiskDataP->needsSalvaged) {
2012 strcpy(xInfoP->name, volname);
2013 xInfoP->volid = currVolID;
2014 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
2020 * Pull out the desired info and stuff it into the area we'll be
2021 * returning to our caller.
2023 strcpy(xInfoP->name,volDiskDataP->name);
2024 xInfoP->volid = volDiskDataP->id;
2025 xInfoP->type = volDiskDataP->type;
2026 xInfoP->backupID = volDiskDataP->backupId;
2027 xInfoP->parentID = volDiskDataP->parentId;
2028 xInfoP->cloneID = volDiskDataP->cloneId;
2029 xInfoP->status = VOK;
2030 xInfoP->copyDate = volDiskDataP->copyDate;
2031 xInfoP->inUse = volDiskDataP->inUse;
2032 xInfoP->creationDate = volDiskDataP->creationDate;
2033 xInfoP->accessDate = volDiskDataP->accessDate;
2034 xInfoP->updateDate = volDiskDataP->updateDate;
2035 xInfoP->backupDate = volDiskDataP->backupDate;
2036 now = FT_ApproxTime();
2037 if (now - volDiskDataP->dayUseDate > OneDay)
2040 xInfoP->dayUse = volDiskDataP->dayUse;
2041 xInfoP->filecount = volDiskDataP->filecount;
2042 xInfoP->maxquota = volDiskDataP->maxquota;
2043 xInfoP->size = volDiskDataP->diskused;
2046 * Copy out the stat fields in a single operation.
2048 bcopy((char *)&(volDiskDataP->stat_reads[0]),
2049 (char *)&(xInfoP->stat_reads[0]),
2053 * We're done copying. Detach the volume and iterate (at this
2054 * point, since we found our volume, we'll then drop out of the
2057 VDetachVolume(&error, tv);
2061 strcpy(xInfoP->name, volname);
2062 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2068 * At this point, we're golden.
2071 } /*Found desired volume*/
2072 GetNextVol(dirp, volname, &currVolID);
2076 * Drop the transaction we have for this volume.
2080 VDetachVolume(&error, tv);
2085 ttc = (struct volser_trans *)0;
2089 * Clean up before going to dinner: close the partition directory,
2090 * return the proper value.
2095 } /*SAFSVolXListOneVolume*/
2097 /*returns all the volumes on partition partid. If flags = 1 then all the
2098 * relevant info about the volumes is also returned */
2099 afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
2100 struct rx_call *acid;
2101 afs_int32 flags, partid;
2102 volEntries *volumeInfo;
2106 code = VolListVolumes (acid, partid, flags, volumeInfo);
2107 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2111 afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
2112 struct rx_call *acid;
2113 afs_int32 flags, partid;
2114 volEntries *volumeInfo;
2116 register struct Volume *tv;
2117 struct DiskPartition *partP;
2118 struct volser_trans *ttc;
2119 afs_int32 allocSize = 1000;/*to be changed to a larger figure */
2120 char pname[9], volname[20];
2121 afs_int32 error = 0;
2126 volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2127 pntr = volumeInfo->volEntries_val;
2128 volumeInfo->volEntries_len = 0;
2129 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
2130 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2131 dirp = opendir(VPartitionPath(partP));
2132 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2134 while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
2135 ttc = (struct volser_trans *) 0; /* new one for each pass */
2136 tv = (Volume *) 0; /* volume not attached */
2138 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
2139 GetNextVol(dirp, volname, &volid);
2140 continue; /*back to while loop */
2143 if(flags) { /*copy other things too */
2144 IOMGR_Poll(); /*make sure that the client doesnot time out*/
2145 ttc = NewTrans(volid,partid);
2147 pntr->status = VBUSY;
2148 pntr->volid = volid;
2151 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
2153 pntr->status = 0; /*things are messed up */
2154 strcpy(pntr->name,volname);
2155 pntr->volid = volid;
2156 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
2159 if(tv->header->diskstuff.needsSalvaged){
2160 /*this volume will be salvaged */
2162 strcpy(pntr->name,volname);
2163 pntr->volid = volid;
2164 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
2168 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
2169 /*this volume will be salvaged */
2172 /*read in the relevant info */
2173 pntr->status = VOK ; /*its ok */
2174 pntr->volid = tv->header->diskstuff.id;
2175 strcpy(pntr->name,tv->header->diskstuff.name);
2176 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
2177 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
2178 pntr->backupID = tv->header->diskstuff.backupId;
2179 pntr->parentID = tv->header->diskstuff.parentId;
2180 pntr->copyDate = tv->header->diskstuff.copyDate;
2181 pntr->inUse = tv->header->diskstuff.inUse;
2182 pntr->size = tv->header->diskstuff.diskused;
2183 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2184 pntr->maxquota = tv->header->diskstuff.maxquota;
2185 pntr->filecount = tv->header->diskstuff.filecount;
2186 now = FT_ApproxTime();
2187 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2190 pntr->dayUse = tv->header->diskstuff.dayUse;
2191 pntr->creationDate = tv->header->diskstuff.creationDate;
2192 pntr->accessDate = tv->header->diskstuff.accessDate;
2193 pntr->updateDate = tv->header->diskstuff.updateDate;
2194 pntr->backupDate = tv->header->diskstuff.backupDate;
2195 pntr->spare0 = tv->header->diskstuff.minquota;
2196 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
2197 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
2198 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
2199 (long) tv->header->diskstuff.weekUse[6];
2200 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
2201 VDetachVolume(&error,tv);/*free the volume */
2204 pntr->status = 0; /*things are messed up */
2205 strcpy(pntr->name,volname);
2206 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
2210 pntr->volid = volid;
2211 /*just volids are needed*/
2217 ttc = (struct volser_trans *) 0;
2220 volumeInfo->volEntries_len += 1;
2221 if((allocSize - volumeInfo->volEntries_len) < 5) {
2222 /*running out of space, allocate more space */
2223 allocSize = (allocSize *3)/2;
2224 pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
2225 allocSize * sizeof(volintInfo));
2228 VDetachVolume(&error, tv);
2233 ttc = (struct volser_trans *) 0;
2236 return VOLSERNO_MEMORY;
2238 volumeInfo->volEntries_val = pntr; /* point to new block */
2239 /* set pntr to the right position */
2240 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2246 VDetachVolume(&error, tv);
2251 ttc = (struct volser_trans *) 0;
2253 GetNextVol(dirp, volname, &volid);
2263 /*------------------------------------------------------------------------
2264 * EXPORTED SAFSVolXListVolumes
2267 * Returns all the volumes on partition a_partID. If a_flags
2268 * is set to 1, then all the relevant extended volume information
2272 * a_rxCidP : Pointer to the Rx call we're performing.
2273 * a_partID : Partition for which we want the extended list.
2274 * a_flags : Various flags.
2275 * a_volumeXInfoP : Ptr to the extended info blob.
2278 * 0 Successful operation
2279 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2280 * VOLSERNO_MEMORY if we ran out of memory allocating
2284 * Nothing interesting.
2288 *------------------------------------------------------------------------*/
2290 afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2291 struct rx_call *a_rxCidP;
2294 volXEntries *a_volumeXInfoP;
2298 code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2299 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2303 afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2304 struct rx_call *a_rxCidP;
2307 volXEntries *a_volumeXInfoP;
2309 { /*SAFSVolXListVolumes*/
2311 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
2312 register struct Volume *tv; /*Volume ptr*/
2313 struct DiskPartition *partP; /*Ptr to partition*/
2314 struct volser_trans *ttc; /*Volume transaction ptr*/
2315 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2316 char pname[9], volname[20]; /*Partition, volume names*/
2317 afs_int32 error = 0; /*Return code*/
2318 DIR *dirp; /*Partition directory ptr*/
2319 afs_int32 volid; /*Current volume ID*/
2320 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
2321 int numStatBytes; /*Num stat bytes to copy per volume*/
2325 * Allocate a large array of extended volume info structures, then
2326 * set it up for action.
2328 a_volumeXInfoP->volXEntries_val =
2329 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2330 xInfoP = a_volumeXInfoP->volXEntries_val;
2331 a_volumeXInfoP->volXEntries_len = 0;
2334 * If the partition name we've been given is bad, bogue out.
2336 if (GetPartName(a_partID, pname))
2337 return(VOLSERILLEGAL_PARTITION);
2340 * Open the directory representing the given AFS parttion. If we can't
2343 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2344 dirp = opendir(VPartitionPath(partP));
2346 return (VOLSERILLEGAL_PARTITION);
2349 * Sweep through the partition directory, acting on each entry. First,
2350 * of course, figure out how many stat bytes to copy out of each volume.
2352 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
2353 (4*VOLINT_STATS_NUM_TIME_FIELDS));
2355 while (strcmp(volname, "EOD")) {
2356 ttc = (struct volser_trans *)0; /*New one for each pass*/
2357 tv = (Volume *)0; /*Volume not yet attached*/
2360 * If this is not a volume, move on to the next entry in the
2361 * partition's directory.
2363 if(!strcmp(volname,"")) {
2364 GetNextVol(dirp, volname, &volid);
2370 * Full info about the volume desired. Poll to make sure the
2371 * client doesn't time out, then start up a new transaction.
2374 ttc = NewTrans(volid,a_partID);
2377 * Couldn't get a transaction on this volume; let our caller
2380 xInfoP->status = VBUSY;
2381 xInfoP->volid = volid;
2386 * Attach the volume, give up on this volume if we can't.
2388 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2390 xInfoP->status = 0; /*things are messed up */
2391 strcpy(xInfoP->name, volname);
2392 xInfoP->volid = volid;
2393 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2399 * Also bag out on this volume if it's been marked as needing a
2400 * salvage or to-be-destroyed.
2402 volDiskDataP = &(tv->header->diskstuff);
2403 if (volDiskDataP->needsSalvaged) {
2405 strcpy(xInfoP->name, volname);
2406 xInfoP->volid = volid;
2407 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
2412 if (volDiskDataP->destroyMe == DESTROY_ME)
2416 * Pull out the desired info and stuff it into the area we'll be
2417 * returning to our caller.
2419 strcpy(xInfoP->name,volDiskDataP->name);
2420 xInfoP->volid = volDiskDataP->id;
2421 xInfoP->type = volDiskDataP->type;
2422 xInfoP->backupID = volDiskDataP->backupId;
2423 xInfoP->parentID = volDiskDataP->parentId;
2424 xInfoP->cloneID = volDiskDataP->cloneId;
2425 xInfoP->status = VOK;
2426 xInfoP->copyDate = volDiskDataP->copyDate;
2427 xInfoP->inUse = volDiskDataP->inUse;
2428 xInfoP->creationDate = volDiskDataP->creationDate;
2429 xInfoP->accessDate = volDiskDataP->accessDate;
2430 xInfoP->updateDate = volDiskDataP->updateDate;
2431 xInfoP->backupDate = volDiskDataP->backupDate;
2432 now = FT_ApproxTime();
2433 if (now - volDiskDataP->dayUseDate > OneDay)
2436 xInfoP->dayUse = volDiskDataP->dayUse;
2437 xInfoP->filecount = volDiskDataP->filecount;
2438 xInfoP->maxquota = volDiskDataP->maxquota;
2439 xInfoP->size = volDiskDataP->diskused;
2442 * Copy out the stat fields in a single operation.
2444 bcopy((char *)&(volDiskDataP->stat_reads[0]),
2445 (char *)&(xInfoP->stat_reads[0]),
2449 * We're done copying. Detach the volume and iterate.
2451 VDetachVolume(&error, tv);
2455 strcpy(xInfoP->name, volname);
2456 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2460 } /*Full contents desired*/
2463 * Just volume IDs are needed.
2465 xInfoP->volid = volid;
2469 * Drop the transaction we have for this volume.
2473 ttc = (struct volser_trans *) 0;
2477 * Bump the pointer in the data area we're building, along with
2478 * the count of the number of entries it contains.
2481 (a_volumeXInfoP->volXEntries_len)++;
2482 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2484 * We're running out of space in the area we've built. Grow it.
2486 allocSize = (allocSize * 3)/2;
2487 xInfoP = (volintXInfo *)
2488 realloc((char *) a_volumeXInfoP->volXEntries_val,
2489 (allocSize * sizeof(volintXInfo)));
2490 if (xInfoP == NULL) {
2492 * Bummer, no memory. Bag it, tell our caller what went wrong.
2495 VDetachVolume(&error, tv);
2500 ttc = (struct volser_trans *) 0;
2503 return(VOLSERNO_MEMORY);
2507 * Memory reallocation worked. Correct our pointers so they
2508 * now point to the new block and the current open position within
2511 a_volumeXInfoP->volXEntries_val = xInfoP;
2512 xInfoP = a_volumeXInfoP->volXEntries_val +
2513 a_volumeXInfoP->volXEntries_len;
2514 } /*Need more space*/
2518 * Detach our current volume and the transaction on it, then move on
2519 * to the next volume in the partition directory.
2522 VDetachVolume(&error, tv);
2527 ttc = (struct volser_trans *) 0;
2529 GetNextVol(dirp, volname, &volid);
2530 } /*Sweep through the partition directory*/
2533 * We've examined all entries in the partition directory. Close it,
2534 * delete our transaction (if any), and go home happy.
2541 } /*SAFSVolXListVolumes*/
2543 /*this call is used to monitor the status of volser for debugging purposes.
2544 *information about all the active transactions is returned in transInfo*/
2545 afs_int32 SAFSVolMonitor (acid,transInfo)
2546 struct rx_call *acid;
2547 transDebugEntries *transInfo;
2551 code = VolMonitor (acid,transInfo);
2552 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2556 afs_int32 VolMonitor (acid,transInfo)
2557 struct rx_call *acid;
2558 transDebugEntries *transInfo;
2560 transDebugInfo *pntr;
2561 afs_int32 allocSize = 50;
2562 struct volser_trans *tt, *allTrans;
2564 transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2565 pntr = transInfo->transDebugEntries_val;
2566 transInfo->transDebugEntries_len = 0;
2567 allTrans = TransList();
2568 if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
2569 for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
2570 pntr->tid = tt->tid;
2571 pntr->time = tt->time;
2572 pntr->creationTime = tt->creationTime;
2573 pntr->returnCode = tt->returnCode;
2574 pntr->volid = tt->volid;
2575 pntr->partition = tt->partition;
2576 pntr->iflags = tt->iflags;
2577 pntr->vflags = tt->vflags;
2578 pntr->tflags = tt->tflags;
2579 strcpy(pntr->lastProcName,tt->lastProcName);
2580 pntr->callValid = 0;
2581 if(tt->rxCallPtr) { /*record call related info */
2582 pntr->callValid = 1;
2583 pntr->readNext = tt->rxCallPtr->rnext;
2584 pntr->transmitNext = tt->rxCallPtr->tnext;
2585 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2586 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2589 transInfo->transDebugEntries_len += 1;
2590 if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
2591 allocSize = (allocSize *3)/2;
2592 pntr = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
2593 transInfo->transDebugEntries_val = pntr;
2594 pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
2595 /*set pntr to right position*/
2603 afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2604 struct rx_call *acid;
2605 afs_int32 type, pId, cloneId, backupId, atid;
2610 code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
2611 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid,
2616 AUD_LONG, backupId, AUD_END);
2620 afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2621 struct rx_call *acid;
2622 afs_int32 type, pId, cloneId, backupId, atid;
2626 afs_int32 error = 0;
2627 register struct volser_trans *tt;
2628 char caller[MAXKTCNAMELEN];
2630 if (strlen(name)>31) return VOLSERBADNAME;
2631 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2632 /* find the trans */
2633 tt = FindTrans(atid);
2634 if (!tt) return ENOENT;
2635 if (tt->vflags & VTDeleted) {
2636 Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
2640 strcpy(tt->lastProcName,"SetIdsTypes");
2641 tt->rxCallPtr = acid;
2645 V_backupId(tv) = backupId;
2646 V_cloneId(tv) = cloneId;
2647 V_parentId(tv) = pId;
2648 strcpy((&V_disk(tv))->name,name);
2649 VUpdateVolume(&error, tv);
2651 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2655 tt->rxCallPtr = (struct rx_call *)0;
2656 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2660 tt->rxCallPtr = (struct rx_call *)0;
2661 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2665 afs_int32 SAFSVolSetDate (acid,atid,cdate)
2666 struct rx_call *acid;
2667 afs_int32 atid, cdate;
2671 code = VolSetDate (acid,atid,cdate);
2672 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
2676 afs_int32 VolSetDate (acid,atid,cdate)
2677 struct rx_call *acid;
2678 afs_int32 atid, cdate;
2681 afs_int32 error = 0;
2682 register struct volser_trans *tt;
2683 char caller[MAXKTCNAMELEN];
2685 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2686 /* find the trans */
2687 tt = FindTrans(atid);
2688 if (!tt) return ENOENT;
2689 if (tt->vflags & VTDeleted) {
2690 Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
2694 strcpy(tt->lastProcName,"SetDate");
2695 tt->rxCallPtr = acid;
2698 V_creationDate(tv) = cdate;
2699 VUpdateVolume(&error, tv);
2701 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2705 tt->rxCallPtr = (struct rx_call *)0;
2706 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2710 tt->rxCallPtr = (struct rx_call *)0;
2711 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2715 /* GetPartName - map partid (a decimal number) into pname (a string)
2716 * Since for NT we actually want to return the drive name, we map through the
2719 static int GetPartName(afs_int32 partid, char *pname)
2724 strcpy(pname,"/vicep");
2725 pname[6] = 'a' + partid;
2728 } else if (partid < VOLMAXPARTS) {
2729 strcpy(pname,"/vicep");
2731 pname[6] = 'a' + (partid / 26);
2732 pname[7] = 'a' + (partid % 26);