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"
67 #include <volser_prototypes.h>
70 extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
71 extern struct afsconf_dir *tdir;
72 extern char *volutil_PartitionName();
74 extern void LogError(afs_int32 errcode);
76 /* Forward declarations */
77 static int GetPartName(afs_int32 partid, char *pname);
79 #define OneDay (24*60*60)
86 afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
87 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
88 afs_int32 VolForwardMultiple();
89 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
90 afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
91 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
93 /* this call unlocks all of the partition locks we've set */
95 register struct DiskPartition *tp;
96 for(tp = DiskPartitionList; tp; tp = tp->next) {
97 if (tp->lock_fd != -1) {
98 close(tp->lock_fd); /* releases flock held on this partition */
105 /* get partition id from a name */
106 afs_int32 PartitionID(aname)
109 register int code = 0;
113 if (tc == 0) return -1; /* unknown */
115 /* otherwise check for vicepa or /vicepa, or just plain "a" */
117 if (!strncmp(aname, "/vicep", 6)) {
118 strncpy(ascii, aname+6, 2);
120 else return -1; /* bad partition name */
121 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
122 from 0. Do the appropriate conversion */
124 /* one char name, 0..25 */
125 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
126 return ascii[0] - 'a';
129 /* two char name, 26 .. <whatever> */
130 if (ascii[0] < 'a' || ascii[0] > 'z') return -1; /* wrongo */
131 if (ascii[1] < 'a' || ascii[1] > 'z') return -1; /* just as bad */
132 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
133 if (code > VOLMAXPARTS) return -1;
138 static int ConvertVolume(avol, aname, asize)
142 if (asize < 18) return -1;
143 /* 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 */
144 (void) afs_snprintf(aname, asize, VFORMAT, (unsigned long) avol);
148 static int ConvertPartition(apartno, aname, asize)
152 if (asize < 10) return E2BIG;
153 if (apartno < 0) return EINVAL;
154 strcpy(aname, "/vicep");
156 aname[6] = 'a'+apartno;
161 aname[6] = 'a' + (apartno / 26);
162 aname[7] = 'a' + (apartno % 26);
168 /* the only attach function that takes a partition is "...ByName", so we use it */
169 struct Volume *XAttachVolume(error, avolid, apartid, amode)
174 char pbuf[30], vbuf[20];
175 register struct Volume *tv;
177 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
181 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
185 tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
189 /* Adapted from the file server; create a root directory for this volume */
190 static ViceCreateRoot(vp)
194 struct acl_accessList * ACL;
196 Inode inodeNumber, nearInode;
197 char buf[SIZEOF_LARGEDISKVNODE];
198 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
199 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
205 memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
207 V_pref(vp, nearInode);
208 inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
209 VPartitionPath(V_partition(vp)), nearInode,
210 V_parentId(vp), 1, 1, 0);
211 assert(VALID_INO(inodeNumber));
213 SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
214 did.Volume = V_id(vp);
215 did.Vnode = (VnodeId)1;
218 assert(!(MakeDir(&dir, &did, &did)));
219 DFlush(); /* flush all modified dir buffers out */
220 DZap(&dir); /* Remove all buffers for this dir */
221 length = Length(&dir); /* Remember size of this directory */
223 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
225 /* build a single entry ACL that gives all rights to system:administrators */
226 /* this section of code assumes that access list format is not going to
229 ACL = VVnodeDiskACL(vnode);
230 ACL->size = sizeof(struct acl_accessList);
231 ACL->version = ACL_ACLVERSION;
235 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
236 ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
238 vnode->type = vDirectory;
240 vnode->modeBits = 0777;
241 vnode->linkCount = 2;
242 VNDISK_SET_LEN(vnode, length);
243 vnode->uniquifier = 1;
244 V_uniquifier(vp) = vnode->uniquifier+1;
245 vnode->dataVersion = 1;
246 VNDISK_SET_INO(vnode, inodeNumber);
247 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
251 vnode->vnodeMagic = vcp->magic;
253 IH_INIT(h, vp->device, V_parentId(vp),
254 vp->vnodeIndex[vLarge].handle->ih_ino);
257 code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
259 code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
260 assert(code == SIZEOF_LARGEDISKVNODE);
261 FDH_REALLYCLOSE(fdP);
263 VNDISK_GET_LEN(length, vnode);
264 V_diskused(vp) = nBlocks(length);
269 afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
270 struct rx_call *acid;
272 struct diskPartition *partition;
276 code = VolPartitionInfo (acid,pname,partition);
277 osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
281 afs_int32 VolPartitionInfo (acid,pname,partition)
282 struct rx_call *acid;
284 struct diskPartition *partition;
286 register struct DiskPartition *dp;
289 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
292 dp = VGetPartition(pname, 0);
294 strncpy(partition->name,dp->name,32);
295 strncpy(partition->devName,dp->devName,32);
296 partition->lock_fd = dp->lock_fd ;
297 partition->free = dp->free;
298 partition->minFree = dp->totalUsable;
302 return VOLSERILLEGAL_PARTITION;
305 /* obliterate a volume completely, and slowly. */
306 afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
307 struct rx_call *acid;
308 afs_int32 apartID, avolID;
312 code = VolNukeVolume (acid, apartID, avolID);
313 osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
317 afs_int32 VolNukeVolume (acid, apartID, avolID)
318 struct rx_call *acid;
319 afs_int32 apartID, avolID;
324 register afs_int32 code;
326 char caller[MAXKTCNAMELEN];
328 /* check for access */
329 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
330 if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
332 tp = volutil_PartitionName(apartID);
333 if (!tp) return VOLSERNOVOL;
334 strcpy(partName, tp); /* remember it for later */
335 /* we first try to attach the volume in update mode, so that the file
336 * server doesn't try to use it (and abort) while (or after) we delete it.
337 * If we don't get the volume, that's fine, too. We just won't put it back.
339 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
340 code = nuke(partName, avolID);
341 if (tvp) VDetachVolume(&error, tvp);
345 /* create a new volume, with name aname, on the specified partition (1..n)
346 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
347 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
348 * for the volume id (useful for things like volume restore).
349 * Return the new volume id in *avolid.
351 afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
352 struct rx_call *acid;
362 code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
363 osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans,
372 afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
373 struct rx_call *acid;
383 afs_int32 junk; /* discardable error code */
384 register afs_int32 volumeID, doCreateRoot=1;
385 register struct volser_trans *tt;
387 char caller[MAXKTCNAMELEN];
389 if (strlen(aname) > 31) return VOLSERBADNAME;
390 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
391 if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
392 if ((error = ConvertPartition(apart, ppath, sizeof(ppath)))) return error;/*a standard unix error*/
393 if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
395 if ((volumeID = *avolid) == 0) {
397 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
401 if ((aparent == volumeID) && (atype == readwriteVolume)) {
404 if (aparent == 0) aparent = volumeID;
405 tt = NewTrans(volumeID, apart);
407 Log("1 createvolume: failed to create trans\n");
408 return VOLSERVOLBUSY; /* volume already busy! */
410 vp = VCreateVolume(&error, ppath, volumeID, aparent);
412 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
417 V_uniquifier(vp) = 1;
418 V_creationDate(vp) = V_copyDate(vp);
419 V_inService(vp) = V_blessed(vp) = 1;
421 AssignVolumeName(&V_disk(vp), aname, 0);
424 V_destroyMe(vp) = DESTROY_ME;
426 V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
427 VUpdateVolume(&error, vp);
429 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
432 VDetachVolume(&junk, vp); /* rather return the real error code */
437 strcpy(tt->lastProcName,"CreateVolume");
438 tt->rxCallPtr = acid;
439 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
440 tt->rxCallPtr = (struct rx_call *)0;
441 if(TRELE(tt)) return VOLSERTRELE_ERROR;
445 /* delete the volume associated with this transaction */
446 afs_int32 SAFSVolDeleteVolume (acid, atrans)
448 struct rx_call *acid;
452 code = VolDeleteVolume (acid, atrans);
453 osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
457 afs_int32 VolDeleteVolume (acid, atrans)
459 struct rx_call *acid;
461 register struct volser_trans *tt;
463 char caller[MAXKTCNAMELEN];
465 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
466 tt = FindTrans(atrans);
467 if (!tt) return ENOENT;
468 if (tt->vflags & VTDeleted) {
469 Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
473 if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
474 strcpy(tt->lastProcName,"DeleteVolume");
475 tt->rxCallPtr = acid;
476 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
477 tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
478 tt->rxCallPtr = (struct rx_call *)0;
479 if(TRELE(tt)) return VOLSERTRELE_ERROR;
481 Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
482 return 0; /* vpurgevolume doesn't set an error code */
485 /* make a clone of the volume associated with atrans, possibly giving it a new
486 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
487 * for the clone's id). The new clone is given the name newName. Finally, due to
488 * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
489 * the clone operation. This may be useful when making new backup volumes, for instance
490 * since the net result of a clone and a purge generally leaves many inode ref counts
491 * the same, while doing them separately would result in far more iincs and idecs being
492 * peformed (and they are slow operations).
494 afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
495 struct rx_call *acid;
498 afs_int32 *newNumber;
499 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
504 code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
505 osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans,
509 AUD_LONG, *newNumber, AUD_END);
513 afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
514 struct rx_call *acid;
517 afs_int32 *newNumber;
518 afs_int32 purgeId; /* for efficiency reasons, sometimes faster to piggyback a purge here */
522 register struct Volume *originalvp, *purgevp, *newvp;
524 register struct volser_trans *tt,*ttc;
525 char caller[MAXKTCNAMELEN];
527 if (strlen(newName)>31) return VOLSERBADNAME;
528 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
529 if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
531 originalvp = (Volume *) 0;
532 purgevp = (Volume *) 0;
533 newvp = (Volume *) 0;
534 tt = ttc = (struct volser_trans *) 0;
536 if (!newNumber || !*newNumber)
538 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
543 if (newType != readonlyVolume && newType != backupVolume)
545 tt = FindTrans(atrans);
546 if (!tt) return ENOENT;
547 if (tt->vflags & VTDeleted) {
548 Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
552 ttc = NewTrans(newId,tt->partition);
554 { /* someone is messing with the clone already */
558 strcpy(tt->lastProcName,"Clone");
559 tt->rxCallPtr = acid;
563 purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
565 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
572 originalvp = tt->volume;
573 if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
574 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
578 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
579 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
585 if (originalvp->device != purgevp->device) {
586 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
590 if (V_type(purgevp) != readonlyVolume) {
591 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
595 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
596 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
600 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
601 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
610 newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
612 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
613 newvp = (Volume *) 0;
616 if (newType == readonlyVolume)
617 V_cloneId(originalvp) = newId;
618 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
620 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
621 CloneVolume(&error, originalvp, newvp, purgevp);
622 purgevp = NULL; /* clone releases it, maybe even if error */
624 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
628 if (newType == readonlyVolume) {
629 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
630 V_type(newvp) = readonlyVolume;
632 else if (newType == backupVolume) {
633 AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
634 V_type(newvp) = backupVolume;
635 V_backupId(originalvp) = newId;
637 strcpy(newvp->header->diskstuff.name,newName);
638 V_creationDate(newvp) = V_copyDate(newvp);
639 ClearVolumeStats(&V_disk(newvp));
640 V_destroyMe(newvp) = DESTROY_ME;
641 V_inService(newvp) = 0;
642 if (newType == backupVolume) {
643 V_backupDate(originalvp) = V_copyDate(newvp);
644 V_backupDate(newvp) = V_copyDate(newvp);
647 VUpdateVolume(&error, newvp);
649 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
653 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
655 VUpdateVolume(&error, originalvp);
657 Log("1 Volser: Clone: original update %u\n", error);
661 tt->rxCallPtr = (struct rx_call *)0;
663 tt = (struct volser_trans *) 0;
664 error = VOLSERTRELE_ERROR;
671 if (purgevp) VDetachVolume(&code, purgevp);
672 if (newvp) VDetachVolume(&code, newvp);
674 tt->rxCallPtr = (struct rx_call *)0;
677 if(ttc) DeleteTrans(ttc);
681 /* reclone this volume into the specified id */
682 afs_int32 SAFSVolReClone (acid, atrans, cloneId)
683 struct rx_call *acid;
689 code = VolReClone (acid, atrans, cloneId);
690 osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
694 afs_int32 VolReClone (acid, atrans, cloneId)
695 struct rx_call *acid;
699 register struct Volume *originalvp, *clonevp;
702 register struct volser_trans *tt,*ttc;
703 char caller[MAXKTCNAMELEN];
706 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
707 if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
709 clonevp = originalvp = (Volume *) 0;
710 tt = (struct volser_trans *) 0;
712 tt = FindTrans(atrans);
713 if (!tt) return ENOENT;
714 if (tt->vflags & VTDeleted) {
715 Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
719 ttc = NewTrans(cloneId, tt->partition);
720 if (!ttc){ /* someone is messing with the clone already */
724 strcpy(tt->lastProcName,"ReClone");
725 tt->rxCallPtr = acid;
727 originalvp = tt->volume;
728 if ((V_type(originalvp) == backupVolume) ||
729 (V_type(originalvp) == readonlyVolume)){
730 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
734 if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
735 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
741 clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
743 Log("1 Volser: can't attach clone %d\n", cloneId);
747 newType = V_type(clonevp); /* type of the new volume */
749 if (originalvp->device != clonevp->device) {
750 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
754 if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
755 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
759 if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
760 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
764 if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
765 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
772 Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
774 CloneVolume(&error, originalvp, clonevp, clonevp);
776 Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
781 /* fix up volume name and type, CloneVolume just propagated RW's */
782 if (newType == readonlyVolume) {
783 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
784 V_type(clonevp) = readonlyVolume;
786 else if (newType == backupVolume) {
787 AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
788 V_type(clonevp) = backupVolume;
789 V_backupId(originalvp) = cloneId;
791 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
793 /* pretend recloned volume is a totally new instance */
794 V_copyDate(clonevp) = time(0);
795 V_creationDate(clonevp) = V_copyDate(clonevp);
796 ClearVolumeStats(&V_disk(clonevp));
797 V_destroyMe(clonevp) = 0;
798 V_inService(clonevp) = 0;
799 if (newType == backupVolume) {
800 V_backupDate(originalvp) = V_copyDate(clonevp);
801 V_backupDate(clonevp) = V_copyDate(clonevp);
803 V_inUse(clonevp) = 0;
804 VUpdateVolume(&error, clonevp);
806 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
810 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
812 VUpdateVolume(&error, originalvp);
814 Log("1 Volser: Clone: original update %u\n", error);
818 tt->rxCallPtr = (struct rx_call *)0;
820 tt = (struct volser_trans *) 0;
821 error = VOLSERTRELE_ERROR;
828 struct DiskPartition *tpartp = originalvp->partition;
829 FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
834 if (clonevp) VDetachVolume(&code, clonevp);
836 tt->rxCallPtr = (struct rx_call *)0;
839 if(ttc) DeleteTrans(ttc);
843 /* create a new transaction, associated with volume and partition. Type of
844 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
845 * See volser.h for definition of iflags (the constants are named IT*).
847 afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
848 struct rx_call *acid;
856 code = VolTransCreate (acid, volume, partition, iflags, ttid);
857 osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
861 afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
862 struct rx_call *acid;
868 register struct volser_trans *tt;
870 afs_int32 error, code;
872 char caller[MAXKTCNAMELEN];
874 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
875 if (iflags & ITCreate) mode = V_SECRETLY;
876 else if (iflags & ITBusy) mode = V_CLONE;
877 else if (iflags & ITReadOnly) mode = V_READONLY;
878 else if (iflags & ITOffline) mode = V_VOLUPD;
880 Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
884 tt = NewTrans(volume, partition);
886 /* can't create a transaction? put the volume back */
887 Log("1 transcreate: can't create transaction\n");
888 return VOLSERVOLBUSY;
890 tv = XAttachVolume(&error, volume, partition, mode);
893 if (tv) VDetachVolume(&code, tv);
901 strcpy(tt->lastProcName,"TransCreate");
902 if(TRELE(tt)) return VOLSERTRELE_ERROR;
907 /* using aindex as a 0-based index, return the aindex'th volume on this server
908 * Both the volume number and partition number (one-based) are returned.
910 afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
911 struct rx_call *acid;
918 code = VolGetNthVolume (acid, aindex, avolume, apart);
919 osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
923 afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
924 struct rx_call *acid;
929 Log("1 Volser: GetNthVolume: Not yet implemented\n");
933 /* return the volume flags (VT* constants in volser.h) associated with this
936 afs_int32 SAFSVolGetFlags (acid, atid, aflags)
937 struct rx_call *acid;
943 code = VolGetFlags (acid, atid, aflags);
944 osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
948 afs_int32 VolGetFlags (acid, atid, aflags)
949 struct rx_call *acid;
953 register struct volser_trans *tt;
955 tt = FindTrans(atid);
956 if (!tt) return ENOENT;
957 if (tt->vflags & VTDeleted) {
958 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
962 strcpy(tt->lastProcName,"GetFlags");
963 tt->rxCallPtr = acid;
964 *aflags = tt->vflags;
965 tt->rxCallPtr = (struct rx_call *)0;
966 if(TRELE(tt)) return VOLSERTRELE_ERROR;
971 /* Change the volume flags (VT* constants in volser.h) associated with this
972 * transaction. Effects take place immediately on volume, although volume
973 * remains attached as usual by the transaction.
975 afs_int32 SAFSVolSetFlags (acid, atid, aflags)
976 struct rx_call *acid;
982 code = VolSetFlags (acid, atid, aflags);
983 osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
987 afs_int32 VolSetFlags (acid, atid, aflags)
988 struct rx_call *acid;
992 register struct volser_trans *tt;
993 register struct Volume *vp;
995 char caller[MAXKTCNAMELEN];
997 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
999 tt = FindTrans(atid);
1000 if (!tt) return ENOENT;
1001 if (tt->vflags & VTDeleted) {
1002 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
1006 strcpy(tt->lastProcName,"SetFlags");
1007 tt->rxCallPtr = acid;
1008 vp = tt->volume; /* pull volume out of transaction */
1010 /* check if we're allowed to make any updates */
1011 if (tt->iflags & ITReadOnly) {
1016 /* handle delete-on-salvage flag */
1017 if (aflags & VTDeleteOnSalvage) {
1018 V_destroyMe(tt->volume) = DESTROY_ME;
1021 V_destroyMe(tt->volume) = 0;
1024 if (aflags & VTOutOfService) {
1025 V_inService(vp) = 0;
1028 V_inService(vp) = 1;
1030 VUpdateVolume(&error, vp);
1031 tt->vflags = aflags;
1032 tt->rxCallPtr = (struct rx_call *)0;
1033 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
1038 /* dumpS the volume associated with a particular transaction from a particular
1039 * date. Send the dump to a different transaction (destTrans) on the server
1040 * specified by the destServer structure.
1042 afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1043 struct rx_call *acid;
1044 afs_int32 fromTrans;
1046 struct destServer *destination;
1047 struct restoreCookie *cookie;
1048 afs_int32 destTrans;
1052 code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
1053 osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans,
1054 AUD_HOST, destination->destHost,
1055 AUD_LONG, destTrans, AUD_END);
1059 afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
1060 struct rx_call *acid;
1061 afs_int32 fromTrans;
1063 struct destServer *destination;
1064 struct restoreCookie *cookie;
1065 afs_int32 destTrans;
1067 register struct volser_trans *tt;
1068 register afs_int32 code;
1069 register struct rx_connection *tcon;
1070 struct rx_call *tcall;
1071 register struct Volume *vp;
1072 struct rx_securityClass *securityObject;
1073 afs_int32 securityIndex;
1074 char caller[MAXKTCNAMELEN];
1076 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1077 /* initialize things */
1078 tcon = (struct rx_connection *) 0;
1079 tt = (struct volser_trans *) 0;
1081 /* find the local transaction */
1082 tt = FindTrans(fromTrans);
1083 if (!tt) return ENOENT;
1084 if (tt->vflags & VTDeleted) {
1085 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1090 strcpy(tt->lastProcName,"Forward");
1092 /* get auth info for the this connection (uses afs from ticket file) */
1093 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1099 /* make an rpc connection to the other server */
1100 tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
1102 tt->rxCallPtr = (struct rx_call *)0;
1106 tcall = rx_NewCall(tcon);
1107 tt->rxCallPtr = tcall;
1108 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1109 code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
1114 /* these next calls implictly call rx_Write when writing out data */
1115 code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
1116 if (code) goto fail;
1117 EndAFSVolRestore(tcall); /* probably doesn't do much */
1118 tt->rxCallPtr = (struct rx_call *)0;
1119 code = rx_EndCall(tcall, 0);
1120 rx_DestroyConnection(tcon); /* done with the connection */
1122 if (code) goto fail;
1123 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1129 (void) rx_EndCall(tcall,0);
1130 rx_DestroyConnection(tcon);
1133 tt->rxCallPtr = (struct rx_call *)0;
1139 /* Start a dump and send it to multiple places simultaneously.
1140 * If this returns an error (eg, return ENOENT), it means that
1141 * none of the releases worked. If this returns 0, that means
1142 * that one or more of the releases worked, and the caller has
1143 * to examine the results array to see which one(s).
1144 * This will only do EITHER incremental or full, not both, so it's
1145 * the caller's responsibility to be sure that all the destinations
1146 * need just an incremental (and from the same time), if that's
1149 afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations,
1150 spare, cookie, results)
1151 struct rx_call *acid;
1152 afs_int32 fromTrans;
1155 manyDests *destinations;
1156 struct restoreCookie *cookie;
1157 manyResults *results;
1159 afs_int32 securityIndex;
1160 struct rx_securityClass *securityObject;
1161 char caller[MAXKTCNAMELEN];
1162 struct volser_trans *tt;
1163 afs_int32 ec, code, *codes;
1164 struct rx_connection **tcons;
1165 struct rx_call **tcalls;
1167 int i, nconns, is_incremental;
1170 memset(results, 0, sizeof(manyResults));
1172 if (!afsconf_SuperUser(tdir, acid, caller))
1173 return VOLSERBAD_ACCESS;/*not a super user*/
1174 tt = FindTrans(fromTrans);
1177 if (tt->vflags & VTDeleted) {
1178 Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
1183 strcpy(tt->lastProcName, "ForwardMulti");
1185 /* (fromDate == 0) ==> incremental dump */
1186 is_incremental = (fromDate ? 1 : 0);
1188 i= results->manyResults_len = destinations->manyDests_len;
1189 results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
1190 tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
1191 tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
1193 /* get auth info for this connection (uses afs from ticket file) */
1194 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1196 goto fail; /* in order to audit each failure */
1199 /* make connections to all the other servers */
1200 for (i=0; i < destinations->manyDests_len; i++) {
1201 struct replica *dest = &(destinations->manyDests_val[i]);
1202 tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
1203 htons(dest->server.destPort),
1204 VOLSERVICE_ID, securityObject, securityIndex);
1206 codes[i] = ENOTCONN;
1209 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1212 codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
1213 is_incremental,cookie);
1215 (void) rx_EndCall (tcalls[i],0); tcalls[i] = 0;
1216 rx_DestroyConnection(tcons[i]); tcons[i] = 0;
1222 /* these next calls implictly call rx_Write when writing out data */
1223 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1227 for (i--; i >=0 ; i--) {
1228 struct replica *dest = &(destinations->manyDests_val[i]);
1230 if (!code && tcalls[i] && !codes[i]) {
1231 EndAFSVolRestore(tcalls[i]);
1234 ec = rx_EndCall(tcalls[i], 0);
1235 if (!codes[i]) codes[i] = ec;
1238 rx_DestroyConnection(tcons[i]); /* done with the connection */
1241 osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]),
1242 AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost,
1243 AUD_LONG, dest->trans, AUD_END);
1249 tt->rxCallPtr = (struct rx_call *)0;
1250 if(TRELE(tt) && !code) /* return the first code if it's set */
1251 return VOLSERTRELE_ERROR;
1257 afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
1258 struct rx_call *acid;
1259 afs_int32 fromTrans;
1264 code = VolDump (acid, fromTrans, fromDate);
1265 osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
1269 afs_int32 VolDump (acid, fromTrans, fromDate)
1270 struct rx_call *acid;
1271 afs_int32 fromTrans;
1275 register struct volser_trans *tt;
1276 char caller[MAXKTCNAMELEN];
1278 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1279 tt = FindTrans(fromTrans);
1280 if (!tt) return ENOENT;
1281 if (tt->vflags & VTDeleted) {
1282 Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
1286 strcpy(tt->lastProcName,"Dump");
1287 tt->rxCallPtr = acid;
1288 code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
1289 if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
1290 tt->rxCallPtr = (struct rx_call *)0;
1292 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1298 * Ha! No more helper process!
1300 afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
1301 struct rx_call *acid;
1304 struct restoreCookie *cookie;
1308 code = VolRestore (acid, atrans, aflags,cookie);
1309 osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
1313 afs_int32 VolRestore (acid, atrans, aflags,cookie)
1314 struct rx_call *acid;
1317 struct restoreCookie *cookie;
1319 register struct volser_trans *tt;
1320 register afs_int32 code,tcode;
1321 char caller[MAXKTCNAMELEN];
1323 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1324 tt = FindTrans(atrans);
1325 if (!tt) return ENOENT;
1326 if (tt->vflags & VTDeleted) {
1327 Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
1331 strcpy(tt->lastProcName,"Restore");
1332 tt->rxCallPtr = acid;
1333 code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie); /* last is incrementalp */
1334 FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
1336 tt->rxCallPtr = (struct rx_call *)0;
1339 return (code? code : tcode);
1342 /* end a transaction, returning the transaction's final error code in rcode */
1343 afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
1344 struct rx_call *acid;
1345 afs_int32 destTrans;
1350 code = VolEndTrans (acid, destTrans, rcode);
1351 osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
1355 afs_int32 VolEndTrans (acid, destTrans, rcode)
1356 struct rx_call *acid;
1357 afs_int32 destTrans;
1360 register struct volser_trans *tt;
1361 char caller[MAXKTCNAMELEN];
1363 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1364 tt = FindTrans(destTrans);
1365 if (!tt) {return ENOENT;}
1366 *rcode = tt->returnCode;
1367 DeleteTrans(tt); /* this does an implicit TRELE */
1372 afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
1373 struct rx_call *acid;
1379 code = VolSetForwarding (acid, atid, anewsite);
1380 osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
1384 afs_int32 VolSetForwarding (acid, atid, anewsite)
1385 struct rx_call *acid;
1390 register struct volser_trans *tt;
1391 char caller[MAXKTCNAMELEN];
1393 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1394 tt = FindTrans(atid);
1395 if (!tt) return ENOENT;
1396 if (tt->vflags & VTDeleted) {
1397 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
1401 strcpy(tt->lastProcName,"SetForwarding");
1402 tt->rxCallPtr = acid;
1403 FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
1404 tt->rxCallPtr = (struct rx_call *)0;
1405 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1410 afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
1411 struct rx_call *acid;
1413 register struct volser_status *astatus;
1417 code = VolGetStatus (acid, atrans, astatus);
1418 osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
1422 afs_int32 VolGetStatus (acid, atrans, astatus)
1423 struct rx_call *acid;
1425 register struct volser_status *astatus;
1427 register struct Volume *tv;
1428 register struct VolumeDiskData *td;
1429 struct volser_trans *tt;
1432 tt = FindTrans(atrans);
1433 if (!tt) return ENOENT;
1434 if (tt->vflags & VTDeleted) {
1435 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
1439 strcpy(tt->lastProcName,"GetStatus");
1440 tt->rxCallPtr = acid;
1443 tt->rxCallPtr = (struct rx_call *)0;
1448 td = &tv->header->diskstuff;
1449 astatus->volID = td->id;
1450 astatus->nextUnique = td->uniquifier;
1451 astatus->type = td->type;
1452 astatus->parentID = td->parentId;
1453 astatus->cloneID = td->cloneId;
1454 astatus->backupID = td->backupId;
1455 astatus->restoredFromID = td->restoredFromId;
1456 astatus->maxQuota = td->maxquota;
1457 astatus->minQuota = td->minquota;
1458 astatus->owner = td->owner;
1459 astatus->creationDate = td->creationDate;
1460 astatus->accessDate = td->accessDate;
1461 astatus->updateDate = td->updateDate;
1462 astatus->expirationDate = td->expirationDate;
1463 astatus->backupDate = td->backupDate;
1464 astatus->copyDate = td->copyDate;
1465 tt->rxCallPtr = (struct rx_call *)0;
1466 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1471 afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
1472 struct rx_call *acid;
1474 register struct volintInfo *astatus;
1478 code = VolSetInfo (acid, atrans, astatus);
1479 osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
1483 afs_int32 VolSetInfo (acid, atrans, astatus)
1484 struct rx_call *acid;
1486 register struct volintInfo *astatus;
1488 register struct Volume *tv;
1489 register struct VolumeDiskData *td;
1490 struct volser_trans *tt;
1491 char caller[MAXKTCNAMELEN];
1494 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
1495 tt = FindTrans(atrans);
1496 if (!tt) return ENOENT;
1497 if (tt->vflags & VTDeleted) {
1498 Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
1502 strcpy(tt->lastProcName,"SetStatus");
1503 tt->rxCallPtr = acid;
1506 tt->rxCallPtr = (struct rx_call *)0;
1511 td = &tv->header->diskstuff;
1513 * Add more fields as necessary
1515 if (astatus->maxquota != -1)
1516 td->maxquota = astatus->maxquota;
1517 if (astatus->dayUse != -1)
1518 td->dayUse = astatus->dayUse;
1519 VUpdateVolume(&error, tv);
1520 tt->rxCallPtr = (struct rx_call *)0;
1521 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1526 afs_int32 SAFSVolGetName (acid, atrans, aname)
1527 struct rx_call *acid;
1533 code = VolGetName (acid, atrans, aname);
1534 osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
1538 afs_int32 VolGetName (acid, atrans, aname)
1539 struct rx_call *acid;
1543 register struct Volume *tv;
1544 register struct VolumeDiskData *td;
1545 struct volser_trans *tt;
1549 tt = FindTrans(atrans);
1550 if (!tt) return ENOENT;
1551 if (tt->vflags & VTDeleted) {
1552 Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
1556 strcpy(tt->lastProcName,"GetName");
1557 tt->rxCallPtr = acid;
1560 tt->rxCallPtr = (struct rx_call *)0;
1565 td = &tv->header->diskstuff;
1566 len = strlen(td->name)+1; /* don't forget the null */
1568 tt->rxCallPtr = (struct rx_call *)0;
1572 *aname = (char *)malloc(len);
1573 strcpy(*aname, td->name);
1574 tt->rxCallPtr = (struct rx_call *)0;
1575 if(TRELE(tt)) return VOLSERTRELE_ERROR;
1579 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1581 afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
1582 struct rx_call *acid;
1584 afs_int32 parentId, cloneId;
1591 /*return a list of all partitions on the server. The non mounted
1592 *partitions are returned as -1 in the corresponding slot in partIds*/
1593 afs_int32 SAFSVolListPartitions (acid, partIds)
1594 struct rx_call *acid;
1595 struct pIDs *partIds;
1599 code = VolListPartitions (acid, partIds);
1600 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1604 afs_int32 VolListPartitions (acid, partIds)
1605 struct rx_call *acid;
1606 struct pIDs *partIds;
1612 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1614 /* Just return attached partitions. */
1616 for (i=0; i<26; i++) {
1617 namehead[6] = i + 'a';
1618 if (VGetPartition(namehead, 0))
1619 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1625 /*return a list of all partitions on the server. The non mounted
1626 *partitions are returned as -1 in the corresponding slot in partIds*/
1627 afs_int32 SAFSVolXListPartitions (acid, pEntries)
1628 struct rx_call *acid;
1629 struct partEntries *pEntries;
1633 code = XVolListPartitions (acid, pEntries);
1634 osi_auditU(acid, VS_ListParEvent, code, AUD_END);
1638 afs_int32 XVolListPartitions (acid, pEntries)
1639 struct rx_call *acid;
1640 struct partEntries *pEntries;
1642 struct stat rbuf, pbuf;
1644 struct partList partList;
1645 struct DiskPartition *dp;
1648 strcpy(namehead, "/vicep"); /*7 including null terminator*/
1650 /* Only report attached partitions */
1651 for(i = 0 ; i < VOLMAXPARTS; i++){
1653 namehead[6] = i + 'a';
1657 namehead[6] = 'a' + (k/26);
1658 namehead[7] = 'a' + (k%26);
1661 dp = VGetPartition(namehead, 0);
1663 partList.partId[j++] = i;
1665 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1666 memcpy((char *)pEntries->partEntries_val, (char *)&partList, j * sizeof(int));
1667 pEntries->partEntries_len = j;
1672 /*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1673 afs_int32 ExtractVolId(vname)
1677 char name[VOLSER_MAXVOLNAME +1];
1681 while(name[i] == 'V' || name[i] == '0')
1684 name[11] = '\0'; /* smash the "." */
1685 return(atol(&name[i]));
1688 /*return the name of the next volume header in the directory associated with dirp and dp.
1689 *the volume id is returned in volid, and volume header name is returned in volname*/
1690 GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
1694 dp = readdir(dirp);/*read next entry in the directory */
1697 if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
1698 *volid = ExtractVolId(dp->d_name);
1699 strcpy(volname,dp->d_name);
1700 return 0;/*return the name of the file representing a volume */
1704 return 0;/*volname doesnot represent a volume*/
1707 else {strcpy(volname,"EOD"); return 0;/*end of directory */}
1711 /*return the header information about the <volid> */
1712 afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
1713 struct rx_call *acid;
1714 afs_int32 volumeId, partid;
1715 volEntries *volumeInfo;
1719 code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
1720 osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
1724 afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
1725 struct rx_call *acid;
1726 afs_int32 volumeId, partid;
1727 volEntries *volumeInfo;
1729 register struct Volume *tv;
1730 struct DiskPartition *partP;
1731 struct volser_trans *ttc;
1732 char pname[9], volname[20];
1733 afs_int32 error = 0;
1739 volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
1740 pntr = volumeInfo->volEntries_val;
1741 volumeInfo->volEntries_len = 1;
1742 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
1743 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1744 dirp = opendir(VPartitionPath(partP));
1745 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
1747 ttc = (struct volser_trans *) 0;
1748 tv = (Volume *) 0; /* volume not attached */
1750 while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
1752 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
1753 GetNextVol(dirp, volname, &volid);
1754 continue; /*back to while loop */
1757 if(volid == volumeId) { /*copy other things too */
1759 IOMGR_Poll(); /*make sure that the client doesnot time out*/
1760 ttc = NewTrans(volid,partid);
1762 pntr->status = VBUSY;
1763 pntr->volid = volid;
1766 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
1768 pntr->status = 0; /*things are messed up */
1769 strcpy(pntr->name,volname);
1770 pntr->volid = volid;
1771 Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
1774 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
1775 /*this volume will be salvaged */
1777 strcpy(pntr->name,volname);
1778 pntr->volid = volid;
1779 Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
1783 if(tv->header->diskstuff.needsSalvaged){
1784 /*this volume will be salvaged */
1786 strcpy(pntr->name,volname);
1787 pntr->volid = volid;
1788 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
1792 /*read in the relevant info */
1793 pntr->status = VOK ; /*its ok */
1794 pntr->volid = tv->header->diskstuff.id;
1795 strcpy(pntr->name,tv->header->diskstuff.name);
1796 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
1797 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
1798 pntr->backupID = tv->header->diskstuff.backupId;
1799 pntr->parentID = tv->header->diskstuff.parentId;
1800 pntr->copyDate = tv->header->diskstuff.copyDate;
1801 pntr->inUse = tv->header->diskstuff.inUse;
1802 pntr->size = tv->header->diskstuff.diskused;
1803 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
1804 pntr->destroyMe = tv->header->diskstuff.destroyMe;
1805 pntr->maxquota = tv->header->diskstuff.maxquota;
1806 pntr->filecount = tv->header->diskstuff.filecount;
1807 now = FT_ApproxTime();
1808 if (now - tv->header->diskstuff.dayUseDate > OneDay)
1811 pntr->dayUse = tv->header->diskstuff.dayUse;
1812 pntr->creationDate = tv->header->diskstuff.creationDate;
1813 pntr->accessDate = tv->header->diskstuff.accessDate;
1814 pntr->updateDate = tv->header->diskstuff.updateDate;
1815 pntr->backupDate = tv->header->diskstuff.backupDate;
1816 pntr->spare0 = tv->header->diskstuff.minquota;
1817 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
1818 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
1819 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
1820 (long) tv->header->diskstuff.weekUse[6];
1821 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
1822 VDetachVolume(&error,tv);/*free the volume */
1825 pntr->status = 0; /*things are messed up */
1826 strcpy(pntr->name,volname);
1827 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
1831 GetNextVol(dirp, volname, &volid);
1835 VDetachVolume(&error, tv);
1840 ttc = (struct volser_trans *) 0;
1848 /*------------------------------------------------------------------------
1849 * EXPORTED SAFSVolXListOneVolume
1852 * Returns extended info on volume a_volID on partition a_partID.
1855 * a_rxCidP : Pointer to the Rx call we're performing.
1856 * a_partID : Partition for which we want the extended list.
1857 * a_volID : Volume ID we wish to know about.
1858 * a_volumeXInfoP : Ptr to the extended info blob.
1861 * 0 Successful operation
1862 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
1865 * Nothing interesting.
1869 *------------------------------------------------------------------------*/
1871 afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1872 struct rx_call *a_rxCidP;
1875 volXEntries *a_volumeXInfoP;
1879 code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
1880 osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
1884 afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
1885 struct rx_call *a_rxCidP;
1888 volXEntries *a_volumeXInfoP;
1890 { /*SAFSVolXListOneVolume*/
1892 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
1893 register struct Volume *tv; /*Volume ptr*/
1894 struct volser_trans *ttc; /*Volume transaction ptr*/
1895 struct DiskPartition *partP; /*Ptr to partition */
1896 char pname[9], volname[20]; /*Partition, volume names*/
1897 afs_int32 error; /*Error code*/
1898 afs_int32 code; /*Return code*/
1899 DIR *dirp; /*Partition directory ptr*/
1900 afs_int32 currVolID; /*Current volume ID*/
1901 int found = 0; /*Did we find the volume we need?*/
1902 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
1903 int numStatBytes; /*Num stat bytes to copy per volume*/
1907 * Set up our pointers for action, marking our structure to hold exactly
1908 * one entry. Also, assume we'll fail in our quest.
1910 a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
1911 xInfoP = a_volumeXInfoP->volXEntries_val;
1912 a_volumeXInfoP->volXEntries_len = 1;
1916 * If the partition name we've been given is bad, bogue out.
1918 if (GetPartName(a_partID, pname))
1919 return(VOLSERILLEGAL_PARTITION);
1922 * Open the directory representing the given AFS parttion. If we can't
1925 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
1926 dirp = opendir(VPartitionPath(partP));
1928 return(VOLSERILLEGAL_PARTITION);
1931 * Sweep through the partition directory, looking for the desired entry.
1932 * First, of course, figure out how many stat bytes to copy out of each
1935 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
1936 (4*VOLINT_STATS_NUM_TIME_FIELDS));
1937 strcpy(volname, "");
1938 ttc = (struct volser_trans *)0; /*No transaction yet*/
1939 tv = (Volume *)0; /*Volume not yet attached*/
1941 while (strcmp(volname,"EOD") && !found) {
1943 * If this is not a volume, move on to the next entry in the
1944 * partition's directory.
1946 if (!strcmp(volname,"")) {
1947 GetNextVol(dirp, volname, &currVolID);
1951 if (currVolID == a_volID) {
1953 * We found the volume entry we're interested. Pull out the
1954 * extended information, remembering to poll (so that the client
1955 * doesn't time out) and to set up a transaction on the volume.
1959 ttc = NewTrans(currVolID, a_partID);
1962 * Couldn't get a transaction on this volume; let our caller
1965 xInfoP->status = VBUSY;
1966 xInfoP->volid = currVolID;
1971 * Attach the volume, give up on the volume if we can't.
1973 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
1975 xInfoP->status = 0; /*things are messed up */
1976 strcpy(xInfoP->name, volname);
1977 xInfoP->volid = currVolID;
1978 Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
1984 * Also bag out on this volume if it's been marked as needing a
1985 * salvage or to-be-destroyed.
1987 volDiskDataP = &(tv->header->diskstuff);
1988 if (volDiskDataP->destroyMe == DESTROY_ME) {
1990 strcpy(xInfoP->name, volname);
1991 xInfoP->volid = currVolID;
1992 Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
1996 if (volDiskDataP->needsSalvaged) {
1998 strcpy(xInfoP->name, volname);
1999 xInfoP->volid = currVolID;
2000 Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
2006 * Pull out the desired info and stuff it into the area we'll be
2007 * returning to our caller.
2009 strcpy(xInfoP->name,volDiskDataP->name);
2010 xInfoP->volid = volDiskDataP->id;
2011 xInfoP->type = volDiskDataP->type;
2012 xInfoP->backupID = volDiskDataP->backupId;
2013 xInfoP->parentID = volDiskDataP->parentId;
2014 xInfoP->cloneID = volDiskDataP->cloneId;
2015 xInfoP->status = VOK;
2016 xInfoP->copyDate = volDiskDataP->copyDate;
2017 xInfoP->inUse = volDiskDataP->inUse;
2018 xInfoP->creationDate = volDiskDataP->creationDate;
2019 xInfoP->accessDate = volDiskDataP->accessDate;
2020 xInfoP->updateDate = volDiskDataP->updateDate;
2021 xInfoP->backupDate = volDiskDataP->backupDate;
2022 now = FT_ApproxTime();
2023 if (now - volDiskDataP->dayUseDate > OneDay)
2026 xInfoP->dayUse = volDiskDataP->dayUse;
2027 xInfoP->filecount = volDiskDataP->filecount;
2028 xInfoP->maxquota = volDiskDataP->maxquota;
2029 xInfoP->size = volDiskDataP->diskused;
2032 * Copy out the stat fields in a single operation.
2034 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2037 * We're done copying. Detach the volume and iterate (at this
2038 * point, since we found our volume, we'll then drop out of the
2041 VDetachVolume(&error, tv);
2045 strcpy(xInfoP->name, volname);
2046 Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
2052 * At this point, we're golden.
2055 } /*Found desired volume*/
2056 GetNextVol(dirp, volname, &currVolID);
2060 * Drop the transaction we have for this volume.
2064 VDetachVolume(&error, tv);
2069 ttc = (struct volser_trans *)0;
2073 * Clean up before going to dinner: close the partition directory,
2074 * return the proper value.
2079 } /*SAFSVolXListOneVolume*/
2081 /*returns all the volumes on partition partid. If flags = 1 then all the
2082 * relevant info about the volumes is also returned */
2083 afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
2084 struct rx_call *acid;
2085 afs_int32 flags, partid;
2086 volEntries *volumeInfo;
2090 code = VolListVolumes (acid, partid, flags, volumeInfo);
2091 osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
2095 afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
2096 struct rx_call *acid;
2097 afs_int32 flags, partid;
2098 volEntries *volumeInfo;
2100 register struct Volume *tv;
2101 struct DiskPartition *partP;
2102 struct volser_trans *ttc;
2103 afs_int32 allocSize = 1000;/*to be changed to a larger figure */
2104 char pname[9], volname[20];
2105 afs_int32 error = 0;
2110 volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2111 pntr = volumeInfo->volEntries_val;
2112 volumeInfo->volEntries_len = 0;
2113 if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
2114 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2115 dirp = opendir(VPartitionPath(partP));
2116 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2118 while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
2119 ttc = (struct volser_trans *) 0; /* new one for each pass */
2120 tv = (Volume *) 0; /* volume not attached */
2122 if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
2123 GetNextVol(dirp, volname, &volid);
2124 continue; /*back to while loop */
2127 if(flags) { /*copy other things too */
2128 IOMGR_Poll(); /*make sure that the client doesnot time out*/
2129 ttc = NewTrans(volid,partid);
2131 pntr->status = VBUSY;
2132 pntr->volid = volid;
2135 tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
2137 pntr->status = 0; /*things are messed up */
2138 strcpy(pntr->name,volname);
2139 pntr->volid = volid;
2140 Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
2143 if(tv->header->diskstuff.needsSalvaged){
2144 /*this volume will be salvaged */
2146 strcpy(pntr->name,volname);
2147 pntr->volid = volid;
2148 Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
2152 if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
2153 /*this volume will be salvaged */
2156 /*read in the relevant info */
2157 pntr->status = VOK ; /*its ok */
2158 pntr->volid = tv->header->diskstuff.id;
2159 strcpy(pntr->name,tv->header->diskstuff.name);
2160 pntr->type = tv->header->diskstuff.type; /*if ro volume*/
2161 pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
2162 pntr->backupID = tv->header->diskstuff.backupId;
2163 pntr->parentID = tv->header->diskstuff.parentId;
2164 pntr->copyDate = tv->header->diskstuff.copyDate;
2165 pntr->inUse = tv->header->diskstuff.inUse;
2166 pntr->size = tv->header->diskstuff.diskused;
2167 pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
2168 pntr->maxquota = tv->header->diskstuff.maxquota;
2169 pntr->filecount = tv->header->diskstuff.filecount;
2170 now = FT_ApproxTime();
2171 if (now - tv->header->diskstuff.dayUseDate > OneDay)
2174 pntr->dayUse = tv->header->diskstuff.dayUse;
2175 pntr->creationDate = tv->header->diskstuff.creationDate;
2176 pntr->accessDate = tv->header->diskstuff.accessDate;
2177 pntr->updateDate = tv->header->diskstuff.updateDate;
2178 pntr->backupDate = tv->header->diskstuff.backupDate;
2179 pntr->spare0 = tv->header->diskstuff.minquota;
2180 pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
2181 (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
2182 (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
2183 (long) tv->header->diskstuff.weekUse[6];
2184 pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
2185 VDetachVolume(&error,tv);/*free the volume */
2188 pntr->status = 0; /*things are messed up */
2189 strcpy(pntr->name,volname);
2190 Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
2194 pntr->volid = volid;
2195 /*just volids are needed*/
2201 ttc = (struct volser_trans *) 0;
2204 volumeInfo->volEntries_len += 1;
2205 if((allocSize - volumeInfo->volEntries_len) < 5) {
2206 /*running out of space, allocate more space */
2207 allocSize = (allocSize *3)/2;
2208 pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
2209 allocSize * sizeof(volintInfo));
2212 VDetachVolume(&error, tv);
2217 ttc = (struct volser_trans *) 0;
2220 return VOLSERNO_MEMORY;
2222 volumeInfo->volEntries_val = pntr; /* point to new block */
2223 /* set pntr to the right position */
2224 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2230 VDetachVolume(&error, tv);
2235 ttc = (struct volser_trans *) 0;
2237 GetNextVol(dirp, volname, &volid);
2247 /*------------------------------------------------------------------------
2248 * EXPORTED SAFSVolXListVolumes
2251 * Returns all the volumes on partition a_partID. If a_flags
2252 * is set to 1, then all the relevant extended volume information
2256 * a_rxCidP : Pointer to the Rx call we're performing.
2257 * a_partID : Partition for which we want the extended list.
2258 * a_flags : Various flags.
2259 * a_volumeXInfoP : Ptr to the extended info blob.
2262 * 0 Successful operation
2263 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2264 * VOLSERNO_MEMORY if we ran out of memory allocating
2268 * Nothing interesting.
2272 *------------------------------------------------------------------------*/
2274 afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2275 struct rx_call *a_rxCidP;
2278 volXEntries *a_volumeXInfoP;
2282 code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2283 osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
2287 afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
2288 struct rx_call *a_rxCidP;
2291 volXEntries *a_volumeXInfoP;
2293 { /*SAFSVolXListVolumes*/
2295 volintXInfo *xInfoP; /*Ptr to the extended vol info*/
2296 register struct Volume *tv; /*Volume ptr*/
2297 struct DiskPartition *partP; /*Ptr to partition*/
2298 struct volser_trans *ttc; /*Volume transaction ptr*/
2299 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2300 char pname[9], volname[20]; /*Partition, volume names*/
2301 afs_int32 error = 0; /*Return code*/
2302 DIR *dirp; /*Partition directory ptr*/
2303 afs_int32 volid; /*Current volume ID*/
2304 struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data*/
2305 int numStatBytes; /*Num stat bytes to copy per volume*/
2309 * Allocate a large array of extended volume info structures, then
2310 * set it up for action.
2312 a_volumeXInfoP->volXEntries_val =
2313 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2314 xInfoP = a_volumeXInfoP->volXEntries_val;
2315 a_volumeXInfoP->volXEntries_len = 0;
2318 * If the partition name we've been given is bad, bogue out.
2320 if (GetPartName(a_partID, pname))
2321 return(VOLSERILLEGAL_PARTITION);
2324 * Open the directory representing the given AFS parttion. If we can't
2327 if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
2328 dirp = opendir(VPartitionPath(partP));
2330 return (VOLSERILLEGAL_PARTITION);
2333 * Sweep through the partition directory, acting on each entry. First,
2334 * of course, figure out how many stat bytes to copy out of each volume.
2336 numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
2337 (4*VOLINT_STATS_NUM_TIME_FIELDS));
2339 while (strcmp(volname, "EOD")) {
2340 ttc = (struct volser_trans *)0; /*New one for each pass*/
2341 tv = (Volume *)0; /*Volume not yet attached*/
2344 * If this is not a volume, move on to the next entry in the
2345 * partition's directory.
2347 if(!strcmp(volname,"")) {
2348 GetNextVol(dirp, volname, &volid);
2354 * Full info about the volume desired. Poll to make sure the
2355 * client doesn't time out, then start up a new transaction.
2358 ttc = NewTrans(volid,a_partID);
2361 * Couldn't get a transaction on this volume; let our caller
2364 xInfoP->status = VBUSY;
2365 xInfoP->volid = volid;
2370 * Attach the volume, give up on this volume if we can't.
2372 tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
2374 xInfoP->status = 0; /*things are messed up */
2375 strcpy(xInfoP->name, volname);
2376 xInfoP->volid = volid;
2377 Log("1 Volser: XListVolumes: Could not attach volume %u\n",
2383 * Also bag out on this volume if it's been marked as needing a
2384 * salvage or to-be-destroyed.
2386 volDiskDataP = &(tv->header->diskstuff);
2387 if (volDiskDataP->needsSalvaged) {
2389 strcpy(xInfoP->name, volname);
2390 xInfoP->volid = volid;
2391 Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
2396 if (volDiskDataP->destroyMe == DESTROY_ME)
2400 * Pull out the desired info and stuff it into the area we'll be
2401 * returning to our caller.
2403 strcpy(xInfoP->name,volDiskDataP->name);
2404 xInfoP->volid = volDiskDataP->id;
2405 xInfoP->type = volDiskDataP->type;
2406 xInfoP->backupID = volDiskDataP->backupId;
2407 xInfoP->parentID = volDiskDataP->parentId;
2408 xInfoP->cloneID = volDiskDataP->cloneId;
2409 xInfoP->status = VOK;
2410 xInfoP->copyDate = volDiskDataP->copyDate;
2411 xInfoP->inUse = volDiskDataP->inUse;
2412 xInfoP->creationDate = volDiskDataP->creationDate;
2413 xInfoP->accessDate = volDiskDataP->accessDate;
2414 xInfoP->updateDate = volDiskDataP->updateDate;
2415 xInfoP->backupDate = volDiskDataP->backupDate;
2416 now = FT_ApproxTime();
2417 if (now - volDiskDataP->dayUseDate > OneDay)
2420 xInfoP->dayUse = volDiskDataP->dayUse;
2421 xInfoP->filecount = volDiskDataP->filecount;
2422 xInfoP->maxquota = volDiskDataP->maxquota;
2423 xInfoP->size = volDiskDataP->diskused;
2426 * Copy out the stat fields in a single operation.
2428 memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
2431 * We're done copying. Detach the volume and iterate.
2433 VDetachVolume(&error, tv);
2437 strcpy(xInfoP->name, volname);
2438 Log("1 Volser: XListVolumes: Could not detach volume %s\n",
2442 } /*Full contents desired*/
2445 * Just volume IDs are needed.
2447 xInfoP->volid = volid;
2451 * Drop the transaction we have for this volume.
2455 ttc = (struct volser_trans *) 0;
2459 * Bump the pointer in the data area we're building, along with
2460 * the count of the number of entries it contains.
2463 (a_volumeXInfoP->volXEntries_len)++;
2464 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2466 * We're running out of space in the area we've built. Grow it.
2468 allocSize = (allocSize * 3)/2;
2469 xInfoP = (volintXInfo *)
2470 realloc((char *) a_volumeXInfoP->volXEntries_val,
2471 (allocSize * sizeof(volintXInfo)));
2472 if (xInfoP == NULL) {
2474 * Bummer, no memory. Bag it, tell our caller what went wrong.
2477 VDetachVolume(&error, tv);
2482 ttc = (struct volser_trans *) 0;
2485 return(VOLSERNO_MEMORY);
2489 * Memory reallocation worked. Correct our pointers so they
2490 * now point to the new block and the current open position within
2493 a_volumeXInfoP->volXEntries_val = xInfoP;
2494 xInfoP = a_volumeXInfoP->volXEntries_val +
2495 a_volumeXInfoP->volXEntries_len;
2496 } /*Need more space*/
2500 * Detach our current volume and the transaction on it, then move on
2501 * to the next volume in the partition directory.
2504 VDetachVolume(&error, tv);
2509 ttc = (struct volser_trans *) 0;
2511 GetNextVol(dirp, volname, &volid);
2512 } /*Sweep through the partition directory*/
2515 * We've examined all entries in the partition directory. Close it,
2516 * delete our transaction (if any), and go home happy.
2523 } /*SAFSVolXListVolumes*/
2525 /*this call is used to monitor the status of volser for debugging purposes.
2526 *information about all the active transactions is returned in transInfo*/
2527 afs_int32 SAFSVolMonitor (acid,transInfo)
2528 struct rx_call *acid;
2529 transDebugEntries *transInfo;
2533 code = VolMonitor (acid,transInfo);
2534 osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
2538 afs_int32 VolMonitor (acid,transInfo)
2539 struct rx_call *acid;
2540 transDebugEntries *transInfo;
2542 transDebugInfo *pntr;
2543 afs_int32 allocSize = 50;
2544 struct volser_trans *tt, *allTrans;
2546 transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2547 pntr = transInfo->transDebugEntries_val;
2548 transInfo->transDebugEntries_len = 0;
2549 allTrans = TransList();
2550 if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
2551 for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
2552 pntr->tid = tt->tid;
2553 pntr->time = tt->time;
2554 pntr->creationTime = tt->creationTime;
2555 pntr->returnCode = tt->returnCode;
2556 pntr->volid = tt->volid;
2557 pntr->partition = tt->partition;
2558 pntr->iflags = tt->iflags;
2559 pntr->vflags = tt->vflags;
2560 pntr->tflags = tt->tflags;
2561 strcpy(pntr->lastProcName,tt->lastProcName);
2562 pntr->callValid = 0;
2563 if(tt->rxCallPtr) { /*record call related info */
2564 pntr->callValid = 1;
2565 pntr->readNext = tt->rxCallPtr->rnext;
2566 pntr->transmitNext = tt->rxCallPtr->tnext;
2567 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2568 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2571 transInfo->transDebugEntries_len += 1;
2572 if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
2573 allocSize = (allocSize *3)/2;
2574 pntr = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
2575 transInfo->transDebugEntries_val = pntr;
2576 pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
2577 /*set pntr to right position*/
2585 afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2586 struct rx_call *acid;
2587 afs_int32 type, pId, cloneId, backupId, atid;
2592 code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
2593 osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid,
2598 AUD_LONG, backupId, AUD_END);
2602 afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
2603 struct rx_call *acid;
2604 afs_int32 type, pId, cloneId, backupId, atid;
2608 afs_int32 error = 0;
2609 register struct volser_trans *tt;
2610 char caller[MAXKTCNAMELEN];
2612 if (strlen(name)>31) return VOLSERBADNAME;
2613 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2614 /* find the trans */
2615 tt = FindTrans(atid);
2616 if (!tt) return ENOENT;
2617 if (tt->vflags & VTDeleted) {
2618 Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
2622 strcpy(tt->lastProcName,"SetIdsTypes");
2623 tt->rxCallPtr = acid;
2627 V_backupId(tv) = backupId;
2628 V_cloneId(tv) = cloneId;
2629 V_parentId(tv) = pId;
2630 strcpy((&V_disk(tv))->name,name);
2631 VUpdateVolume(&error, tv);
2633 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2637 tt->rxCallPtr = (struct rx_call *)0;
2638 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2642 tt->rxCallPtr = (struct rx_call *)0;
2643 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2647 afs_int32 SAFSVolSetDate (acid,atid,cdate)
2648 struct rx_call *acid;
2649 afs_int32 atid, cdate;
2653 code = VolSetDate (acid,atid,cdate);
2654 osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
2658 afs_int32 VolSetDate (acid,atid,cdate)
2659 struct rx_call *acid;
2660 afs_int32 atid, cdate;
2663 afs_int32 error = 0;
2664 register struct volser_trans *tt;
2665 char caller[MAXKTCNAMELEN];
2667 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2668 /* find the trans */
2669 tt = FindTrans(atid);
2670 if (!tt) return ENOENT;
2671 if (tt->vflags & VTDeleted) {
2672 Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
2676 strcpy(tt->lastProcName,"SetDate");
2677 tt->rxCallPtr = acid;
2680 V_creationDate(tv) = cdate;
2681 VUpdateVolume(&error, tv);
2683 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2687 tt->rxCallPtr = (struct rx_call *)0;
2688 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2692 tt->rxCallPtr = (struct rx_call *)0;
2693 if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
2697 #ifdef AFS_NAMEI_ENV
2699 * Inode number format (from namei_ops.c):
2700 * low 26 bits - vnode number - all 1's if volume special file.
2702 * next 3 bits spare (0's)
2703 * high 32 bits - uniquifier (regular) or type if spare
2705 #define NAMEI_VNODEMASK 0x003ffffff
2706 #define NAMEI_TAGMASK 0x7
2707 #define NAMEI_TAGSHIFT 26
2708 #define NAMEI_UNIQMASK 0xffffffff
2709 #define NAMEI_UNIQSHIFT 32
2710 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
2711 #define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
2712 #endif /* AFS_NAMEI_ENV */
2714 afs_int32 SAFSVolConvertROtoRWvolume(acid, partId, volumeId)
2715 struct rx_call *acid;
2719 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
2723 afs_int32 error = 0;
2726 char caller[MAXKTCNAMELEN];
2727 char headername[16];
2730 struct VolumeDiskHeader h;
2734 struct DiskPartition *dp;
2736 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2737 if(GetPartName(partId, pname)) return VOLSERILLEGAL_PARTITION;
2738 dirp = opendir(pname);
2739 if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
2742 while(strcmp(volname,"EOD") && !found) { /*while there are more volumes in the partition */
2743 GetNextVol(dirp,volname,&volid);
2744 if(strcmp(volname,"")) {/* its a volume */
2745 if(volid == volumeId) found = 1;
2748 if (!found) return ENOENT;
2749 (void) afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
2750 (void) afs_snprintf(opath, sizeof opath,"%s/%s", pname, headername);
2751 fd = open(opath, O_RDONLY);
2753 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
2756 if (read(fd, &h, sizeof(h)) != sizeof(h)) {
2757 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
2762 FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
2764 for(dp = DiskPartitionList; dp && strcmp(dp->name, pname); dp = dp->next) ;
2766 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
2769 ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
2770 IH_INIT(ih, dp->device, h.parent, ino);
2772 error = namei_ConvertROtoRWvolume(ih, volumeId);
2776 h.volumeInfo_hi = h.id;
2777 h.smallVnodeIndex_hi = h.id;
2778 h.largeVnodeIndex_hi = h.id;
2779 h.linkTable_hi = h.id;
2780 (void) afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
2781 (void) afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
2782 fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
2784 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
2787 if (write(fd, &h, sizeof(h)) != sizeof(h)) {
2788 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
2793 if (unlink(opath) < 0) {
2794 Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
2796 FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
2797 FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
2799 #else /* AFS_NAMEI_ENV */
2801 #endif /* AFS_NAMEI_ENV */
2804 afs_int32 SAFSVolGetSize (acid, fromTrans, fromDate, size)
2805 struct rx_call *acid;
2806 afs_int32 fromTrans;
2808 register struct volintSize *size;
2811 register struct volser_trans *tt;
2812 char caller[MAXKTCNAMELEN];
2814 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
2815 tt = FindTrans(fromTrans);
2816 if (!tt) return ENOENT;
2817 if (tt->vflags & VTDeleted) {
2821 strcpy(tt->lastProcName,"GetSize");
2822 tt->rxCallPtr = acid;
2823 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
2824 tt->rxCallPtr = (struct rx_call *)0;
2825 if(TRELE(tt)) return VOLSERTRELE_ERROR;
2827 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
2831 /* GetPartName - map partid (a decimal number) into pname (a string)
2832 * Since for NT we actually want to return the drive name, we map through the
2835 static int GetPartName(afs_int32 partid, char *pname)
2840 strcpy(pname,"/vicep");
2841 pname[6] = 'a' + partid;
2844 } else if (partid < VOLMAXPARTS) {
2845 strcpy(pname,"/vicep");
2847 pname[6] = 'a' + (partid / 26);
2848 pname[7] = 'a' + (partid % 26);