2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
23 #include <netinet/in.h>
40 #include <afs/afsint.h>
42 #include <afs/assert.h>
43 #include <afs/prs_fs.h>
48 #include <afs/cellconfig.h>
51 #include <afs/ihandle.h>
53 #include <afs/ntops.h>
55 #include <afs/vnode.h>
56 #include <afs/volume.h>
57 #include <afs/partition.h>
59 #include <afs/fssync.h>
61 #include "afs/audit.h"
66 #include <volser_prototypes.h>
69 extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
70 extern struct afsconf_dir *tdir;
71 extern char *volutil_PartitionName();
73 /* Forward declarations */
74 static int GetPartName(afs_int32 partid, char *pname);
76 #define OneDay (24*60*60)
83 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
84 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
85 afs_int32 VolForwardMultiple();
86 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
87 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
88 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
90 /* this call unlocks all of the partition locks we've set */
92 register struct DiskPartition *tp;
93 for(tp = DiskPartitionList; tp; tp = tp->next) {
94 if (tp->lock_fd != -1) {
95 close(tp->lock_fd); /* releases flock held on this partition */
102 /* get partition id from a name */
103 afs_int32 PartitionID(aname)
106 register int code = 0;
110 if (tc == 0) return -1; /* unknown */
112 /* otherwise check for vicepa or /vicepa, or just plain "a" */
114 if (!strncmp(aname, "/vicep", 6)) {
115 strncpy(ascii, aname+6, 2);
117 else return -1; /* bad partition name */
118 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
119 from 0. Do the appropriate conversion */
121 /* one char name, 0..25 */
122 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
123 return ascii[0] - 'a';
126 /* two char name, 26 .. <whatever> */
127 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
128 if (ascii[1] < 'a' || ascii[1] > 'z') return -1; /* just as bad */
129 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
130 if (code > VOLMAXPARTS) return -1;
135 static int ConvertVolume(avol, aname, asize)
139 if (asize < 18) return -1;
140 /* It's better using the Generic VFORMAT since otherwise we have to make changes to too many places... The 14 char limitation in names hits us again in AIX; print in field of 9 digits (still 10 for the rest), right justified with 0 padding */
141 sprintf(aname, VFORMAT, avol);
145 static int ConvertPartition(apartno, aname, asize)
149 if (asize < 10) return E2BIG;
150 if (apartno < 0) return EINVAL;
151 strcpy(aname, "/vicep");
153 aname[6] = 'a'+apartno;
158 aname[6] = 'a' + (apartno / 26);
159 aname[7] = 'a' + (apartno % 26);
165 /* the only attach function that takes a partition is "...ByName", so we use it */
166 struct Volume *XAttachVolume(error, avolid, apartid, amode)
171 char pbuf[30], vbuf[20];
172 register struct Volume *tv;
174 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
178 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
182 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
186 /* Adapted from the file server; create a root directory for this volume */
187 static ViceCreateRoot(vp)
191 struct acl_accessList * ACL;
193 Inode inodeNumber, nearInode;
194 char buf[SIZEOF_LARGEDISKVNODE];
195 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
196 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
202 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
204 V_pref(vp, nearInode);
205 inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
206 VPartitionPath(V_partition(vp)), nearInode,
207 V_parentId(vp), 1, 1, 0);
208 assert(VALID_INO(inodeNumber));
210 SetSalvageDirHandle(&dir, V_id(vp), vp->device, inodeNumber);
211 did.Volume = V_id(vp);
212 did.Vnode = (VnodeId)1;
215 assert(!(MakeDir(&dir, &did, &did)));
216 DFlush(); /* flush all modified dir buffers out */
217 DZap(&dir); /* Remove all buffers for this dir */
218 length = Length(&dir); /* Remember size of this directory */
220 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
222 /* build a single entry ACL that gives all rights to system:administrators */
223 /* this section of code assumes that access list format is not going to
226 ACL = VVnodeDiskACL(vnode);
227 ACL->size = sizeof(struct acl_accessList);
228 ACL->version = ACL_ACLVERSION;
232 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
233 ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
235 vnode->type = vDirectory;
237 vnode->modeBits = 0777;
238 vnode->linkCount = 2;
239 vnode->length = length;
240 vnode->uniquifier = 1;
241 V_uniquifier(vp) = vnode->uniquifier+1;
242 vnode->dataVersion = 1;
243 VNDISK_SET_INO(vnode, inodeNumber);
244 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
248 vnode->vnodeMagic = vcp->magic;
250 IH_INIT(h, vp->device, V_parentId(vp),
251 vp->vnodeIndex[vLarge].handle->ih_ino);
254 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
256 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
257 assert(code == SIZEOF_LARGEDISKVNODE);
258 FDH_REALLYCLOSE(fdP);
260 V_diskused(vp) = nBlocks(vnode->length);
265 afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
266 struct rx_call *acid;
268 struct diskPartition *partition;
272 code = VolPartitionInfo (acid,pname,partition);
273 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
277 afs_int32 VolPartitionInfo (acid,pname,partition)
278 struct rx_call *acid;
280 struct diskPartition *partition;
282 register struct DiskPartition *dp;
285 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
288 dp = VGetPartition(pname, 0);
290 strncpy(partition->name,dp->name,32);
291 strncpy(partition->devName,dp->devName,32);
292 partition->lock_fd = dp->lock_fd ;
293 partition->free = dp->free;
294 partition->minFree = dp->totalUsable;
298 return VOLSERILLEGAL_PARTITION;
301 /* obliterate a volume completely, and slowly. */
302 afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
303 struct rx_call *acid;
304 afs_int32 apartID, avolID;
308 code = VolNukeVolume (acid, apartID, avolID);
309 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
313 afs_int32 VolNukeVolume (acid, apartID, avolID)
314 struct rx_call *acid;
315 afs_int32 apartID, avolID;
320 register afs_int32 code;
322 char caller[MAXKTCNAMELEN];
324 /* check for access */
325 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
326 if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
328 tp = volutil_PartitionName(apartID);
329 if (!tp) return VOLSERNOVOL;
330 strcpy(partName, tp); /* remember it for later */
331 /* we first try to attach the volume in update mode, so that the file
332 * server doesn't try to use it (and abort) while (or after) we delete it.
333 * If we don't get the volume, that's fine, too. We just won't put it back.
335 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
336 code = nuke(partName, avolID);
337 if (tvp) VDetachVolume(&error, tvp);
341 /* create a new volume, with name aname, on the specified partition (1..n)
342 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
343 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
344 * for the volume id (useful for things like volume restore).
345 * Return the new volume id in *avolid.
347 afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
348 struct rx_call *acid;
358 code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
359 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans,
368 afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
369 struct rx_call *acid;
379 afs_int32 junk; /* discardable error code */
380 register afs_int32 volumeID, doCreateRoot=1;
381 register struct volser_trans *tt;
383 char caller[MAXKTCNAMELEN];
385 if (strlen(aname) > 31) return VOLSERBADNAME;
386 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
387 if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
388 if (error = ConvertPartition(apart, ppath, sizeof(ppath))) return error;/*a standard unix error*/
389 if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
391 if ((volumeID = *avolid) == 0) {
393 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
397 if ((aparent == volumeID) && (atype == readwriteVolume)) {
400 if (aparent == 0) aparent = volumeID;
401 tt = NewTrans(volumeID, apart);
403 Log("1 createvolume: failed to create trans\n");
404 return VOLSERVOLBUSY; /* volume already busy! */
406 vp = VCreateVolume(&error, ppath, volumeID, aparent);
408 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
413 V_uniquifier(vp) = 1;
414 V_creationDate(vp) = V_copyDate(vp);
415 V_inService(vp) = V_blessed(vp) = 1;
417 AssignVolumeName(&V_disk(vp), aname, 0);
420 V_destroyMe(vp) = DESTROY_ME;
422 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
423 VUpdateVolume(&error, vp);
425 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
428 VDetachVolume(&junk, vp); /* rather return the real error code */
433 strcpy(tt->lastProcName,"CreateVolume");
434 tt->rxCallPtr = acid;
435 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
436 tt->rxCallPtr = (struct rx_call *)0;
437 if(TRELE(tt)) return VOLSERTRELE_ERROR;
441 /* delete the volume associated with this transaction */
442 afs_int32 SAFSVolDeleteVolume (acid, atrans)
444 struct rx_call *acid;
448 code = VolDeleteVolume (acid, atrans);
449 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
453 afs_int32 VolDeleteVolume (acid, atrans)
455 struct rx_call *acid;
457 register struct volser_trans *tt;
459 char caller[MAXKTCNAMELEN];
461 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
462 tt = FindTrans(atrans);
463 if (!tt) return ENOENT;
464 if (tt->vflags & VTDeleted) {
465 Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
469 if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
470 strcpy(tt->lastProcName,"DeleteVolume");
471 tt->rxCallPtr = acid;
472 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
473 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
474 tt->rxCallPtr = (struct rx_call *)0;
475 if(TRELE(tt)) return VOLSERTRELE_ERROR;
477 Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
478 return 0; /* vpurgevolume doesn't set an error code */
481 /* make a clone of the volume associated with atrans, possibly giving it a new
482 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
483 * for the clone's id). The new clone is given the name newName. Finally, due to
484 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
485 * the clone operation. This may be useful when making new backup volumes, for instance
486 * since the net result of a clone and a purge generally leaves many inode ref counts
487 * the same, while doing them separately would result in far more iincs and idecs being
488 * peformed (and they are slow operations).
490 afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
491 struct rx_call *acid;
494 afs_int32 *newNumber;
495 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
500 code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
501 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans,
505 AUD_LONG, *newNumber, AUD_END);
509 afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
510 struct rx_call *acid;
513 afs_int32 *newNumber;
514 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
518 register struct Volume *originalvp, *purgevp, *newvp;
520 register struct volser_trans *tt,*ttc;
521 char caller[MAXKTCNAMELEN];
523 if (strlen(newName)>31) return VOLSERBADNAME;
524 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
525 if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
527 originalvp = (Volume *) 0;
528 purgevp = (Volume *) 0;
529 newvp = (Volume *) 0;
530 tt = ttc = (struct volser_trans *) 0;
532 if (!newNumber || !*newNumber)
534 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
539 if (newType != readonlyVolume && newType != backupVolume)
541 tt = FindTrans(atrans);
542 if (!tt) return ENOENT;
543 if (tt->vflags & VTDeleted) {
544 Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
548 ttc = NewTrans(newId,tt->partition);
550 { /* someone is messing with the clone already */
554 strcpy(tt->lastProcName,"Clone");
555 tt->rxCallPtr = acid;
559 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
561 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
568 originalvp = tt->volume;
569 if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
570 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
574 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
575 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
581 if (originalvp->device != purgevp->device) {
582 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
586 if (V_type(purgevp) != readonlyVolume) {
587 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
591 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
592 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
596 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
597 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
606 newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
608 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
609 newvp = (Volume *) 0;
612 if (newType == readonlyVolume)
613 V_cloneId(originalvp) = newId;
614 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
616 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
617 CloneVolume(&error, originalvp, newvp, purgevp);
618 purgevp = NULL; /* clone releases it, maybe even if error */
620 Log("1 Volser: Clone: clone operation failed with code %d\n", error);
624 if (newType == readonlyVolume) {
625 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
626 V_type(newvp) = readonlyVolume;
628 else if (newType == backupVolume) {
629 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
630 V_type(newvp) = backupVolume;
631 V_backupId(originalvp) = newId;
633 strcpy(newvp->header->diskstuff.name,newName);
634 V_creationDate(newvp) = V_copyDate(newvp);
635 ClearVolumeStats(&V_disk(newvp));
636 V_destroyMe(newvp) = DESTROY_ME;
637 V_inService(newvp) = 0;
638 if (newType == backupVolume) {
639 V_backupDate(originalvp) = V_copyDate(newvp);
640 V_backupDate(newvp) = V_copyDate(newvp);
643 VUpdateVolume(&error, newvp);
645 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
649 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
651 VUpdateVolume(&error, originalvp);
653 Log("1 Volser: Clone: original update %d\n", error);
657 tt->rxCallPtr = (struct rx_call *)0;
659 tt = (struct volser_trans *) 0;
660 error = VOLSERTRELE_ERROR;
667 if (purgevp) VDetachVolume(&code, purgevp);
668 if (newvp) VDetachVolume(&code, newvp);
670 tt->rxCallPtr = (struct rx_call *)0;
673 if(ttc) DeleteTrans(ttc);
677 /* reclone this volume into the specified id */
678 afs_int32 SAFSVolReClone (acid, atrans, cloneId)
679 struct rx_call *acid;
685 code = VolReClone (acid, atrans, cloneId);
686 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
690 afs_int32 VolReClone (acid, atrans, cloneId)
691 struct rx_call *acid;
695 register struct Volume *originalvp, *clonevp;
698 register struct volser_trans *tt,*ttc;
699 char caller[MAXKTCNAMELEN];
702 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
703 if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
705 clonevp = originalvp = (Volume *) 0;
706 tt = (struct volser_trans *) 0;
708 tt = FindTrans(atrans);
709 if (!tt) return ENOENT;
710 if (tt->vflags & VTDeleted) {
711 Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
715 ttc = NewTrans(cloneId, tt->partition);
716 if (!ttc){ /* someone is messing with the clone already */
720 strcpy(tt->lastProcName,"ReClone");
721 tt->rxCallPtr = acid;
723 originalvp = tt->volume;
724 if ((V_type(originalvp) == backupVolume) ||
725 (V_type(originalvp) == readonlyVolume)){
726 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
730 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
731 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
737 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
739 Log("1 Volser: can't attach clone %d\n", cloneId);
743 newType = V_type(clonevp); /* type of the new volume */
745 if (originalvp->device != clonevp->device) {
746 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
750 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
751 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
755 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
756 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
760 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
761 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
768 Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
770 CloneVolume(&error, originalvp, clonevp, clonevp);
772 Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
777 /* fix up volume name and type, CloneVolume just propagated RW's */
778 if (newType == readonlyVolume) {
779 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
780 V_type(clonevp) = readonlyVolume;
782 else if (newType == backupVolume) {
783 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
784 V_type(clonevp) = backupVolume;
785 V_backupId(originalvp) = cloneId;
787 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
789 /* pretend recloned volume is a totally new instance */
790 V_copyDate(clonevp) = time(0);
791 V_creationDate(clonevp) = V_copyDate(clonevp);
792 ClearVolumeStats(&V_disk(clonevp));
793 V_destroyMe(clonevp) = 0;
794 V_inService(clonevp) = 0;
795 if (newType == backupVolume) {
796 V_backupDate(originalvp) = V_copyDate(clonevp);
797 V_backupDate(clonevp) = V_copyDate(clonevp);
799 V_inUse(clonevp) = 0;
800 VUpdateVolume(&error, clonevp);
802 Log("1 Volser: Clone: VUpdate failed code %d\n", error);
806 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
808 VUpdateVolume(&error, originalvp);
810 Log("1 Volser: Clone: original update %d\n", error);
814 tt->rxCallPtr = (struct rx_call *)0;
816 tt = (struct volser_trans *) 0;
817 error = VOLSERTRELE_ERROR;
824 struct DiskPartition *tpartp = originalvp->partition;
825 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
830 if (clonevp) VDetachVolume(&code, clonevp);
832 tt->rxCallPtr = (struct rx_call *)0;
835 if(ttc) DeleteTrans(ttc);
839 /* create a new transaction, associated with volume and partition. Type of
840 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
841 * See volser.h for definition of iflags (the constants are named IT*).
843 afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
844 struct rx_call *acid;
852 code = VolTransCreate (acid, volume, partition, iflags, ttid);
853 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
857 afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
858 struct rx_call *acid;
864 register struct volser_trans *tt;
866 afs_int32 error, code;
868 char caller[MAXKTCNAMELEN];
870 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
871 if (iflags & ITCreate) mode = V_SECRETLY;
872 else if (iflags & ITBusy) mode = V_CLONE;
873 else if (iflags & ITReadOnly) mode = V_READONLY;
874 else if (iflags & ITOffline) mode = V_VOLUPD;
876 Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
880 tt = NewTrans(volume, partition);
882 /* can't create a transaction? put the volume back */
883 Log("1 transcreate: can't create transaction\n");
884 return VOLSERVOLBUSY;
886 tv = XAttachVolume(&error, volume, partition, mode);
889 if (tv) VDetachVolume(&code, tv);
897 strcpy(tt->lastProcName,"TransCreate");
898 if(TRELE(tt)) return VOLSERTRELE_ERROR;
903 /* using aindex as a 0-based index, return the aindex'th volume on this server
904 * Both the volume number and partition number (one-based) are returned.
906 afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
907 struct rx_call *acid;
914 code = VolGetNthVolume (acid, aindex, avolume, apart);
915 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
919 afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
920 struct rx_call *acid;
925 Log("1 Volser: GetNthVolume: Not yet implemented\n");
929 /* return the volume flags (VT* constants in volser.h) associated with this
932 afs_int32 SAFSVolGetFlags (acid, atid, aflags)
933 struct rx_call *acid;
939 code = VolGetFlags (acid, atid, aflags);
940 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
944 afs_int32 VolGetFlags (acid, atid, aflags)
945 struct rx_call *acid;
949 register struct volser_trans *tt;
951 tt = FindTrans(atid);
952 if (!tt) return ENOENT;
953 if (tt->vflags & VTDeleted) {
954 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
958 strcpy(tt->lastProcName,"GetFlags");
959 tt->rxCallPtr = acid;
960 *aflags = tt->vflags;
961 tt->rxCallPtr = (struct rx_call *)0;
962 if(TRELE(tt)) return VOLSERTRELE_ERROR;
967 /* Change the volume flags (VT* constants in volser.h) associated with this
968 * transaction. Effects take place immediately on volume, although volume
969 * remains attached as usual by the transaction.
971 afs_int32 SAFSVolSetFlags (acid, atid, aflags)
972 struct rx_call *acid;
978 code = VolSetFlags (acid, atid, aflags);
979 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
983 afs_int32 VolSetFlags (acid, atid, aflags)
984 struct rx_call *acid;
988 register struct volser_trans *tt;
989 register struct Volume *vp;
991 char caller[MAXKTCNAMELEN];
993 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
995 tt = FindTrans(atid);
996 if (!tt) return ENOENT;
997 if (tt->vflags & VTDeleted) {
998 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
1002 strcpy(tt->lastProcName,"SetFlags");
1003 tt->rxCallPtr = acid;
1004 vp = tt->volume; /* pull volume out of transaction */
1006 /* check if we're allowed to make any updates */
1007 if (tt->iflags & ITReadOnly) {
1012 /* handle delete-on-salvage flag */
1013 if (aflags & VTDeleteOnSalvage) {
1014 V_destroyMe(tt->volume) = DESTROY_ME;
1017 V_destroyMe(tt->volume) = 0;
1020 if (aflags & VTOutOfService) {
1021 V_inService(vp) = 0;
1024 V_inService(vp) = 1;
1026 VUpdateVolume(&error, vp);
1027 tt->vflags = aflags;
1028 tt->rxCallPtr = (struct rx_call *)0;
1029 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
1034 /* dumpS the volume associated with a particular transaction from a particular
1035 * date. Send the dump to a different transaction (destTrans) on the server
1036 * specified by the destServer structure.
1038 afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1039 struct rx_call *acid;
1040 afs_int32 fromTrans;
1042 struct destServer *destination;
1043 struct restoreCookie *cookie;
1044 afs_int32 destTrans;
1048 code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
1049 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans,
1050 AUD_HOST, destination->destHost,
1051 AUD_LONG, destTrans, AUD_END);
1055 afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1056 struct rx_call *acid;
1057 afs_int32 fromTrans;
1059 struct destServer *destination;
1060 struct restoreCookie *cookie;
1061 afs_int32 destTrans;
1063 register struct volser_trans *tt;
1064 register afs_int32 code;
1065 register struct rx_connection *tcon;
1066 struct rx_call *tcall;
1067 register struct Volume *vp;
1068 struct rx_securityClass *securityObject;
1069 afs_int32 securityIndex;
1070 char caller[MAXKTCNAMELEN];
1072 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1073 /* initialize things */
1074 tcon = (struct rx_connection *) 0;
1075 tt = (struct volser_trans *) 0;
1077 /* find the local transaction */
1078 tt = FindTrans(fromTrans);
1079 if (!tt) return ENOENT;
1080 if (tt->vflags & VTDeleted) {
1081 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1086 strcpy(tt->lastProcName,"Forward");
1088 /* get auth info for the this connection (uses afs from ticket file) */
1089 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1095 /* make an rpc connection to the other server */
1096 tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
1098 tt->rxCallPtr = (struct rx_call *)0;
1102 tcall = rx_NewCall(tcon);
1103 tt->rxCallPtr = tcall;
1104 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1105 code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
1110 /* these next calls implictly call rx_Write when writing out data */
1111 code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
1112 if (code) goto fail;
1113 EndAFSVolRestore(tcall); /* probably doesn't do much */
1114 tt->rxCallPtr = (struct rx_call *)0;
1115 code = rx_EndCall(tcall, 0);
1116 rx_DestroyConnection(tcon); /* done with the connection */
1118 if (code) goto fail;
1119 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1125 rx_EndCall(tcall,0);
1126 rx_DestroyConnection(tcon);
1129 tt->rxCallPtr = (struct rx_call *)0;
1135 /* Start a dump and send it to multiple places simultaneously.
1136 * If this returns an error (eg, return ENOENT), it means that
1137 * none of the releases worked. If this returns 0, that means
1138 * that one or more of the releases worked, and the caller has
1139 * to examine the results array to see which one(s).
1140 * This will only do EITHER incremental or full, not both, so it's
1141 * the caller's responsibility to be sure that all the destinations
1142 * need just an incremental (and from the same time), if that's
1145 afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations,
1146 spare, cookie, results)
1147 struct rx_call *acid;
1148 afs_int32 fromTrans;
1151 manyDests *destinations;
1152 struct restoreCookie *cookie;
1153 manyResults *results;
1155 afs_int32 securityIndex;
1156 struct rx_securityClass *securityObject;
1157 char caller[MAXKTCNAMELEN];
1158 struct volser_trans *tt;
1159 afs_int32 ec, code, *codes;
1160 struct rx_connection **tcons;
1161 struct rx_call **tcalls;
1163 int i, nconns, is_incremental;
1166 memset(results, 0, sizeof(manyResults));
1168 if (!afsconf_SuperUser(tdir, acid, caller))
1169 return VOLSERBAD_ACCESS;/*not a super user*/
1170 tt = FindTrans(fromTrans);
1173 if (tt->vflags & VTDeleted) {
1174 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1179 strcpy(tt->lastProcName, "ForwardMulti");
1181 /* (fromDate == 0) ==> incremental dump */
1182 is_incremental = (fromDate ? 1 : 0);
1184 i= results->manyResults_len = destinations->manyDests_len;
1185 results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
1186 tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
1187 tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
1189 /* get auth info for this connection (uses afs from ticket file) */
1190 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1192 goto fail; /* in order to audit each failure */
1195 /* make connections to all the other servers */
1196 for (i=0; i < destinations->manyDests_len; i++) {
1197 struct replica *dest = &(destinations->manyDests_val[i]);
1198 tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
1199 htons(dest->server.destPort),
1200 VOLSERVICE_ID, securityObject, securityIndex);
1202 codes[i] = ENOTCONN;
1205 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1208 codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
1209 is_incremental,cookie);
1211 rx_EndCall (tcalls[i],0); tcalls[i] = 0;
1212 rx_DestroyConnection(tcons[i]); tcons[i] = 0;
1218 /* these next calls implictly call rx_Write when writing out data */
1219 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1223 for (i--; i >=0 ; i--) {
1224 struct replica *dest = &(destinations->manyDests_val[i]);
1226 if (!code && tcalls[i] && !codes[i]) {
1227 EndAFSVolRestore(tcalls[i]);
1230 ec = rx_EndCall(tcalls[i], 0);
1231 if (!codes[i]) codes[i] = ec;
1234 rx_DestroyConnection(tcons[i]); /* done with the connection */
1237 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]),
1238 AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost,
1239 AUD_LONG, dest->trans, AUD_END);
1245 tt->rxCallPtr = (struct rx_call *)0;
1246 if(TRELE(tt) && !code) /* return the first code if it's set */
1247 return VOLSERTRELE_ERROR;
1253 afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
1254 struct rx_call *acid;
1255 afs_int32 fromTrans;
1260 code = VolDump (acid, fromTrans, fromDate);
1261 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1265 afs_int32 VolDump (acid, fromTrans, fromDate)
1266 struct rx_call *acid;
1267 afs_int32 fromTrans;
1271 register struct volser_trans *tt;
1272 char caller[MAXKTCNAMELEN];
1274 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1275 tt = FindTrans(fromTrans);
1276 if (!tt) return ENOENT;
1277 if (tt->vflags & VTDeleted) {
1278 Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
1282 strcpy(tt->lastProcName,"Dump");
1283 tt->rxCallPtr = acid;
1284 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1285 if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
1286 tt->rxCallPtr = (struct rx_call *)0;
1288 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1294 * Ha! No more helper process!
1296 afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
1297 struct rx_call *acid;
1300 struct restoreCookie *cookie;
1304 code = VolRestore (acid, atrans, aflags,cookie);
1305 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1309 afs_int32 VolRestore (acid, atrans, aflags,cookie)
1310 struct rx_call *acid;
1313 struct restoreCookie *cookie;
1315 register struct volser_trans *tt;
1316 register afs_int32 code,tcode;
1317 char caller[MAXKTCNAMELEN];
1319 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1320 tt = FindTrans(atrans);
1321 if (!tt) return ENOENT;
1322 if (tt->vflags & VTDeleted) {
1323 Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
1327 strcpy(tt->lastProcName,"Restore");
1328 tt->rxCallPtr = acid;
1329 code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie); /* last is incrementalp */
1330 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
1332 tt->rxCallPtr = (struct rx_call *)0;
1335 return (code? code : tcode);
1338 /* end a transaction, returning the transaction's final error code in rcode */
1339 afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
1340 struct rx_call *acid;
1341 afs_int32 destTrans;
1346 code = VolEndTrans (acid, destTrans, rcode);
1347 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1351 afs_int32 VolEndTrans (acid, destTrans, rcode)
1352 struct rx_call *acid;
1353 afs_int32 destTrans;
1356 register struct volser_trans *tt;
1357 char caller[MAXKTCNAMELEN];
1359 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1360 tt = FindTrans(destTrans);
1361 if (!tt) {return ENOENT;}
1362 *rcode = tt->returnCode;
1363 DeleteTrans(tt); /* this does an implicit TRELE */
1368 afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
1369 struct rx_call *acid;
1375 code = VolSetForwarding (acid, atid, anewsite);
1376 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
1380 afs_int32 VolSetForwarding (acid, atid, anewsite)
1381 struct rx_call *acid;
1386 register struct volser_trans *tt;
1387 char caller[MAXKTCNAMELEN];
1389 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1390 tt = FindTrans(atid);
1391 if (!tt) return ENOENT;
1392 if (tt->vflags & VTDeleted) {
1393 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
1397 strcpy(tt->lastProcName,"SetForwarding");
1398 tt->rxCallPtr = acid;
1399 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1400 tt->rxCallPtr = (struct rx_call *)0;
1401 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1406 afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
1407 struct rx_call *acid;
1409 register struct volser_status *astatus;
1413 code = VolGetStatus (acid, atrans, astatus);
1414 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1418 afs_int32 VolGetStatus (acid, atrans, astatus)
1419 struct rx_call *acid;
1421 register struct volser_status *astatus;
1423 register struct Volume *tv;
1424 register struct VolumeDiskData *td;
1425 struct volser_trans *tt;
1428 tt = FindTrans(atrans);
1429 if (!tt) return ENOENT;
1430 if (tt->vflags & VTDeleted) {
1431 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
1435 strcpy(tt->lastProcName,"GetStatus");
1436 tt->rxCallPtr = acid;
1439 tt->rxCallPtr = (struct rx_call *)0;
1444 td = &tv->header->diskstuff;
1445 astatus->volID = td->id;
1446 astatus->nextUnique = td->uniquifier;
1447 astatus->type = td->type;
1448 astatus->parentID = td->parentId;
1449 astatus->cloneID = td->cloneId;
1450 astatus->backupID = td->backupId;
1451 astatus->restoredFromID = td->restoredFromId;
1452 astatus->maxQuota = td->maxquota;
1453 astatus->minQuota = td->minquota;
1454 astatus->owner = td->owner;
1455 astatus->creationDate = td->creationDate;
1456 astatus->accessDate = td->accessDate;
1457 astatus->updateDate = td->updateDate;
1458 astatus->expirationDate = td->expirationDate;
1459 astatus->backupDate = td->backupDate;
1460 astatus->copyDate = td->copyDate;
1461 tt->rxCallPtr = (struct rx_call *)0;
1462 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1467 afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
1468 struct rx_call *acid;
1470 register struct volintInfo *astatus;
1474 code = VolSetInfo (acid, atrans, astatus);
1475 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1479 afs_int32 VolSetInfo (acid, atrans, astatus)
1480 struct rx_call *acid;
1482 register struct volintInfo *astatus;
1484 register struct Volume *tv;
1485 register struct VolumeDiskData *td;
1486 struct volser_trans *tt;
1487 char caller[MAXKTCNAMELEN];
1490 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1491 tt = FindTrans(atrans);
1492 if (!tt) return ENOENT;
1493 if (tt->vflags & VTDeleted) {
1494 Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
1498 strcpy(tt->lastProcName,"SetStatus");
1499 tt->rxCallPtr = acid;
1502 tt->rxCallPtr = (struct rx_call *)0;
1507 td = &tv->header->diskstuff;
1509 * Add more fields as necessary
1511 if (astatus->maxquota != -1)
1512 td->maxquota = astatus->maxquota;
1513 if (astatus->dayUse != -1)
1514 td->dayUse = astatus->dayUse;
1515 VUpdateVolume(&error, tv);
1516 tt->rxCallPtr = (struct rx_call *)0;
1517 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1522 afs_int32 SAFSVolGetName (acid, atrans, aname)
1523 struct rx_call *acid;
1529 code = VolGetName (acid, atrans, aname);
1530 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1534 afs_int32 VolGetName (acid, atrans, aname)
1535 struct rx_call *acid;
1539 register struct Volume *tv;
1540 register struct VolumeDiskData *td;
1541 struct volser_trans *tt;
1545 tt = FindTrans(atrans);
1546 if (!tt) return ENOENT;
1547 if (tt->vflags & VTDeleted) {
1548 Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
1552 strcpy(tt->lastProcName,"GetName");
1553 tt->rxCallPtr = acid;
1556 tt->rxCallPtr = (struct rx_call *)0;
1561 td = &tv->header->diskstuff;
1562 len = strlen(td->name)+1; /* don't forget the null */
1564 tt->rxCallPtr = (struct rx_call *)0;
1568 *aname = (char *)malloc(len);
1569 strcpy(*aname, td->name);
1570 tt->rxCallPtr = (struct rx_call *)0;
1571 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1575 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1577 afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
1578 struct rx_call *acid;
1580 afs_int32 parentId, cloneId;
1587 /*return a list of all partitions on the server. The non mounted
1588 *partitions are returned as -1 in the corresponding slot in partIds*/
1589 afs_int32 SAFSVolListPartitions (acid, partIds)
1590 struct rx_call *acid;
1591 struct pIDs *partIds;
1595 code = VolListPartitions (acid, partIds);
1596 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1600 afs_int32 VolListPartitions (acid, partIds)
1601 struct rx_call *acid;
1602 struct pIDs *partIds;
1608 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1610 /* Just return attached partitions. */
1612 for (i=0; i<26; i++) {
1613 namehead[6] = i + 'a';
1614 if (VGetPartition(namehead, 0))
1615 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1621 /*return a list of all partitions on the server. The non mounted
1622 *partitions are returned as -1 in the corresponding slot in partIds*/
1623 afs_int32 SAFSVolXListPartitions (acid, pEntries)
1624 struct rx_call *acid;
1625 struct partEntries *pEntries;
1629 code = XVolListPartitions (acid, pEntries);
1630 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1634 afs_int32 XVolListPartitions (acid, pEntries)
1635 struct rx_call *acid;
1636 struct partEntries *pEntries;
1638 struct stat rbuf, pbuf;
1640 struct partList partList;
1641 struct DiskPartition *dp;
1644 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1646 /* Only report attached partitions */
1647 for(i = 0 ; i < VOLMAXPARTS; i++){
1649 namehead[6] = i + 'a';
1653 namehead[6] = 'a' + (k/26);
1654 namehead[7] = 'a' + (k%26);
1657 dp = VGetPartition(namehead, 0);
1659 partList.partId[j++] = i;
1661 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1662 memcpy((char *)pEntries->partEntries_val, (char *)&partList, j * sizeof(int));
1663 pEntries->partEntries_len = j;
1668 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1669 afs_int32 ExtractVolId(vname)
1673 char name[VOLSER_MAXVOLNAME +1];
1677 while(name[i] == 'V' || name[i] == '0')
1680 name[11] = '\0'; /* smash the "." */
1681 return(atol(&name[i]));
1684 /*return the name of the next volume header in the directory associated with dirp and dp.
1685 *the volume id is returned in volid, and volume header name is returned in volname*/
1686 GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
1690 dp = readdir(dirp);/*read next entry in the directory */
1693 if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
1694 *volid = ExtractVolId(dp->d_name);
1695 strcpy(volname,dp->d_name);
1696 return 0;/*return the name of the file representing a volume */
1700 return 0;/*volname doesnot represent a volume*/
1703 else {strcpy(volname,"EOD"); return 0;/*end of directory */}
1707 /*return the header information about the <volid> */
1708 afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
1709 struct rx_call *acid;
1710 afs_int32 volumeId, partid;
1711 volEntries *volumeInfo;
1715 code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
1716 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1720 afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
1721 struct rx_call *acid;
1722 afs_int32 volumeId, partid;
1723 volEntries *volumeInfo;
1725 register struct Volume *tv;
1726 struct DiskPartition *partP;
1727 struct volser_trans *ttc;
1728 char pname[9], volname[20];
1729 afs_int32 error = 0;
1735 volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
1736 pntr = volumeInfo->volEntries_val;
1737 volumeInfo->volEntries_len = 1;
1738 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
1739 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1740 dirp = opendir(VPartitionPath(partP));
1741 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
1743 ttc = (struct volser_trans *) 0;
1744 tv = (Volume *) 0; /* volume not attached */
1746 while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
1748 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
1749 GetNextVol(dirp, volname, &volid);
1750 continue; /*back to while loop */
1753 if(volid == volumeId) { /*copy other things too */
1755 IOMGR_Poll(); /*make sure that the client doesnot time out*/
1756 ttc = NewTrans(volid,partid);
1758 pntr->status = VBUSY;
1759 pntr->volid = volid;
1762 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
1764 pntr->status = 0; /*things are messed up */
1765 strcpy(pntr->name,volname);
1766 pntr->volid = volid;
1767 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
1770 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
1771 /*this volume will be salvaged */
1773 strcpy(pntr->name,volname);
1774 pntr->volid = volid;
1775 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
1779 if(tv->header->diskstuff.needsSalvaged){
1780 /*this volume will be salvaged */
1782 strcpy(pntr->name,volname);
1783 pntr->volid = volid;
1784 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
1788 /*read in the relevant info */
1789 pntr->status = VOK ; /*its ok */
1790 pntr->volid = tv->header->diskstuff.id;
1791 strcpy(pntr->name,tv->header->diskstuff.name);
1792 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
1793 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
1794 pntr->backupID = tv->header->diskstuff.backupId;
1795 pntr->parentID = tv->header->diskstuff.parentId;
1796 pntr->copyDate = tv->header->diskstuff.copyDate;
1797 pntr->inUse = tv->header->diskstuff.inUse;
1798 pntr->size = tv->header->diskstuff.diskused;
1799 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1800 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1801 pntr->maxquota = tv->header->diskstuff.maxquota;
1802 pntr->filecount = tv->header->diskstuff.filecount;
1803 now = FT_ApproxTime();
1804 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1807 pntr->dayUse = tv->header->diskstuff.dayUse;
1808 pntr->creationDate = tv->header->diskstuff.creationDate;
1809 pntr->accessDate = tv->header->diskstuff.accessDate;
1810 pntr->updateDate = tv->header->diskstuff.updateDate;
1811 pntr->backupDate = tv->header->diskstuff.backupDate;
1812 pntr->spare0 = tv->header->diskstuff.minquota;
1813 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
1814 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
1815 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
1816 (long) tv->header->diskstuff.weekUse[6];
1817 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
1818 VDetachVolume(&error,tv);/*free the volume */
1821 pntr->status = 0; /*things are messed up */
1822 strcpy(pntr->name,volname);
1823 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
1827 GetNextVol(dirp, volname, &volid);
1831 VDetachVolume(&error, tv);
1836 ttc = (struct volser_trans *) 0;
1844 /*------------------------------------------------------------------------
1845 * EXPORTED SAFSVolXListOneVolume
1848 * Returns extended info on volume a_volID on partition a_partID.
1851 * a_rxCidP : Pointer to the Rx call we're performing.
1852 * a_partID : Partition for which we want the extended list.
1853 * a_volID : Volume ID we wish to know about.
1854 * a_volumeXInfoP : Ptr to the extended info blob.
1857 * 0 Successful operation
1858 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1861 * Nothing interesting.
1865 *------------------------------------------------------------------------*/
1867 afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1868 struct rx_call *a_rxCidP;
1871 volXEntries *a_volumeXInfoP;
1875 code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1876 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1880 afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1881 struct rx_call *a_rxCidP;
1884 volXEntries *a_volumeXInfoP;
1886 { /*SAFSVolXListOneVolume*/
1888 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
1889 register struct Volume *tv; /*Volume ptr*/
1890 struct volser_trans *ttc; /*Volume transaction ptr*/
1891 struct DiskPartition *partP; /*Ptr to partition */
1892 char pname[9], volname[20]; /*Partition, volume names*/
1893 afs_int32 error; /*Error code*/
1894 afs_int32 code; /*Return code*/
1895 DIR *dirp; /*Partition directory ptr*/
1896 afs_int32 currVolID; /*Current volume ID*/
1897 int found = 0; /*Did we find the volume we need?*/
1898 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
1899 int numStatBytes; /*Num stat bytes to copy per volume*/
1903 * Set up our pointers for action, marking our structure to hold exactly
1904 * one entry. Also, assume we'll fail in our quest.
1906 a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
1907 xInfoP = a_volumeXInfoP->volXEntries_val;
1908 a_volumeXInfoP->volXEntries_len = 1;
1912 * If the partition name we've been given is bad, bogue out.
1914 if (GetPartName(a_partID, pname))
1915 return(VOLSERILLEGAL_PARTITION);
1918 * Open the directory representing the given AFS parttion. If we can't
1921 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1922 dirp = opendir(VPartitionPath(partP));
1924 return(VOLSERILLEGAL_PARTITION);
1927 * Sweep through the partition directory, looking for the desired entry.
1928 * First, of course, figure out how many stat bytes to copy out of each
1931 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
1932 (4*VOLINT_STATS_NUM_TIME_FIELDS));
1933 strcpy(volname, "");
1934 ttc = (struct volser_trans *)0; /*No transaction yet*/
1935 tv = (Volume *)0; /*Volume not yet attached*/
1937 while (strcmp(volname,"EOD") && !found) {
1939 * If this is not a volume, move on to the next entry in the
1940 * partition's directory.
1942 if (!strcmp(volname,"")) {
1943 GetNextVol(dirp, volname, &currVolID);
1947 if (currVolID == a_volID) {
1949 * We found the volume entry we're interested. Pull out the
1950 * extended information, remembering to poll (so that the client
1951 * doesn't time out) and to set up a transaction on the volume.
1955 ttc = NewTrans(currVolID, a_partID);
1958 * Couldn't get a transaction on this volume; let our caller
1961 xInfoP->status = VBUSY;
1962 xInfoP->volid = currVolID;
1967 * Attach the volume, give up on the volume if we can't.
1969 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1971 xInfoP->status = 0; /*things are messed up */
1972 strcpy(xInfoP->name, volname);
1973 xInfoP->volid = currVolID;
1974 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
1980 * Also bag out on this volume if it's been marked as needing a
1981 * salvage or to-be-destroyed.
1983 volDiskDataP = &(tv->header->diskstuff);
1984 if (volDiskDataP->destroyMe == DESTROY_ME) {
1986 strcpy(xInfoP->name, volname);
1987 xInfoP->volid = currVolID;
1988 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
1992 if (volDiskDataP->needsSalvaged) {
1994 strcpy(xInfoP->name, volname);
1995 xInfoP->volid = currVolID;
1996 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
2002 * Pull out the desired info and stuff it into the area we'll be
2003 * returning to our caller.
2005 strcpy(xInfoP->name,volDiskDataP->name);
2006 xInfoP->volid = volDiskDataP->id;
2007 xInfoP->type = volDiskDataP->type;
2008 xInfoP->backupID = volDiskDataP->backupId;
2009 xInfoP->parentID = volDiskDataP->parentId;
2010 xInfoP->cloneID = volDiskDataP->cloneId;
2011 xInfoP->status = VOK;
2012 xInfoP->copyDate = volDiskDataP->copyDate;
2013 xInfoP->inUse = volDiskDataP->inUse;
2014 xInfoP->creationDate = volDiskDataP->creationDate;
2015 xInfoP->accessDate = volDiskDataP->accessDate;
2016 xInfoP->updateDate = volDiskDataP->updateDate;
2017 xInfoP->backupDate = volDiskDataP->backupDate;
2018 now = FT_ApproxTime();
2019 if (now - volDiskDataP->dayUseDate > OneDay)
2022 xInfoP->dayUse = volDiskDataP->dayUse;
2023 xInfoP->filecount = volDiskDataP->filecount;
2024 xInfoP->maxquota = volDiskDataP->maxquota;
2025 xInfoP->size = volDiskDataP->diskused;
2028 * Copy out the stat fields in a single operation.
2030 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2033 * We're done copying. Detach the volume and iterate (at this
2034 * point, since we found our volume, we'll then drop out of the
2037 VDetachVolume(&error, tv);
2041 strcpy(xInfoP->name, volname);
2042 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2048 * At this point, we're golden.
2051 } /*Found desired volume*/
2052 GetNextVol(dirp, volname, &currVolID);
2056 * Drop the transaction we have for this volume.
2060 VDetachVolume(&error, tv);
2065 ttc = (struct volser_trans *)0;
2069 * Clean up before going to dinner: close the partition directory,
2070 * return the proper value.
2075 } /*SAFSVolXListOneVolume*/
2077 /*returns all the volumes on partition partid. If flags = 1 then all the
2078 * relevant info about the volumes is also returned */
2079 afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
2080 struct rx_call *acid;
2081 afs_int32 flags, partid;
2082 volEntries *volumeInfo;
2086 code = VolListVolumes (acid, partid, flags, volumeInfo);
2087 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2091 afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
2092 struct rx_call *acid;
2093 afs_int32 flags, partid;
2094 volEntries *volumeInfo;
2096 register struct Volume *tv;
2097 struct DiskPartition *partP;
2098 struct volser_trans *ttc;
2099 afs_int32 allocSize = 1000;/*to be changed to a larger figure */
2100 char pname[9], volname[20];
2101 afs_int32 error = 0;
2106 volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2107 pntr = volumeInfo->volEntries_val;
2108 volumeInfo->volEntries_len = 0;
2109 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
2110 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2111 dirp = opendir(VPartitionPath(partP));
2112 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2114 while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
2115 ttc = (struct volser_trans *) 0; /* new one for each pass */
2116 tv = (Volume *) 0; /* volume not attached */
2118 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
2119 GetNextVol(dirp, volname, &volid);
2120 continue; /*back to while loop */
2123 if(flags) { /*copy other things too */
2124 IOMGR_Poll(); /*make sure that the client doesnot time out*/
2125 ttc = NewTrans(volid,partid);
2127 pntr->status = VBUSY;
2128 pntr->volid = volid;
2131 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
2133 pntr->status = 0; /*things are messed up */
2134 strcpy(pntr->name,volname);
2135 pntr->volid = volid;
2136 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
2139 if(tv->header->diskstuff.needsSalvaged){
2140 /*this volume will be salvaged */
2142 strcpy(pntr->name,volname);
2143 pntr->volid = volid;
2144 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
2148 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
2149 /*this volume will be salvaged */
2152 /*read in the relevant info */
2153 pntr->status = VOK ; /*its ok */
2154 pntr->volid = tv->header->diskstuff.id;
2155 strcpy(pntr->name,tv->header->diskstuff.name);
2156 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
2157 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
2158 pntr->backupID = tv->header->diskstuff.backupId;
2159 pntr->parentID = tv->header->diskstuff.parentId;
2160 pntr->copyDate = tv->header->diskstuff.copyDate;
2161 pntr->inUse = tv->header->diskstuff.inUse;
2162 pntr->size = tv->header->diskstuff.diskused;
2163 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2164 pntr->maxquota = tv->header->diskstuff.maxquota;
2165 pntr->filecount = tv->header->diskstuff.filecount;
2166 now = FT_ApproxTime();
2167 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2170 pntr->dayUse = tv->header->diskstuff.dayUse;
2171 pntr->creationDate = tv->header->diskstuff.creationDate;
2172 pntr->accessDate = tv->header->diskstuff.accessDate;
2173 pntr->updateDate = tv->header->diskstuff.updateDate;
2174 pntr->backupDate = tv->header->diskstuff.backupDate;
2175 pntr->spare0 = tv->header->diskstuff.minquota;
2176 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
2177 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
2178 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
2179 (long) tv->header->diskstuff.weekUse[6];
2180 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
2181 VDetachVolume(&error,tv);/*free the volume */
2184 pntr->status = 0; /*things are messed up */
2185 strcpy(pntr->name,volname);
2186 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
2190 pntr->volid = volid;
2191 /*just volids are needed*/
2197 ttc = (struct volser_trans *) 0;
2200 volumeInfo->volEntries_len += 1;
2201 if((allocSize - volumeInfo->volEntries_len) < 5) {
2202 /*running out of space, allocate more space */
2203 allocSize = (allocSize *3)/2;
2204 pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
2205 allocSize * sizeof(volintInfo));
2208 VDetachVolume(&error, tv);
2213 ttc = (struct volser_trans *) 0;
2216 return VOLSERNO_MEMORY;
2218 volumeInfo->volEntries_val = pntr; /* point to new block */
2219 /* set pntr to the right position */
2220 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2226 VDetachVolume(&error, tv);
2231 ttc = (struct volser_trans *) 0;
2233 GetNextVol(dirp, volname, &volid);
2243 /*------------------------------------------------------------------------
2244 * EXPORTED SAFSVolXListVolumes
2247 * Returns all the volumes on partition a_partID. If a_flags
2248 * is set to 1, then all the relevant extended volume information
2252 * a_rxCidP : Pointer to the Rx call we're performing.
2253 * a_partID : Partition for which we want the extended list.
2254 * a_flags : Various flags.
2255 * a_volumeXInfoP : Ptr to the extended info blob.
2258 * 0 Successful operation
2259 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2260 * VOLSERNO_MEMORY if we ran out of memory allocating
2264 * Nothing interesting.
2268 *------------------------------------------------------------------------*/
2270 afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2271 struct rx_call *a_rxCidP;
2274 volXEntries *a_volumeXInfoP;
2278 code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2279 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2283 afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2284 struct rx_call *a_rxCidP;
2287 volXEntries *a_volumeXInfoP;
2289 { /*SAFSVolXListVolumes*/
2291 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
2292 register struct Volume *tv; /*Volume ptr*/
2293 struct DiskPartition *partP; /*Ptr to partition*/
2294 struct volser_trans *ttc; /*Volume transaction ptr*/
2295 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2296 char pname[9], volname[20]; /*Partition, volume names*/
2297 afs_int32 error = 0; /*Return code*/
2298 DIR *dirp; /*Partition directory ptr*/
2299 afs_int32 volid; /*Current volume ID*/
2300 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
2301 int numStatBytes; /*Num stat bytes to copy per volume*/
2305 * Allocate a large array of extended volume info structures, then
2306 * set it up for action.
2308 a_volumeXInfoP->volXEntries_val =
2309 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2310 xInfoP = a_volumeXInfoP->volXEntries_val;
2311 a_volumeXInfoP->volXEntries_len = 0;
2314 * If the partition name we've been given is bad, bogue out.
2316 if (GetPartName(a_partID, pname))
2317 return(VOLSERILLEGAL_PARTITION);
2320 * Open the directory representing the given AFS parttion. If we can't
2323 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2324 dirp = opendir(VPartitionPath(partP));
2326 return (VOLSERILLEGAL_PARTITION);
2329 * Sweep through the partition directory, acting on each entry. First,
2330 * of course, figure out how many stat bytes to copy out of each volume.
2332 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
2333 (4*VOLINT_STATS_NUM_TIME_FIELDS));
2335 while (strcmp(volname, "EOD")) {
2336 ttc = (struct volser_trans *)0; /*New one for each pass*/
2337 tv = (Volume *)0; /*Volume not yet attached*/
2340 * If this is not a volume, move on to the next entry in the
2341 * partition's directory.
2343 if(!strcmp(volname,"")) {
2344 GetNextVol(dirp, volname, &volid);
2350 * Full info about the volume desired. Poll to make sure the
2351 * client doesn't time out, then start up a new transaction.
2354 ttc = NewTrans(volid,a_partID);
2357 * Couldn't get a transaction on this volume; let our caller
2360 xInfoP->status = VBUSY;
2361 xInfoP->volid = volid;
2366 * Attach the volume, give up on this volume if we can't.
2368 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2370 xInfoP->status = 0; /*things are messed up */
2371 strcpy(xInfoP->name, volname);
2372 xInfoP->volid = volid;
2373 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2379 * Also bag out on this volume if it's been marked as needing a
2380 * salvage or to-be-destroyed.
2382 volDiskDataP = &(tv->header->diskstuff);
2383 if (volDiskDataP->needsSalvaged) {
2385 strcpy(xInfoP->name, volname);
2386 xInfoP->volid = volid;
2387 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
2392 if (volDiskDataP->destroyMe == DESTROY_ME)
2396 * Pull out the desired info and stuff it into the area we'll be
2397 * returning to our caller.
2399 strcpy(xInfoP->name,volDiskDataP->name);
2400 xInfoP->volid = volDiskDataP->id;
2401 xInfoP->type = volDiskDataP->type;
2402 xInfoP->backupID = volDiskDataP->backupId;
2403 xInfoP->parentID = volDiskDataP->parentId;
2404 xInfoP->cloneID = volDiskDataP->cloneId;
2405 xInfoP->status = VOK;
2406 xInfoP->copyDate = volDiskDataP->copyDate;
2407 xInfoP->inUse = volDiskDataP->inUse;
2408 xInfoP->creationDate = volDiskDataP->creationDate;
2409 xInfoP->accessDate = volDiskDataP->accessDate;
2410 xInfoP->updateDate = volDiskDataP->updateDate;
2411 xInfoP->backupDate = volDiskDataP->backupDate;
2412 now = FT_ApproxTime();
2413 if (now - volDiskDataP->dayUseDate > OneDay)
2416 xInfoP->dayUse = volDiskDataP->dayUse;
2417 xInfoP->filecount = volDiskDataP->filecount;
2418 xInfoP->maxquota = volDiskDataP->maxquota;
2419 xInfoP->size = volDiskDataP->diskused;
2422 * Copy out the stat fields in a single operation.
2424 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2427 * We're done copying. Detach the volume and iterate.
2429 VDetachVolume(&error, tv);
2433 strcpy(xInfoP->name, volname);
2434 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2438 } /*Full contents desired*/
2441 * Just volume IDs are needed.
2443 xInfoP->volid = volid;
2447 * Drop the transaction we have for this volume.
2451 ttc = (struct volser_trans *) 0;
2455 * Bump the pointer in the data area we're building, along with
2456 * the count of the number of entries it contains.
2459 (a_volumeXInfoP->volXEntries_len)++;
2460 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2462 * We're running out of space in the area we've built. Grow it.
2464 allocSize = (allocSize * 3)/2;
2465 xInfoP = (volintXInfo *)
2466 realloc((char *) a_volumeXInfoP->volXEntries_val,
2467 (allocSize * sizeof(volintXInfo)));
2468 if (xInfoP == NULL) {
2470 * Bummer, no memory. Bag it, tell our caller what went wrong.
2473 VDetachVolume(&error, tv);
2478 ttc = (struct volser_trans *) 0;
2481 return(VOLSERNO_MEMORY);
2485 * Memory reallocation worked. Correct our pointers so they
2486 * now point to the new block and the current open position within
2489 a_volumeXInfoP->volXEntries_val = xInfoP;
2490 xInfoP = a_volumeXInfoP->volXEntries_val +
2491 a_volumeXInfoP->volXEntries_len;
2492 } /*Need more space*/
2496 * Detach our current volume and the transaction on it, then move on
2497 * to the next volume in the partition directory.
2500 VDetachVolume(&error, tv);
2505 ttc = (struct volser_trans *) 0;
2507 GetNextVol(dirp, volname, &volid);
2508 } /*Sweep through the partition directory*/
2511 * We've examined all entries in the partition directory. Close it,
2512 * delete our transaction (if any), and go home happy.
2519 } /*SAFSVolXListVolumes*/
2521 /*this call is used to monitor the status of volser for debugging purposes.
2522 *information about all the active transactions is returned in transInfo*/
2523 afs_int32 SAFSVolMonitor (acid,transInfo)
2524 struct rx_call *acid;
2525 transDebugEntries *transInfo;
2529 code = VolMonitor (acid,transInfo);
2530 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2534 afs_int32 VolMonitor (acid,transInfo)
2535 struct rx_call *acid;
2536 transDebugEntries *transInfo;
2538 transDebugInfo *pntr;
2539 afs_int32 allocSize = 50;
2540 struct volser_trans *tt, *allTrans;
2542 transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2543 pntr = transInfo->transDebugEntries_val;
2544 transInfo->transDebugEntries_len = 0;
2545 allTrans = TransList();
2546 if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
2547 for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
2548 pntr->tid = tt->tid;
2549 pntr->time = tt->time;
2550 pntr->creationTime = tt->creationTime;
2551 pntr->returnCode = tt->returnCode;
2552 pntr->volid = tt->volid;
2553 pntr->partition = tt->partition;
2554 pntr->iflags = tt->iflags;
2555 pntr->vflags = tt->vflags;
2556 pntr->tflags = tt->tflags;
2557 strcpy(pntr->lastProcName,tt->lastProcName);
2558 pntr->callValid = 0;
2559 if(tt->rxCallPtr) { /*record call related info */
2560 pntr->callValid = 1;
2561 pntr->readNext = tt->rxCallPtr->rnext;
2562 pntr->transmitNext = tt->rxCallPtr->tnext;
2563 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2564 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2567 transInfo->transDebugEntries_len += 1;
2568 if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
2569 allocSize = (allocSize *3)/2;
2570 pntr = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
2571 transInfo->transDebugEntries_val = pntr;
2572 pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
2573 /*set pntr to right position*/
2581 afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2582 struct rx_call *acid;
2583 afs_int32 type, pId, cloneId, backupId, atid;
2588 code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
2589 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid,
2594 AUD_LONG, backupId, AUD_END);
2598 afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2599 struct rx_call *acid;
2600 afs_int32 type, pId, cloneId, backupId, atid;
2604 afs_int32 error = 0;
2605 register struct volser_trans *tt;
2606 char caller[MAXKTCNAMELEN];
2608 if (strlen(name)>31) return VOLSERBADNAME;
2609 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2610 /* find the trans */
2611 tt = FindTrans(atid);
2612 if (!tt) return ENOENT;
2613 if (tt->vflags & VTDeleted) {
2614 Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
2618 strcpy(tt->lastProcName,"SetIdsTypes");
2619 tt->rxCallPtr = acid;
2623 V_backupId(tv) = backupId;
2624 V_cloneId(tv) = cloneId;
2625 V_parentId(tv) = pId;
2626 strcpy((&V_disk(tv))->name,name);
2627 VUpdateVolume(&error, tv);
2629 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2633 tt->rxCallPtr = (struct rx_call *)0;
2634 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2638 tt->rxCallPtr = (struct rx_call *)0;
2639 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2643 afs_int32 SAFSVolSetDate (acid,atid,cdate)
2644 struct rx_call *acid;
2645 afs_int32 atid, cdate;
2649 code = VolSetDate (acid,atid,cdate);
2650 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
2654 afs_int32 VolSetDate (acid,atid,cdate)
2655 struct rx_call *acid;
2656 afs_int32 atid, cdate;
2659 afs_int32 error = 0;
2660 register struct volser_trans *tt;
2661 char caller[MAXKTCNAMELEN];
2663 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2664 /* find the trans */
2665 tt = FindTrans(atid);
2666 if (!tt) return ENOENT;
2667 if (tt->vflags & VTDeleted) {
2668 Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
2672 strcpy(tt->lastProcName,"SetDate");
2673 tt->rxCallPtr = acid;
2676 V_creationDate(tv) = cdate;
2677 VUpdateVolume(&error, tv);
2679 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2683 tt->rxCallPtr = (struct rx_call *)0;
2684 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2688 tt->rxCallPtr = (struct rx_call *)0;
2689 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2693 /* GetPartName - map partid (a decimal number) into pname (a string)
2694 * Since for NT we actually want to return the drive name, we map through the
2697 static int GetPartName(afs_int32 partid, char *pname)
2702 strcpy(pname,"/vicep");
2703 pname[6] = 'a' + partid;
2706 } else if (partid < VOLMAXPARTS) {
2707 strcpy(pname,"/vicep");
2709 pname[6] = 'a' + (partid / 26);
2710 pname[7] = 'a' + (partid % 26);