2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
23 #include <netinet/in.h>
40 #include <afs/afsint.h>
42 #include <afs/assert.h>
43 #include <afs/prs_fs.h>
48 #include <afs/cellconfig.h>
51 #include <afs/ihandle.h>
53 #include <afs/ntops.h>
55 #include <afs/vnode.h>
56 #include <afs/volume.h>
57 #include <afs/partition.h>
59 #include <afs/fssync.h>
61 #include "afs/audit.h"
66 extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
67 extern struct afsconf_dir *tdir;
68 extern char *volutil_PartitionName();
70 /* Forward declarations */
71 static int GetPartName(afs_int32 partid, char *pname);
73 #define OneDay (24*60*60)
80 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
81 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
82 afs_int32 VolForwardMultiple();
83 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
84 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
85 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
87 /* this call unlocks all of the partition locks we've set */
89 register struct DiskPartition *tp;
90 for(tp = DiskPartitionList; tp; tp = tp->next) {
91 if (tp->lock_fd != -1) {
92 close(tp->lock_fd); /* releases flock held on this partition */
99 /* get partition id from a name */
100 afs_int32 PartitionID(aname)
103 register int code = 0;
107 if (tc == 0) return -1; /* unknown */
109 /* otherwise check for vicepa or /vicepa, or just plain "a" */
111 if (!strncmp(aname, "/vicep", 6)) {
112 strncpy(ascii, aname+6, 2);
114 else return -1; /* bad partition name */
115 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
116 from 0. Do the appropriate conversion */
118 /* one char name, 0..25 */
119 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
120 return ascii[0] - 'a';
123 /* two char name, 26 .. <whatever> */
124 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
125 if (ascii[1] < 'a' || ascii[1] > 'z') return -1; /* just as bad */
126 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
127 if (code > VOLMAXPARTS) return -1;
132 static int ConvertVolume(avol, aname, asize)
136 if (asize < 18) return -1;
137 /* 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 */
138 sprintf(aname, VFORMAT, avol);
142 static int ConvertPartition(apartno, aname, asize)
146 if (asize < 10) return E2BIG;
147 if (apartno < 0) return EINVAL;
148 strcpy(aname, "/vicep");
150 aname[6] = 'a'+apartno;
155 aname[6] = 'a' + (apartno / 26);
156 aname[7] = 'a' + (apartno % 26);
162 /* the only attach function that takes a partition is "...ByName", so we use it */
163 struct Volume *XAttachVolume(error, avolid, apartid, amode)
168 char pbuf[30], vbuf[20];
169 register struct Volume *tv;
171 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
175 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
179 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
183 /* Adapted from the file server; create a root directory for this volume */
184 static ViceCreateRoot(vp)
188 struct acl_accessList * ACL;
190 Inode inodeNumber, nearInode;
191 char buf[SIZEOF_LARGEDISKVNODE];
192 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
193 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
199 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
201 V_pref(vp, nearInode);
202 inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
203 VPartitionPath(V_partition(vp)), nearInode,
204 V_parentId(vp), 1, 1, 0);
205 assert(VALID_INO(inodeNumber));
207 SetSalvageDirHandle(&dir, V_id(vp), vp->device, inodeNumber);
208 did.Volume = V_id(vp);
209 did.Vnode = (VnodeId)1;
212 assert(!(MakeDir(&dir, &did, &did)));
213 DFlush(); /* flush all modified dir buffers out */
214 DZap(&dir); /* Remove all buffers for this dir */
215 length = Length(&dir); /* Remember size of this directory */
217 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
219 /* build a single entry ACL that gives all rights to system:administrators */
220 /* this section of code assumes that access list format is not going to
223 ACL = VVnodeDiskACL(vnode);
224 ACL->size = sizeof(struct acl_accessList);
225 ACL->version = ACL_ACLVERSION;
229 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
230 ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
232 vnode->type = vDirectory;
234 vnode->modeBits = 0777;
235 vnode->linkCount = 2;
236 vnode->length = length;
237 vnode->uniquifier = 1;
238 V_uniquifier(vp) = vnode->uniquifier+1;
239 vnode->dataVersion = 1;
240 VNDISK_SET_INO(vnode, inodeNumber);
241 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
245 vnode->vnodeMagic = vcp->magic;
247 IH_INIT(h, vp->device, V_parentId(vp),
248 vp->vnodeIndex[vLarge].handle->ih_ino);
251 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
253 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
254 assert(code == SIZEOF_LARGEDISKVNODE);
255 FDH_REALLYCLOSE(fdP);
257 V_diskused(vp) = nBlocks(vnode->length);
262 afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
263 struct rx_call *acid;
265 struct diskPartition *partition;
269 code = VolPartitionInfo (acid,pname,partition);
270 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
274 afs_int32 VolPartitionInfo (acid,pname,partition)
275 struct rx_call *acid;
277 struct diskPartition *partition;
279 register struct DiskPartition *dp;
282 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
285 dp = VGetPartition(pname, 0);
287 strncpy(partition->name,dp->name,32);
288 strncpy(partition->devName,dp->devName,32);
289 partition->lock_fd = dp->lock_fd ;
290 partition->free = dp->free;
291 partition->minFree = dp->totalUsable;
295 return VOLSERILLEGAL_PARTITION;
298 /* obliterate a volume completely, and slowly. */
299 afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
300 struct rx_call *acid;
301 afs_int32 apartID, avolID;
305 code = VolNukeVolume (acid, apartID, avolID);
306 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
310 afs_int32 VolNukeVolume (acid, apartID, avolID)
311 struct rx_call *acid;
312 afs_int32 apartID, avolID;
317 register afs_int32 code;
319 char caller[MAXKTCNAMELEN];
321 /* check for access */
322 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
323 if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
325 tp = volutil_PartitionName(apartID);
326 if (!tp) return VOLSERNOVOL;
327 strcpy(partName, tp); /* remember it for later */
328 /* we first try to attach the volume in update mode, so that the file
329 * server doesn't try to use it (and abort) while (or after) we delete it.
330 * If we don't get the volume, that's fine, too. We just won't put it back.
332 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
333 code = nuke(partName, avolID);
334 if (tvp) VDetachVolume(&error, tvp);
338 /* create a new volume, with name aname, on the specified partition (1..n)
339 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
340 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
341 * for the volume id (useful for things like volume restore).
342 * Return the new volume id in *avolid.
344 afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
345 struct rx_call *acid;
355 code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
356 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans,
365 afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
366 struct rx_call *acid;
376 afs_int32 junk; /* discardable error code */
377 register afs_int32 volumeID, doCreateRoot=1;
378 register struct volser_trans *tt;
380 char caller[MAXKTCNAMELEN];
382 if (strlen(aname) > 31) return VOLSERBADNAME;
383 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
384 if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
385 if (error = ConvertPartition(apart, ppath, sizeof(ppath))) return error;/*a standard unix error*/
386 if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
388 if ((volumeID = *avolid) == 0) {
390 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
394 if ((aparent == volumeID) && (atype == readwriteVolume)) {
397 if (aparent == 0) aparent = volumeID;
398 tt = NewTrans(volumeID, apart);
400 Log("1 createvolume: failed to create trans\n");
401 return VOLSERVOLBUSY; /* volume already busy! */
403 vp = VCreateVolume(&error, ppath, volumeID, aparent);
405 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
410 V_uniquifier(vp) = 1;
411 V_creationDate(vp) = V_copyDate(vp);
412 V_inService(vp) = V_blessed(vp) = 1;
414 AssignVolumeName(&V_disk(vp), aname, 0);
417 V_destroyMe(vp) = DESTROY_ME;
419 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
420 VUpdateVolume(&error, vp);
422 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
425 VDetachVolume(&junk, vp); /* rather return the real error code */
430 strcpy(tt->lastProcName,"CreateVolume");
431 tt->rxCallPtr = acid;
432 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
433 tt->rxCallPtr = (struct rx_call *)0;
434 if(TRELE(tt)) return VOLSERTRELE_ERROR;
438 /* delete the volume associated with this transaction */
439 afs_int32 SAFSVolDeleteVolume (acid, atrans)
441 struct rx_call *acid;
445 code = VolDeleteVolume (acid, atrans);
446 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
450 afs_int32 VolDeleteVolume (acid, atrans)
452 struct rx_call *acid;
454 register struct volser_trans *tt;
456 char caller[MAXKTCNAMELEN];
458 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
459 tt = FindTrans(atrans);
460 if (!tt) return ENOENT;
461 if (tt->vflags & VTDeleted) {
462 Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
466 if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
467 strcpy(tt->lastProcName,"DeleteVolume");
468 tt->rxCallPtr = acid;
469 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
470 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
471 tt->rxCallPtr = (struct rx_call *)0;
472 if(TRELE(tt)) return VOLSERTRELE_ERROR;
474 Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
475 return 0; /* vpurgevolume doesn't set an error code */
478 /* make a clone of the volume associated with atrans, possibly giving it a new
479 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
480 * for the clone's id). The new clone is given the name newName. Finally, due to
481 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
482 * the clone operation. This may be useful when making new backup volumes, for instance
483 * since the net result of a clone and a purge generally leaves many inode ref counts
484 * the same, while doing them separately would result in far more iincs and idecs being
485 * peformed (and they are slow operations).
487 afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
488 struct rx_call *acid;
491 afs_int32 *newNumber;
492 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
497 code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
498 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans,
502 AUD_LONG, *newNumber, AUD_END);
506 afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
507 struct rx_call *acid;
510 afs_int32 *newNumber;
511 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
515 register struct Volume *originalvp, *purgevp, *newvp;
517 register struct volser_trans *tt,*ttc;
518 char caller[MAXKTCNAMELEN];
520 if (strlen(newName)>31) return VOLSERBADNAME;
521 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
522 if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
524 originalvp = (Volume *) 0;
525 purgevp = (Volume *) 0;
526 newvp = (Volume *) 0;
527 tt = ttc = (struct volser_trans *) 0;
529 if (!newNumber || !*newNumber)
531 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
536 if (newType != readonlyVolume && newType != backupVolume)
538 tt = FindTrans(atrans);
539 if (!tt) return ENOENT;
540 if (tt->vflags & VTDeleted) {
541 Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
545 ttc = NewTrans(newId,tt->partition);
547 { /* someone is messing with the clone already */
551 strcpy(tt->lastProcName,"Clone");
552 tt->rxCallPtr = acid;
556 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
558 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
565 originalvp = tt->volume;
566 if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
567 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
571 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
572 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
578 if (originalvp->device != purgevp->device) {
579 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
583 if (V_type(purgevp) != readonlyVolume) {
584 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
588 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
589 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
593 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
594 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
603 newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
605 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
606 newvp = (Volume *) 0;
609 if (newType == readonlyVolume)
610 V_cloneId(originalvp) = newId;
611 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
613 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
614 CloneVolume(&error, originalvp, newvp, purgevp);
615 purgevp = NULL; /* clone releases it, maybe even if error */
617 Log("1 Volser: Clone: clone operation failed with code %d\n", error);
621 if (newType == readonlyVolume) {
622 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
623 V_type(newvp) = readonlyVolume;
625 else if (newType == backupVolume) {
626 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
627 V_type(newvp) = backupVolume;
628 V_backupId(originalvp) = newId;
630 strcpy(newvp->header->diskstuff.name,newName);
631 V_creationDate(newvp) = V_copyDate(newvp);
632 ClearVolumeStats(&V_disk(newvp));
633 V_destroyMe(newvp) = DESTROY_ME;
634 V_inService(newvp) = 0;
635 if (newType == backupVolume) {
636 V_backupDate(originalvp) = V_copyDate(newvp);
637 V_backupDate(newvp) = V_copyDate(newvp);
640 VUpdateVolume(&error, newvp);
642 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
646 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
648 VUpdateVolume(&error, originalvp);
650 Log("1 Volser: Clone: original update %d\n", error);
654 tt->rxCallPtr = (struct rx_call *)0;
656 tt = (struct volser_trans *) 0;
657 error = VOLSERTRELE_ERROR;
664 if (purgevp) VDetachVolume(&code, purgevp);
665 if (newvp) VDetachVolume(&code, newvp);
667 tt->rxCallPtr = (struct rx_call *)0;
670 if(ttc) DeleteTrans(ttc);
674 /* reclone this volume into the specified id */
675 afs_int32 SAFSVolReClone (acid, atrans, cloneId)
676 struct rx_call *acid;
682 code = VolReClone (acid, atrans, cloneId);
683 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
687 afs_int32 VolReClone (acid, atrans, cloneId)
688 struct rx_call *acid;
692 register struct Volume *originalvp, *clonevp;
695 register struct volser_trans *tt,*ttc;
696 char caller[MAXKTCNAMELEN];
699 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
700 if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
702 clonevp = originalvp = (Volume *) 0;
703 tt = (struct volser_trans *) 0;
705 tt = FindTrans(atrans);
706 if (!tt) return ENOENT;
707 if (tt->vflags & VTDeleted) {
708 Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
712 ttc = NewTrans(cloneId, tt->partition);
713 if (!ttc){ /* someone is messing with the clone already */
717 strcpy(tt->lastProcName,"ReClone");
718 tt->rxCallPtr = acid;
720 originalvp = tt->volume;
721 if ((V_type(originalvp) == backupVolume) ||
722 (V_type(originalvp) == readonlyVolume)){
723 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
727 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
728 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
734 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
736 Log("1 Volser: can't attach clone %d\n", cloneId);
740 newType = V_type(clonevp); /* type of the new volume */
742 if (originalvp->device != clonevp->device) {
743 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
747 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
748 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
752 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
753 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
757 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
758 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
765 Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
767 CloneVolume(&error, originalvp, clonevp, clonevp);
769 Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
774 /* fix up volume name and type, CloneVolume just propagated RW's */
775 if (newType == readonlyVolume) {
776 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
777 V_type(clonevp) = readonlyVolume;
779 else if (newType == backupVolume) {
780 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
781 V_type(clonevp) = backupVolume;
782 V_backupId(originalvp) = cloneId;
784 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
786 /* pretend recloned volume is a totally new instance */
787 V_copyDate(clonevp) = time(0);
788 V_creationDate(clonevp) = V_copyDate(clonevp);
789 ClearVolumeStats(&V_disk(clonevp));
790 V_destroyMe(clonevp) = 0;
791 V_inService(clonevp) = 0;
792 if (newType == backupVolume) {
793 V_backupDate(originalvp) = V_copyDate(clonevp);
794 V_backupDate(clonevp) = V_copyDate(clonevp);
796 V_inUse(clonevp) = 0;
797 VUpdateVolume(&error, clonevp);
799 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
803 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
805 VUpdateVolume(&error, originalvp);
807 Log("1 Volser: Clone: original update %d\n", error);
811 tt->rxCallPtr = (struct rx_call *)0;
813 tt = (struct volser_trans *) 0;
814 error = VOLSERTRELE_ERROR;
821 struct DiskPartition *tpartp = originalvp->partition;
822 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
827 if (clonevp) VDetachVolume(&code, clonevp);
829 tt->rxCallPtr = (struct rx_call *)0;
832 if(ttc) DeleteTrans(ttc);
836 /* create a new transaction, associated with volume and partition. Type of
837 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
838 * See volser.h for definition of iflags (the constants are named IT*).
840 afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
841 struct rx_call *acid;
849 code = VolTransCreate (acid, volume, partition, iflags, ttid);
850 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
854 afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
855 struct rx_call *acid;
861 register struct volser_trans *tt;
863 afs_int32 error, code;
865 char caller[MAXKTCNAMELEN];
867 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
868 if (iflags & ITCreate) mode = V_SECRETLY;
869 else if (iflags & ITBusy) mode = V_CLONE;
870 else if (iflags & ITReadOnly) mode = V_READONLY;
871 else if (iflags & ITOffline) mode = V_VOLUPD;
873 Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
877 tt = NewTrans(volume, partition);
879 /* can't create a transaction? put the volume back */
880 Log("1 transcreate: can't create transaction\n");
881 return VOLSERVOLBUSY;
883 tv = XAttachVolume(&error, volume, partition, mode);
886 if (tv) VDetachVolume(&code, tv);
894 strcpy(tt->lastProcName,"TransCreate");
895 if(TRELE(tt)) return VOLSERTRELE_ERROR;
900 /* using aindex as a 0-based index, return the aindex'th volume on this server
901 * Both the volume number and partition number (one-based) are returned.
903 afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
904 struct rx_call *acid;
911 code = VolGetNthVolume (acid, aindex, avolume, apart);
912 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
916 afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
917 struct rx_call *acid;
922 Log("1 Volser: GetNthVolume: Not yet implemented\n");
926 /* return the volume flags (VT* constants in volser.h) associated with this
929 afs_int32 SAFSVolGetFlags (acid, atid, aflags)
930 struct rx_call *acid;
936 code = VolGetFlags (acid, atid, aflags);
937 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
941 afs_int32 VolGetFlags (acid, atid, aflags)
942 struct rx_call *acid;
946 register struct volser_trans *tt;
948 tt = FindTrans(atid);
949 if (!tt) return ENOENT;
950 if (tt->vflags & VTDeleted) {
951 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
955 strcpy(tt->lastProcName,"GetFlags");
956 tt->rxCallPtr = acid;
957 *aflags = tt->vflags;
958 tt->rxCallPtr = (struct rx_call *)0;
959 if(TRELE(tt)) return VOLSERTRELE_ERROR;
964 /* Change the volume flags (VT* constants in volser.h) associated with this
965 * transaction. Effects take place immediately on volume, although volume
966 * remains attached as usual by the transaction.
968 afs_int32 SAFSVolSetFlags (acid, atid, aflags)
969 struct rx_call *acid;
975 code = VolSetFlags (acid, atid, aflags);
976 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
980 afs_int32 VolSetFlags (acid, atid, aflags)
981 struct rx_call *acid;
985 register struct volser_trans *tt;
986 register struct Volume *vp;
988 char caller[MAXKTCNAMELEN];
990 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
992 tt = FindTrans(atid);
993 if (!tt) return ENOENT;
994 if (tt->vflags & VTDeleted) {
995 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
999 strcpy(tt->lastProcName,"SetFlags");
1000 tt->rxCallPtr = acid;
1001 vp = tt->volume; /* pull volume out of transaction */
1003 /* check if we're allowed to make any updates */
1004 if (tt->iflags & ITReadOnly) {
1009 /* handle delete-on-salvage flag */
1010 if (aflags & VTDeleteOnSalvage) {
1011 V_destroyMe(tt->volume) = DESTROY_ME;
1014 V_destroyMe(tt->volume) = 0;
1017 if (aflags & VTOutOfService) {
1018 V_inService(vp) = 0;
1021 V_inService(vp) = 1;
1023 VUpdateVolume(&error, vp);
1024 tt->vflags = aflags;
1025 tt->rxCallPtr = (struct rx_call *)0;
1026 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
1031 /* dumpS the volume associated with a particular transaction from a particular
1032 * date. Send the dump to a different transaction (destTrans) on the server
1033 * specified by the destServer structure.
1035 afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1036 struct rx_call *acid;
1037 afs_int32 fromTrans;
1039 struct destServer *destination;
1040 struct restoreCookie *cookie;
1041 afs_int32 destTrans;
1045 code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
1046 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans,
1047 AUD_HOST, destination->destHost,
1048 AUD_LONG, destTrans, AUD_END);
1052 afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1053 struct rx_call *acid;
1054 afs_int32 fromTrans;
1056 struct destServer *destination;
1057 struct restoreCookie *cookie;
1058 afs_int32 destTrans;
1060 register struct volser_trans *tt;
1061 register afs_int32 code;
1062 register struct rx_connection *tcon;
1063 struct rx_call *tcall;
1064 register struct Volume *vp;
1065 struct rx_securityClass *securityObject;
1066 afs_int32 securityIndex;
1067 char caller[MAXKTCNAMELEN];
1069 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1070 /* initialize things */
1071 tcon = (struct rx_connection *) 0;
1072 tt = (struct volser_trans *) 0;
1074 /* find the local transaction */
1075 tt = FindTrans(fromTrans);
1076 if (!tt) return ENOENT;
1077 if (tt->vflags & VTDeleted) {
1078 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1083 strcpy(tt->lastProcName,"Forward");
1085 /* get auth info for the this connection (uses afs from ticket file) */
1086 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1092 /* make an rpc connection to the other server */
1093 tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
1095 tt->rxCallPtr = (struct rx_call *)0;
1099 tcall = rx_NewCall(tcon);
1100 tt->rxCallPtr = tcall;
1101 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1102 code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
1107 /* these next calls implictly call rx_Write when writing out data */
1108 code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
1109 if (code) goto fail;
1110 EndAFSVolRestore(tcall); /* probably doesn't do much */
1111 tt->rxCallPtr = (struct rx_call *)0;
1112 code = rx_EndCall(tcall, 0);
1113 rx_DestroyConnection(tcon); /* done with the connection */
1115 if (code) goto fail;
1116 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1122 rx_EndCall(tcall,0);
1123 rx_DestroyConnection(tcon);
1126 tt->rxCallPtr = (struct rx_call *)0;
1132 /* Start a dump and send it to multiple places simultaneously.
1133 * If this returns an error (eg, return ENOENT), it means that
1134 * none of the releases worked. If this returns 0, that means
1135 * that one or more of the releases worked, and the caller has
1136 * to examine the results array to see which one(s).
1137 * This will only do EITHER incremental or full, not both, so it's
1138 * the caller's responsibility to be sure that all the destinations
1139 * need just an incremental (and from the same time), if that's
1142 afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations,
1143 spare, cookie, results)
1144 struct rx_call *acid;
1145 afs_int32 fromTrans;
1148 manyDests *destinations;
1149 struct restoreCookie *cookie;
1150 manyResults *results;
1152 afs_int32 securityIndex;
1153 struct rx_securityClass *securityObject;
1154 char caller[MAXKTCNAMELEN];
1155 struct volser_trans *tt;
1156 afs_int32 ec, code, *codes;
1157 struct rx_connection **tcons;
1158 struct rx_call **tcalls;
1160 int i, nconns, is_incremental;
1163 memset(results, 0, sizeof(manyResults));
1165 if (!afsconf_SuperUser(tdir, acid, caller))
1166 return VOLSERBAD_ACCESS;/*not a super user*/
1167 tt = FindTrans(fromTrans);
1170 if (tt->vflags & VTDeleted) {
1171 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1176 strcpy(tt->lastProcName, "ForwardMulti");
1178 /* (fromDate == 0) ==> incremental dump */
1179 is_incremental = (fromDate ? 1 : 0);
1181 i= results->manyResults_len = destinations->manyDests_len;
1182 results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
1183 tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
1184 tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
1186 /* get auth info for this connection (uses afs from ticket file) */
1187 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1189 goto fail; /* in order to audit each failure */
1192 /* make connections to all the other servers */
1193 for (i=0; i < destinations->manyDests_len; i++) {
1194 struct replica *dest = &(destinations->manyDests_val[i]);
1195 tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
1196 htons(dest->server.destPort),
1197 VOLSERVICE_ID, securityObject, securityIndex);
1199 codes[i] = ENOTCONN;
1202 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1205 codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
1206 is_incremental,cookie);
1208 rx_EndCall (tcalls[i],0); tcalls[i] = 0;
1209 rx_DestroyConnection(tcons[i]); tcons[i] = 0;
1215 /* these next calls implictly call rx_Write when writing out data */
1216 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1220 for (i--; i >=0 ; i--) {
1221 struct replica *dest = &(destinations->manyDests_val[i]);
1223 if (!code && tcalls[i] && !codes[i]) {
1224 EndAFSVolRestore(tcalls[i]);
1227 ec = rx_EndCall(tcalls[i], 0);
1228 if (!codes[i]) codes[i] = ec;
1231 rx_DestroyConnection(tcons[i]); /* done with the connection */
1234 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]),
1235 AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost,
1236 AUD_LONG, dest->trans, AUD_END);
1242 tt->rxCallPtr = (struct rx_call *)0;
1243 if(TRELE(tt) && !code) /* return the first code if it's set */
1244 return VOLSERTRELE_ERROR;
1250 afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
1251 struct rx_call *acid;
1252 afs_int32 fromTrans;
1257 code = VolDump (acid, fromTrans, fromDate);
1258 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1262 afs_int32 VolDump (acid, fromTrans, fromDate)
1263 struct rx_call *acid;
1264 afs_int32 fromTrans;
1268 register struct volser_trans *tt;
1269 char caller[MAXKTCNAMELEN];
1271 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1272 tt = FindTrans(fromTrans);
1273 if (!tt) return ENOENT;
1274 if (tt->vflags & VTDeleted) {
1275 Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
1279 strcpy(tt->lastProcName,"Dump");
1280 tt->rxCallPtr = acid;
1281 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1282 if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
1283 tt->rxCallPtr = (struct rx_call *)0;
1285 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1291 * Ha! No more helper process!
1293 afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
1294 struct rx_call *acid;
1297 struct restoreCookie *cookie;
1301 code = VolRestore (acid, atrans, aflags,cookie);
1302 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1306 afs_int32 VolRestore (acid, atrans, aflags,cookie)
1307 struct rx_call *acid;
1310 struct restoreCookie *cookie;
1312 register struct volser_trans *tt;
1313 register afs_int32 code,tcode;
1314 char caller[MAXKTCNAMELEN];
1316 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1317 tt = FindTrans(atrans);
1318 if (!tt) return ENOENT;
1319 if (tt->vflags & VTDeleted) {
1320 Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
1324 strcpy(tt->lastProcName,"Restore");
1325 tt->rxCallPtr = acid;
1326 code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie); /* last is incrementalp */
1327 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
1329 tt->rxCallPtr = (struct rx_call *)0;
1332 return (code? code : tcode);
1335 /* end a transaction, returning the transaction's final error code in rcode */
1336 afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
1337 struct rx_call *acid;
1338 afs_int32 destTrans;
1343 code = VolEndTrans (acid, destTrans, rcode);
1344 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1348 afs_int32 VolEndTrans (acid, destTrans, rcode)
1349 struct rx_call *acid;
1350 afs_int32 destTrans;
1353 register struct volser_trans *tt;
1354 char caller[MAXKTCNAMELEN];
1356 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1357 tt = FindTrans(destTrans);
1358 if (!tt) {return ENOENT;}
1359 *rcode = tt->returnCode;
1360 DeleteTrans(tt); /* this does an implicit TRELE */
1365 afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
1366 struct rx_call *acid;
1372 code = VolSetForwarding (acid, atid, anewsite);
1373 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
1377 afs_int32 VolSetForwarding (acid, atid, anewsite)
1378 struct rx_call *acid;
1383 register struct volser_trans *tt;
1384 char caller[MAXKTCNAMELEN];
1386 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1387 tt = FindTrans(atid);
1388 if (!tt) return ENOENT;
1389 if (tt->vflags & VTDeleted) {
1390 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
1394 strcpy(tt->lastProcName,"SetForwarding");
1395 tt->rxCallPtr = acid;
1396 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1397 tt->rxCallPtr = (struct rx_call *)0;
1398 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1403 afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
1404 struct rx_call *acid;
1406 register struct volser_status *astatus;
1410 code = VolGetStatus (acid, atrans, astatus);
1411 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1415 afs_int32 VolGetStatus (acid, atrans, astatus)
1416 struct rx_call *acid;
1418 register struct volser_status *astatus;
1420 register struct Volume *tv;
1421 register struct VolumeDiskData *td;
1422 struct volser_trans *tt;
1425 tt = FindTrans(atrans);
1426 if (!tt) return ENOENT;
1427 if (tt->vflags & VTDeleted) {
1428 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
1432 strcpy(tt->lastProcName,"GetStatus");
1433 tt->rxCallPtr = acid;
1436 tt->rxCallPtr = (struct rx_call *)0;
1441 td = &tv->header->diskstuff;
1442 astatus->volID = td->id;
1443 astatus->nextUnique = td->uniquifier;
1444 astatus->type = td->type;
1445 astatus->parentID = td->parentId;
1446 astatus->cloneID = td->cloneId;
1447 astatus->backupID = td->backupId;
1448 astatus->restoredFromID = td->restoredFromId;
1449 astatus->maxQuota = td->maxquota;
1450 astatus->minQuota = td->minquota;
1451 astatus->owner = td->owner;
1452 astatus->creationDate = td->creationDate;
1453 astatus->accessDate = td->accessDate;
1454 astatus->updateDate = td->updateDate;
1455 astatus->expirationDate = td->expirationDate;
1456 astatus->backupDate = td->backupDate;
1457 astatus->copyDate = td->copyDate;
1458 tt->rxCallPtr = (struct rx_call *)0;
1459 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1464 afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
1465 struct rx_call *acid;
1467 register struct volintInfo *astatus;
1471 code = VolSetInfo (acid, atrans, astatus);
1472 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1476 afs_int32 VolSetInfo (acid, atrans, astatus)
1477 struct rx_call *acid;
1479 register struct volintInfo *astatus;
1481 register struct Volume *tv;
1482 register struct VolumeDiskData *td;
1483 struct volser_trans *tt;
1484 char caller[MAXKTCNAMELEN];
1487 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1488 tt = FindTrans(atrans);
1489 if (!tt) return ENOENT;
1490 if (tt->vflags & VTDeleted) {
1491 Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
1495 strcpy(tt->lastProcName,"SetStatus");
1496 tt->rxCallPtr = acid;
1499 tt->rxCallPtr = (struct rx_call *)0;
1504 td = &tv->header->diskstuff;
1506 * Add more fields as necessary
1508 if (astatus->maxquota != -1)
1509 td->maxquota = astatus->maxquota;
1510 if (astatus->dayUse != -1)
1511 td->dayUse = astatus->dayUse;
1512 VUpdateVolume(&error, tv);
1513 tt->rxCallPtr = (struct rx_call *)0;
1514 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1519 afs_int32 SAFSVolGetName (acid, atrans, aname)
1520 struct rx_call *acid;
1526 code = VolGetName (acid, atrans, aname);
1527 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1531 afs_int32 VolGetName (acid, atrans, aname)
1532 struct rx_call *acid;
1536 register struct Volume *tv;
1537 register struct VolumeDiskData *td;
1538 struct volser_trans *tt;
1542 tt = FindTrans(atrans);
1543 if (!tt) return ENOENT;
1544 if (tt->vflags & VTDeleted) {
1545 Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
1549 strcpy(tt->lastProcName,"GetName");
1550 tt->rxCallPtr = acid;
1553 tt->rxCallPtr = (struct rx_call *)0;
1558 td = &tv->header->diskstuff;
1559 len = strlen(td->name)+1; /* don't forget the null */
1561 tt->rxCallPtr = (struct rx_call *)0;
1565 *aname = (char *)malloc(len);
1566 strcpy(*aname, td->name);
1567 tt->rxCallPtr = (struct rx_call *)0;
1568 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1572 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1574 afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
1575 struct rx_call *acid;
1577 afs_int32 parentId, cloneId;
1584 /*return a list of all partitions on the server. The non mounted
1585 *partitions are returned as -1 in the corresponding slot in partIds*/
1586 afs_int32 SAFSVolListPartitions (acid, partIds)
1587 struct rx_call *acid;
1588 struct pIDs *partIds;
1592 code = VolListPartitions (acid, partIds);
1593 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1597 afs_int32 VolListPartitions (acid, partIds)
1598 struct rx_call *acid;
1599 struct pIDs *partIds;
1605 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1607 /* Just return attached partitions. */
1609 for (i=0; i<26; i++) {
1610 namehead[6] = i + 'a';
1611 if (VGetPartition(namehead, 0))
1612 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1618 /*return a list of all partitions on the server. The non mounted
1619 *partitions are returned as -1 in the corresponding slot in partIds*/
1620 afs_int32 SAFSVolXListPartitions (acid, pEntries)
1621 struct rx_call *acid;
1622 struct partEntries *pEntries;
1626 code = XVolListPartitions (acid, pEntries);
1627 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1631 afs_int32 XVolListPartitions (acid, pEntries)
1632 struct rx_call *acid;
1633 struct partEntries *pEntries;
1635 struct stat rbuf, pbuf;
1637 struct partList partList;
1638 struct DiskPartition *dp;
1641 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1643 /* Only report attached partitions */
1644 for(i = 0 ; i < VOLMAXPARTS; i++){
1646 namehead[6] = i + 'a';
1650 namehead[6] = 'a' + (k/26);
1651 namehead[7] = 'a' + (k%26);
1654 dp = VGetPartition(namehead, 0);
1656 partList.partId[j++] = i;
1658 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1659 memcpy((char *)pEntries->partEntries_val, (char *)&partList, j * sizeof(int));
1660 pEntries->partEntries_len = j;
1665 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1666 afs_int32 ExtractVolId(vname)
1670 char name[VOLSER_MAXVOLNAME +1];
1674 while(name[i] == 'V' || name[i] == '0')
1677 name[11] = '\0'; /* smash the "." */
1678 return(atol(&name[i]));
1681 /*return the name of the next volume header in the directory associated with dirp and dp.
1682 *the volume id is returned in volid, and volume header name is returned in volname*/
1683 GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
1687 dp = readdir(dirp);/*read next entry in the directory */
1690 if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
1691 *volid = ExtractVolId(dp->d_name);
1692 strcpy(volname,dp->d_name);
1693 return 0;/*return the name of the file representing a volume */
1697 return 0;/*volname doesnot represent a volume*/
1700 else {strcpy(volname,"EOD"); return 0;/*end of directory */}
1704 /*return the header information about the <volid> */
1705 afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
1706 struct rx_call *acid;
1707 afs_int32 volumeId, partid;
1708 volEntries *volumeInfo;
1712 code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
1713 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1717 afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
1718 struct rx_call *acid;
1719 afs_int32 volumeId, partid;
1720 volEntries *volumeInfo;
1722 register struct Volume *tv;
1723 struct DiskPartition *partP;
1724 struct volser_trans *ttc;
1725 char pname[9], volname[20];
1726 afs_int32 error = 0;
1732 volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
1733 pntr = volumeInfo->volEntries_val;
1734 volumeInfo->volEntries_len = 1;
1735 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
1736 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1737 dirp = opendir(VPartitionPath(partP));
1738 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
1740 ttc = (struct volser_trans *) 0;
1741 tv = (Volume *) 0; /* volume not attached */
1743 while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
1745 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
1746 GetNextVol(dirp, volname, &volid);
1747 continue; /*back to while loop */
1750 if(volid == volumeId) { /*copy other things too */
1752 IOMGR_Poll(); /*make sure that the client doesnot time out*/
1753 ttc = NewTrans(volid,partid);
1755 pntr->status = VBUSY;
1756 pntr->volid = volid;
1759 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
1761 pntr->status = 0; /*things are messed up */
1762 strcpy(pntr->name,volname);
1763 pntr->volid = volid;
1764 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
1767 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
1768 /*this volume will be salvaged */
1770 strcpy(pntr->name,volname);
1771 pntr->volid = volid;
1772 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
1776 if(tv->header->diskstuff.needsSalvaged){
1777 /*this volume will be salvaged */
1779 strcpy(pntr->name,volname);
1780 pntr->volid = volid;
1781 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
1785 /*read in the relevant info */
1786 pntr->status = VOK ; /*its ok */
1787 pntr->volid = tv->header->diskstuff.id;
1788 strcpy(pntr->name,tv->header->diskstuff.name);
1789 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
1790 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
1791 pntr->backupID = tv->header->diskstuff.backupId;
1792 pntr->parentID = tv->header->diskstuff.parentId;
1793 pntr->copyDate = tv->header->diskstuff.copyDate;
1794 pntr->inUse = tv->header->diskstuff.inUse;
1795 pntr->size = tv->header->diskstuff.diskused;
1796 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1797 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1798 pntr->maxquota = tv->header->diskstuff.maxquota;
1799 pntr->filecount = tv->header->diskstuff.filecount;
1800 now = FT_ApproxTime();
1801 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1804 pntr->dayUse = tv->header->diskstuff.dayUse;
1805 pntr->creationDate = tv->header->diskstuff.creationDate;
1806 pntr->accessDate = tv->header->diskstuff.accessDate;
1807 pntr->updateDate = tv->header->diskstuff.updateDate;
1808 pntr->backupDate = tv->header->diskstuff.backupDate;
1809 pntr->spare0 = tv->header->diskstuff.minquota;
1810 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
1811 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
1812 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
1813 (long) tv->header->diskstuff.weekUse[6];
1814 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
1815 VDetachVolume(&error,tv);/*free the volume */
1818 pntr->status = 0; /*things are messed up */
1819 strcpy(pntr->name,volname);
1820 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
1824 GetNextVol(dirp, volname, &volid);
1828 VDetachVolume(&error, tv);
1833 ttc = (struct volser_trans *) 0;
1841 /*------------------------------------------------------------------------
1842 * EXPORTED SAFSVolXListOneVolume
1845 * Returns extended info on volume a_volID on partition a_partID.
1848 * a_rxCidP : Pointer to the Rx call we're performing.
1849 * a_partID : Partition for which we want the extended list.
1850 * a_volID : Volume ID we wish to know about.
1851 * a_volumeXInfoP : Ptr to the extended info blob.
1854 * 0 Successful operation
1855 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1858 * Nothing interesting.
1862 *------------------------------------------------------------------------*/
1864 afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1865 struct rx_call *a_rxCidP;
1868 volXEntries *a_volumeXInfoP;
1872 code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1873 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1877 afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1878 struct rx_call *a_rxCidP;
1881 volXEntries *a_volumeXInfoP;
1883 { /*SAFSVolXListOneVolume*/
1885 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
1886 register struct Volume *tv; /*Volume ptr*/
1887 struct volser_trans *ttc; /*Volume transaction ptr*/
1888 struct DiskPartition *partP; /*Ptr to partition */
1889 char pname[9], volname[20]; /*Partition, volume names*/
1890 afs_int32 error; /*Error code*/
1891 afs_int32 code; /*Return code*/
1892 DIR *dirp; /*Partition directory ptr*/
1893 afs_int32 currVolID; /*Current volume ID*/
1894 int found = 0; /*Did we find the volume we need?*/
1895 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
1896 int numStatBytes; /*Num stat bytes to copy per volume*/
1900 * Set up our pointers for action, marking our structure to hold exactly
1901 * one entry. Also, assume we'll fail in our quest.
1903 a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
1904 xInfoP = a_volumeXInfoP->volXEntries_val;
1905 a_volumeXInfoP->volXEntries_len = 1;
1909 * If the partition name we've been given is bad, bogue out.
1911 if (GetPartName(a_partID, pname))
1912 return(VOLSERILLEGAL_PARTITION);
1915 * Open the directory representing the given AFS parttion. If we can't
1918 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1919 dirp = opendir(VPartitionPath(partP));
1921 return(VOLSERILLEGAL_PARTITION);
1924 * Sweep through the partition directory, looking for the desired entry.
1925 * First, of course, figure out how many stat bytes to copy out of each
1928 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
1929 (4*VOLINT_STATS_NUM_TIME_FIELDS));
1930 strcpy(volname, "");
1931 ttc = (struct volser_trans *)0; /*No transaction yet*/
1932 tv = (Volume *)0; /*Volume not yet attached*/
1934 while (strcmp(volname,"EOD") && !found) {
1936 * If this is not a volume, move on to the next entry in the
1937 * partition's directory.
1939 if (!strcmp(volname,"")) {
1940 GetNextVol(dirp, volname, &currVolID);
1944 if (currVolID == a_volID) {
1946 * We found the volume entry we're interested. Pull out the
1947 * extended information, remembering to poll (so that the client
1948 * doesn't time out) and to set up a transaction on the volume.
1952 ttc = NewTrans(currVolID, a_partID);
1955 * Couldn't get a transaction on this volume; let our caller
1958 xInfoP->status = VBUSY;
1959 xInfoP->volid = currVolID;
1964 * Attach the volume, give up on the volume if we can't.
1966 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1968 xInfoP->status = 0; /*things are messed up */
1969 strcpy(xInfoP->name, volname);
1970 xInfoP->volid = currVolID;
1971 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
1977 * Also bag out on this volume if it's been marked as needing a
1978 * salvage or to-be-destroyed.
1980 volDiskDataP = &(tv->header->diskstuff);
1981 if (volDiskDataP->destroyMe == DESTROY_ME) {
1983 strcpy(xInfoP->name, volname);
1984 xInfoP->volid = currVolID;
1985 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
1989 if (volDiskDataP->needsSalvaged) {
1991 strcpy(xInfoP->name, volname);
1992 xInfoP->volid = currVolID;
1993 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
1999 * Pull out the desired info and stuff it into the area we'll be
2000 * returning to our caller.
2002 strcpy(xInfoP->name,volDiskDataP->name);
2003 xInfoP->volid = volDiskDataP->id;
2004 xInfoP->type = volDiskDataP->type;
2005 xInfoP->backupID = volDiskDataP->backupId;
2006 xInfoP->parentID = volDiskDataP->parentId;
2007 xInfoP->cloneID = volDiskDataP->cloneId;
2008 xInfoP->status = VOK;
2009 xInfoP->copyDate = volDiskDataP->copyDate;
2010 xInfoP->inUse = volDiskDataP->inUse;
2011 xInfoP->creationDate = volDiskDataP->creationDate;
2012 xInfoP->accessDate = volDiskDataP->accessDate;
2013 xInfoP->updateDate = volDiskDataP->updateDate;
2014 xInfoP->backupDate = volDiskDataP->backupDate;
2015 now = FT_ApproxTime();
2016 if (now - volDiskDataP->dayUseDate > OneDay)
2019 xInfoP->dayUse = volDiskDataP->dayUse;
2020 xInfoP->filecount = volDiskDataP->filecount;
2021 xInfoP->maxquota = volDiskDataP->maxquota;
2022 xInfoP->size = volDiskDataP->diskused;
2025 * Copy out the stat fields in a single operation.
2027 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2030 * We're done copying. Detach the volume and iterate (at this
2031 * point, since we found our volume, we'll then drop out of the
2034 VDetachVolume(&error, tv);
2038 strcpy(xInfoP->name, volname);
2039 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2045 * At this point, we're golden.
2048 } /*Found desired volume*/
2049 GetNextVol(dirp, volname, &currVolID);
2053 * Drop the transaction we have for this volume.
2057 VDetachVolume(&error, tv);
2062 ttc = (struct volser_trans *)0;
2066 * Clean up before going to dinner: close the partition directory,
2067 * return the proper value.
2072 } /*SAFSVolXListOneVolume*/
2074 /*returns all the volumes on partition partid. If flags = 1 then all the
2075 * relevant info about the volumes is also returned */
2076 afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
2077 struct rx_call *acid;
2078 afs_int32 flags, partid;
2079 volEntries *volumeInfo;
2083 code = VolListVolumes (acid, partid, flags, volumeInfo);
2084 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2088 afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
2089 struct rx_call *acid;
2090 afs_int32 flags, partid;
2091 volEntries *volumeInfo;
2093 register struct Volume *tv;
2094 struct DiskPartition *partP;
2095 struct volser_trans *ttc;
2096 afs_int32 allocSize = 1000;/*to be changed to a larger figure */
2097 char pname[9], volname[20];
2098 afs_int32 error = 0;
2103 volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2104 pntr = volumeInfo->volEntries_val;
2105 volumeInfo->volEntries_len = 0;
2106 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
2107 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2108 dirp = opendir(VPartitionPath(partP));
2109 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2111 while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
2112 ttc = (struct volser_trans *) 0; /* new one for each pass */
2113 tv = (Volume *) 0; /* volume not attached */
2115 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
2116 GetNextVol(dirp, volname, &volid);
2117 continue; /*back to while loop */
2120 if(flags) { /*copy other things too */
2121 IOMGR_Poll(); /*make sure that the client doesnot time out*/
2122 ttc = NewTrans(volid,partid);
2124 pntr->status = VBUSY;
2125 pntr->volid = volid;
2128 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
2130 pntr->status = 0; /*things are messed up */
2131 strcpy(pntr->name,volname);
2132 pntr->volid = volid;
2133 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
2136 if(tv->header->diskstuff.needsSalvaged){
2137 /*this volume will be salvaged */
2139 strcpy(pntr->name,volname);
2140 pntr->volid = volid;
2141 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
2145 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
2146 /*this volume will be salvaged */
2149 /*read in the relevant info */
2150 pntr->status = VOK ; /*its ok */
2151 pntr->volid = tv->header->diskstuff.id;
2152 strcpy(pntr->name,tv->header->diskstuff.name);
2153 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
2154 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
2155 pntr->backupID = tv->header->diskstuff.backupId;
2156 pntr->parentID = tv->header->diskstuff.parentId;
2157 pntr->copyDate = tv->header->diskstuff.copyDate;
2158 pntr->inUse = tv->header->diskstuff.inUse;
2159 pntr->size = tv->header->diskstuff.diskused;
2160 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2161 pntr->maxquota = tv->header->diskstuff.maxquota;
2162 pntr->filecount = tv->header->diskstuff.filecount;
2163 now = FT_ApproxTime();
2164 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2167 pntr->dayUse = tv->header->diskstuff.dayUse;
2168 pntr->creationDate = tv->header->diskstuff.creationDate;
2169 pntr->accessDate = tv->header->diskstuff.accessDate;
2170 pntr->updateDate = tv->header->diskstuff.updateDate;
2171 pntr->backupDate = tv->header->diskstuff.backupDate;
2172 pntr->spare0 = tv->header->diskstuff.minquota;
2173 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
2174 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
2175 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
2176 (long) tv->header->diskstuff.weekUse[6];
2177 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
2178 VDetachVolume(&error,tv);/*free the volume */
2181 pntr->status = 0; /*things are messed up */
2182 strcpy(pntr->name,volname);
2183 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
2187 pntr->volid = volid;
2188 /*just volids are needed*/
2194 ttc = (struct volser_trans *) 0;
2197 volumeInfo->volEntries_len += 1;
2198 if((allocSize - volumeInfo->volEntries_len) < 5) {
2199 /*running out of space, allocate more space */
2200 allocSize = (allocSize *3)/2;
2201 pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
2202 allocSize * sizeof(volintInfo));
2205 VDetachVolume(&error, tv);
2210 ttc = (struct volser_trans *) 0;
2213 return VOLSERNO_MEMORY;
2215 volumeInfo->volEntries_val = pntr; /* point to new block */
2216 /* set pntr to the right position */
2217 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2223 VDetachVolume(&error, tv);
2228 ttc = (struct volser_trans *) 0;
2230 GetNextVol(dirp, volname, &volid);
2240 /*------------------------------------------------------------------------
2241 * EXPORTED SAFSVolXListVolumes
2244 * Returns all the volumes on partition a_partID. If a_flags
2245 * is set to 1, then all the relevant extended volume information
2249 * a_rxCidP : Pointer to the Rx call we're performing.
2250 * a_partID : Partition for which we want the extended list.
2251 * a_flags : Various flags.
2252 * a_volumeXInfoP : Ptr to the extended info blob.
2255 * 0 Successful operation
2256 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2257 * VOLSERNO_MEMORY if we ran out of memory allocating
2261 * Nothing interesting.
2265 *------------------------------------------------------------------------*/
2267 afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2268 struct rx_call *a_rxCidP;
2271 volXEntries *a_volumeXInfoP;
2275 code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2276 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2280 afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2281 struct rx_call *a_rxCidP;
2284 volXEntries *a_volumeXInfoP;
2286 { /*SAFSVolXListVolumes*/
2288 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
2289 register struct Volume *tv; /*Volume ptr*/
2290 struct DiskPartition *partP; /*Ptr to partition*/
2291 struct volser_trans *ttc; /*Volume transaction ptr*/
2292 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2293 char pname[9], volname[20]; /*Partition, volume names*/
2294 afs_int32 error = 0; /*Return code*/
2295 DIR *dirp; /*Partition directory ptr*/
2296 afs_int32 volid; /*Current volume ID*/
2297 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
2298 int numStatBytes; /*Num stat bytes to copy per volume*/
2302 * Allocate a large array of extended volume info structures, then
2303 * set it up for action.
2305 a_volumeXInfoP->volXEntries_val =
2306 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2307 xInfoP = a_volumeXInfoP->volXEntries_val;
2308 a_volumeXInfoP->volXEntries_len = 0;
2311 * If the partition name we've been given is bad, bogue out.
2313 if (GetPartName(a_partID, pname))
2314 return(VOLSERILLEGAL_PARTITION);
2317 * Open the directory representing the given AFS parttion. If we can't
2320 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2321 dirp = opendir(VPartitionPath(partP));
2323 return (VOLSERILLEGAL_PARTITION);
2326 * Sweep through the partition directory, acting on each entry. First,
2327 * of course, figure out how many stat bytes to copy out of each volume.
2329 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
2330 (4*VOLINT_STATS_NUM_TIME_FIELDS));
2332 while (strcmp(volname, "EOD")) {
2333 ttc = (struct volser_trans *)0; /*New one for each pass*/
2334 tv = (Volume *)0; /*Volume not yet attached*/
2337 * If this is not a volume, move on to the next entry in the
2338 * partition's directory.
2340 if(!strcmp(volname,"")) {
2341 GetNextVol(dirp, volname, &volid);
2347 * Full info about the volume desired. Poll to make sure the
2348 * client doesn't time out, then start up a new transaction.
2351 ttc = NewTrans(volid,a_partID);
2354 * Couldn't get a transaction on this volume; let our caller
2357 xInfoP->status = VBUSY;
2358 xInfoP->volid = volid;
2363 * Attach the volume, give up on this volume if we can't.
2365 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2367 xInfoP->status = 0; /*things are messed up */
2368 strcpy(xInfoP->name, volname);
2369 xInfoP->volid = volid;
2370 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2376 * Also bag out on this volume if it's been marked as needing a
2377 * salvage or to-be-destroyed.
2379 volDiskDataP = &(tv->header->diskstuff);
2380 if (volDiskDataP->needsSalvaged) {
2382 strcpy(xInfoP->name, volname);
2383 xInfoP->volid = volid;
2384 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
2389 if (volDiskDataP->destroyMe == DESTROY_ME)
2393 * Pull out the desired info and stuff it into the area we'll be
2394 * returning to our caller.
2396 strcpy(xInfoP->name,volDiskDataP->name);
2397 xInfoP->volid = volDiskDataP->id;
2398 xInfoP->type = volDiskDataP->type;
2399 xInfoP->backupID = volDiskDataP->backupId;
2400 xInfoP->parentID = volDiskDataP->parentId;
2401 xInfoP->cloneID = volDiskDataP->cloneId;
2402 xInfoP->status = VOK;
2403 xInfoP->copyDate = volDiskDataP->copyDate;
2404 xInfoP->inUse = volDiskDataP->inUse;
2405 xInfoP->creationDate = volDiskDataP->creationDate;
2406 xInfoP->accessDate = volDiskDataP->accessDate;
2407 xInfoP->updateDate = volDiskDataP->updateDate;
2408 xInfoP->backupDate = volDiskDataP->backupDate;
2409 now = FT_ApproxTime();
2410 if (now - volDiskDataP->dayUseDate > OneDay)
2413 xInfoP->dayUse = volDiskDataP->dayUse;
2414 xInfoP->filecount = volDiskDataP->filecount;
2415 xInfoP->maxquota = volDiskDataP->maxquota;
2416 xInfoP->size = volDiskDataP->diskused;
2419 * Copy out the stat fields in a single operation.
2421 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2424 * We're done copying. Detach the volume and iterate.
2426 VDetachVolume(&error, tv);
2430 strcpy(xInfoP->name, volname);
2431 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2435 } /*Full contents desired*/
2438 * Just volume IDs are needed.
2440 xInfoP->volid = volid;
2444 * Drop the transaction we have for this volume.
2448 ttc = (struct volser_trans *) 0;
2452 * Bump the pointer in the data area we're building, along with
2453 * the count of the number of entries it contains.
2456 (a_volumeXInfoP->volXEntries_len)++;
2457 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2459 * We're running out of space in the area we've built. Grow it.
2461 allocSize = (allocSize * 3)/2;
2462 xInfoP = (volintXInfo *)
2463 realloc((char *) a_volumeXInfoP->volXEntries_val,
2464 (allocSize * sizeof(volintXInfo)));
2465 if (xInfoP == NULL) {
2467 * Bummer, no memory. Bag it, tell our caller what went wrong.
2470 VDetachVolume(&error, tv);
2475 ttc = (struct volser_trans *) 0;
2478 return(VOLSERNO_MEMORY);
2482 * Memory reallocation worked. Correct our pointers so they
2483 * now point to the new block and the current open position within
2486 a_volumeXInfoP->volXEntries_val = xInfoP;
2487 xInfoP = a_volumeXInfoP->volXEntries_val +
2488 a_volumeXInfoP->volXEntries_len;
2489 } /*Need more space*/
2493 * Detach our current volume and the transaction on it, then move on
2494 * to the next volume in the partition directory.
2497 VDetachVolume(&error, tv);
2502 ttc = (struct volser_trans *) 0;
2504 GetNextVol(dirp, volname, &volid);
2505 } /*Sweep through the partition directory*/
2508 * We've examined all entries in the partition directory. Close it,
2509 * delete our transaction (if any), and go home happy.
2516 } /*SAFSVolXListVolumes*/
2518 /*this call is used to monitor the status of volser for debugging purposes.
2519 *information about all the active transactions is returned in transInfo*/
2520 afs_int32 SAFSVolMonitor (acid,transInfo)
2521 struct rx_call *acid;
2522 transDebugEntries *transInfo;
2526 code = VolMonitor (acid,transInfo);
2527 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2531 afs_int32 VolMonitor (acid,transInfo)
2532 struct rx_call *acid;
2533 transDebugEntries *transInfo;
2535 transDebugInfo *pntr;
2536 afs_int32 allocSize = 50;
2537 struct volser_trans *tt, *allTrans;
2539 transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2540 pntr = transInfo->transDebugEntries_val;
2541 transInfo->transDebugEntries_len = 0;
2542 allTrans = TransList();
2543 if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
2544 for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
2545 pntr->tid = tt->tid;
2546 pntr->time = tt->time;
2547 pntr->creationTime = tt->creationTime;
2548 pntr->returnCode = tt->returnCode;
2549 pntr->volid = tt->volid;
2550 pntr->partition = tt->partition;
2551 pntr->iflags = tt->iflags;
2552 pntr->vflags = tt->vflags;
2553 pntr->tflags = tt->tflags;
2554 strcpy(pntr->lastProcName,tt->lastProcName);
2555 pntr->callValid = 0;
2556 if(tt->rxCallPtr) { /*record call related info */
2557 pntr->callValid = 1;
2558 pntr->readNext = tt->rxCallPtr->rnext;
2559 pntr->transmitNext = tt->rxCallPtr->tnext;
2560 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2561 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2564 transInfo->transDebugEntries_len += 1;
2565 if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
2566 allocSize = (allocSize *3)/2;
2567 pntr = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
2568 transInfo->transDebugEntries_val = pntr;
2569 pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
2570 /*set pntr to right position*/
2578 afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2579 struct rx_call *acid;
2580 afs_int32 type, pId, cloneId, backupId, atid;
2585 code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
2586 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid,
2591 AUD_LONG, backupId, AUD_END);
2595 afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2596 struct rx_call *acid;
2597 afs_int32 type, pId, cloneId, backupId, atid;
2601 afs_int32 error = 0;
2602 register struct volser_trans *tt;
2603 char caller[MAXKTCNAMELEN];
2605 if (strlen(name)>31) return VOLSERBADNAME;
2606 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2607 /* find the trans */
2608 tt = FindTrans(atid);
2609 if (!tt) return ENOENT;
2610 if (tt->vflags & VTDeleted) {
2611 Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
2615 strcpy(tt->lastProcName,"SetIdsTypes");
2616 tt->rxCallPtr = acid;
2620 V_backupId(tv) = backupId;
2621 V_cloneId(tv) = cloneId;
2622 V_parentId(tv) = pId;
2623 strcpy((&V_disk(tv))->name,name);
2624 VUpdateVolume(&error, tv);
2626 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2630 tt->rxCallPtr = (struct rx_call *)0;
2631 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2635 tt->rxCallPtr = (struct rx_call *)0;
2636 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2640 afs_int32 SAFSVolSetDate (acid,atid,cdate)
2641 struct rx_call *acid;
2642 afs_int32 atid, cdate;
2646 code = VolSetDate (acid,atid,cdate);
2647 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
2651 afs_int32 VolSetDate (acid,atid,cdate)
2652 struct rx_call *acid;
2653 afs_int32 atid, cdate;
2656 afs_int32 error = 0;
2657 register struct volser_trans *tt;
2658 char caller[MAXKTCNAMELEN];
2660 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2661 /* find the trans */
2662 tt = FindTrans(atid);
2663 if (!tt) return ENOENT;
2664 if (tt->vflags & VTDeleted) {
2665 Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
2669 strcpy(tt->lastProcName,"SetDate");
2670 tt->rxCallPtr = acid;
2673 V_creationDate(tv) = cdate;
2674 VUpdateVolume(&error, tv);
2676 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2680 tt->rxCallPtr = (struct rx_call *)0;
2681 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2685 tt->rxCallPtr = (struct rx_call *)0;
2686 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2690 /* GetPartName - map partid (a decimal number) into pname (a string)
2691 * Since for NT we actually want to return the drive name, we map through the
2694 static int GetPartName(afs_int32 partid, char *pname)
2699 strcpy(pname,"/vicep");
2700 pname[6] = 'a' + partid;
2703 } else if (partid < VOLMAXPARTS) {
2704 strcpy(pname,"/vicep");
2706 pname[6] = 'a' + (partid / 26);
2707 pname[7] = 'a' + (partid % 26);