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
9 * Portions Copyright (c) 2007-2008 Sine Nomine Associates
12 #include <afsconfig.h>
13 #include <afs/param.h>
18 #ifdef AFS_PTHREAD_ENV
19 # include <opr/lock.h>
24 #include <rx/rx_queue.h>
25 #include <afs/afsint.h>
26 #include <afs/prs_fs.h>
30 #include <afs/cellconfig.h>
33 #include <afs/ihandle.h>
35 #include <afs/ntops.h>
37 #include <afs/vnode.h>
38 #include <afs/volume.h>
39 #include <afs/volume_inline.h>
40 #include <afs/partition.h>
42 #include <afs/daemon_com.h>
43 #include <afs/fssync.h>
45 #include "afs/audit.h"
47 #include <afs/afsutil.h>
48 #include <afs/com_err.h>
49 #include <afs/vol_prototypes.h>
50 #include <afs/errors.h>
53 #include "voltrans_inline.h"
56 #include "volser_internal.h"
58 #include "dumpstuff.h"
61 extern struct afsconf_dir
*tdir
;
62 extern int DoPreserveVolumeStats
;
63 extern int restrictedQueryLevel
;
64 extern enum vol_s2s_crypt doCrypt
;
66 extern void LogError(afs_int32 errcode
);
68 /* Forward declarations */
69 static int GetPartName(afs_int32 partid
, char *pname
);
71 #define OneDay (24*60*60)
77 afs_int32 localTid
= 1;
79 static afs_int32
VolPartitionInfo(struct rx_call
*, char *pname
,
80 struct diskPartition64
*);
81 static afs_int32
VolNukeVolume(struct rx_call
*, afs_int32
, afs_uint32
);
82 static afs_int32
VolCreateVolume(struct rx_call
*, afs_int32
, char *,
83 afs_int32
, afs_uint32
, afs_uint32
*,
85 static afs_int32
VolDeleteVolume(struct rx_call
*, afs_int32
);
86 static afs_int32
VolClone(struct rx_call
*, afs_int32
, VolumeId
,
87 afs_int32
, char *, VolumeId
*);
88 static afs_int32
VolReClone(struct rx_call
*, afs_int32
, VolumeId
);
89 static afs_int32
VolTransCreate(struct rx_call
*, VolumeId
, afs_int32
,
90 afs_int32
, afs_int32
*);
91 static afs_int32
VolGetNthVolume(struct rx_call
*, afs_int32
, afs_uint32
*,
93 static afs_int32
VolGetFlags(struct rx_call
*, afs_int32
, afs_int32
*);
94 static afs_int32
VolSetFlags(struct rx_call
*, afs_int32
, afs_int32
);
95 static afs_int32
VolForward(struct rx_call
*, afs_int32
, afs_int32
,
96 struct destServer
*destination
, afs_int32
,
97 struct restoreCookie
*cookie
);
98 static afs_int32
VolDump(struct rx_call
*, afs_int32
, afs_int32
, afs_int32
);
99 static afs_int32
VolRestore(struct rx_call
*, afs_int32
, afs_int32
,
100 struct restoreCookie
*);
101 static afs_int32
VolEndTrans(struct rx_call
*, afs_int32
, afs_int32
*);
102 static afs_int32
VolSetForwarding(struct rx_call
*, afs_int32
, afs_int32
);
103 static afs_int32
VolGetStatus(struct rx_call
*, afs_int32
,
104 struct volser_status
*);
105 static afs_int32
VolSetInfo(struct rx_call
*, afs_int32
, struct volintInfo
*);
106 static afs_int32
VolGetName(struct rx_call
*, afs_int32
, char **);
107 static afs_int32
VolListPartitions(struct rx_call
*, struct pIDs
*);
108 static afs_int32
XVolListPartitions(struct rx_call
*, struct partEntries
*);
109 static afs_int32
VolListOneVolume(struct rx_call
*, afs_int32
, VolumeId
,
111 static afs_int32
VolXListOneVolume(struct rx_call
*, afs_int32
, VolumeId
,
113 static afs_int32
VolListVolumes(struct rx_call
*, afs_int32
, afs_int32
,
115 static afs_int32
VolXListVolumes(struct rx_call
*, afs_int32
, afs_int32
,
117 static afs_int32
VolMonitor(struct rx_call
*, transDebugEntries
*);
118 static afs_int32
VolSetIdsTypes(struct rx_call
*, afs_int32
, char [],
119 afs_int32
, VolumeId
, VolumeId
,
121 static afs_int32
VolSetDate(struct rx_call
*, afs_int32
, afs_int32
);
124 * Return the host address of the caller as a string.
126 * @param[in] acid incoming rx call
127 * @param[out] buffer buffer to be filled with the addess string
129 * @return address as formatted by inet_ntoa
132 callerAddress(struct rx_call
*acid
, char *buffer
)
134 afs_uint32 ip
= rx_HostOf(rx_PeerOf(rx_ConnectionOf(acid
)));
135 return afs_inet_ntoa_r(ip
, buffer
);
138 /* this call unlocks all of the partition locks we've set */
142 struct DiskPartition64
*tp
;
143 for (tp
= DiskPartitionList
; tp
; tp
= tp
->next
) {
144 if (tp
->lock_fd
!= INVALID_FD
) {
145 OS_CLOSE(tp
->lock_fd
);
146 tp
->lock_fd
= INVALID_FD
;
157 code
= VPFullUnlock_r();
162 /* get partition id from a name */
164 PartitionID(char *aname
)
172 return -1; /* unknown */
174 /* otherwise check for vicepa or /vicepa, or just plain "a" */
176 if (!strncmp(aname
, "/vicep", 6)) {
177 strncpy(ascii
, aname
+ 6, 2);
179 return -1; /* bad partition name */
180 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
181 * from 0. Do the appropriate conversion */
183 /* one char name, 0..25 */
184 if (ascii
[0] < 'a' || ascii
[0] > 'z')
185 return -1; /* wrongo */
186 return ascii
[0] - 'a';
188 /* two char name, 26 .. <whatever> */
189 if (ascii
[0] < 'a' || ascii
[0] > 'z')
190 return -1; /* wrongo */
191 if (ascii
[1] < 'a' || ascii
[1] > 'z')
192 return -1; /* just as bad */
193 code
= (ascii
[0] - 'a') * 26 + (ascii
[1] - 'a') + 26;
194 if (code
> VOLMAXPARTS
)
201 ConvertVolume(VolumeId avol
, char *aname
, afs_int32 asize
)
205 /* 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 */
206 snprintf(aname
, asize
, VFORMAT
, afs_printable_VolumeId_lu(avol
));
211 ConvertPartition(int apartno
, char *aname
, int asize
)
217 strcpy(aname
, "/vicep");
219 aname
[6] = 'a' + apartno
;
223 aname
[6] = 'a' + (apartno
/ 26);
224 aname
[7] = 'a' + (apartno
% 26);
230 #ifdef AFS_DEMAND_ATTACH_FS
231 /* normally we should use the regular salvaging functions from the volume
232 * package, but this is a special case where we have a volume ID, but no
233 * volume structure to give the volume package */
235 SalvageUnknownVolume(VolumeId volid
, char *part
)
239 Log("Scheduling salvage for allegedly nonexistent volume %lu part %s\n",
240 afs_printable_uint32_lu(volid
), part
);
242 code
= FSYNC_VolOp(volid
, part
, FSYNC_VOL_FORCE_ERROR
,
243 FSYNC_SALVAGE
, NULL
);
245 Log("SalvageUnknownVolume: error %ld trying to salvage vol %lu part %s\n",
246 afs_printable_int32_ld(code
), afs_printable_uint32_lu(volid
),
250 #endif /* AFS_DEMAND_ATTACH_FS */
252 static struct Volume
*
253 VAttachVolumeByName_retry(Error
*ec
, char *partition
, char *name
, int mode
)
258 vp
= VAttachVolumeByName(ec
, partition
, name
, mode
);
260 #ifdef AFS_DEMAND_ATTACH_FS
264 * The fileserver will take care of keeping track of how many
265 * demand-salvages have been performed, and will force the volume to
266 * ERROR if we've done too many. The limit on This loop is just a
267 * failsafe to prevent trying to salvage forever. We want to attempt
268 * attachment at least SALVAGE_COUNT_MAX times, since we want to
269 * avoid prematurely exiting this loop, if we can.
271 for (i
= 0; i
< SALVAGE_COUNT_MAX
*2 && *ec
== VSALVAGING
; i
++) {
272 sleep(SALVAGE_PRIO_UPDATE_INTERVAL
);
273 vp
= VAttachVolumeByName(ec
, partition
, name
, mode
);
276 if (*ec
== VSALVAGING
) {
280 #endif /* AFS_DEMAND_ATTACH_FS */
285 static struct Volume
*
286 VAttachVolume_retry(Error
*ec
, afs_uint32 avolid
, int amode
)
291 vp
= VAttachVolume(ec
, avolid
, amode
);
293 #ifdef AFS_DEMAND_ATTACH_FS
296 /* see comment above in VAttachVolumeByName_retry */
297 for (i
= 0; i
< SALVAGE_COUNT_MAX
*2 && *ec
== VSALVAGING
; i
++) {
298 sleep(SALVAGE_PRIO_UPDATE_INTERVAL
);
299 vp
= VAttachVolume(ec
, avolid
, amode
);
302 if (*ec
== VSALVAGING
) {
306 #endif /* AFS_DEMAND_ATTACH_FS */
311 /* the only attach function that takes a partition is "...ByName", so we use it */
312 static struct Volume
*
313 XAttachVolume(afs_int32
*error
, afs_uint32 avolid
, afs_int32 apartid
, int amode
)
315 char pbuf
[30], vbuf
[20];
317 if (ConvertPartition(apartid
, pbuf
, sizeof(pbuf
))) {
321 if (ConvertVolume(avolid
, vbuf
, sizeof(vbuf
))) {
326 return VAttachVolumeByName_retry((Error
*)error
, pbuf
, vbuf
, amode
);
329 /* Adapted from the file server; create a root directory for this volume */
331 ViceCreateRoot(Volume
*vp
)
334 struct acl_accessList
*ACL
;
336 Inode inodeNumber
, AFS_UNUSED nearInode
;
337 struct VnodeDiskObject
*vnode
;
338 struct VnodeClassInfo
*vcp
= &VnodeClassInfo
[vLarge
];
344 vnode
= calloc(1, SIZEOF_LARGEDISKVNODE
);
348 V_pref(vp
, nearInode
);
350 IH_CREATE(V_linkHandle(vp
), V_device(vp
),
351 VPartitionPath(V_partition(vp
)), nearInode
, V_parentId(vp
),
353 if (!VALID_INO(inodeNumber
)) {
354 Log("ViceCreateRoot: IH_CREATE: %s\n", afs_error_message(errno
));
359 SetSalvageDirHandle(&dir
, V_parentId(vp
), vp
->device
, inodeNumber
);
360 did
.Volume
= V_id(vp
);
361 did
.Vnode
= (VnodeId
) 1;
364 opr_Verify(!(afs_dir_MakeDir(&dir
, (afs_int32
*)&did
, (afs_int32
*)&did
)));
365 DFlush(); /* flush all modified dir buffers out */
366 DZap(&dir
); /* Remove all buffers for this dir */
367 length
= afs_dir_Length(&dir
); /* Remember size of this directory */
369 FidZap(&dir
); /* Done with the dir handle obtained via SetSalvageDirHandle() */
371 /* build a single entry ACL that gives all rights to system:administrators */
372 /* this section of code assumes that access list format is not going to
375 ACL
= VVnodeDiskACL(vnode
);
376 ACL
->size
= sizeof(struct acl_accessList
);
377 ACL
->version
= ACL_ACLVERSION
;
381 ACL
->entries
[0].id
= -204; /* this assumes System:administrators is group -204 */
382 ACL
->entries
[0].rights
=
383 PRSFS_READ
| PRSFS_WRITE
| PRSFS_INSERT
| PRSFS_LOOKUP
| PRSFS_DELETE
384 | PRSFS_LOCK
| PRSFS_ADMINISTER
;
386 vnode
->type
= vDirectory
;
388 vnode
->modeBits
= 0777;
389 vnode
->linkCount
= 2;
390 VNDISK_SET_LEN(vnode
, length
);
391 vnode
->uniquifier
= 1;
392 V_uniquifier(vp
) = vnode
->uniquifier
+ 1;
393 vnode
->dataVersion
= 1;
394 VNDISK_SET_INO(vnode
, inodeNumber
);
395 vnode
->unixModifyTime
= vnode
->serverModifyTime
= V_creationDate(vp
);
399 vnode
->vnodeMagic
= vcp
->magic
;
401 IH_INIT(h
, vp
->device
, V_parentId(vp
),
402 vp
->vnodeIndex
[vLarge
].handle
->ih_ino
);
404 opr_Assert(fdP
!= NULL
);
405 nBytes
= FDH_PWRITE(fdP
, vnode
, SIZEOF_LARGEDISKVNODE
, vnodeIndexOffset(vcp
, 1));
406 opr_Assert(nBytes
== SIZEOF_LARGEDISKVNODE
);
407 FDH_REALLYCLOSE(fdP
);
409 VNDISK_GET_LEN(length
, vnode
);
410 V_diskused(vp
) = nBlocks(length
);
417 SAFSVolPartitionInfo(struct rx_call
*acid
, char *pname
, struct diskPartition
421 struct diskPartition64
*dp
= malloc(sizeof(struct diskPartition64
));
423 code
= VolPartitionInfo(acid
, pname
, dp
);
425 strncpy(partition
->name
, dp
->name
, 32);
426 strncpy(partition
->devName
, dp
->devName
, 32);
427 partition
->lock_fd
= dp
->lock_fd
;
428 partition
->free
=RoundInt64ToInt32(dp
->free
);
429 partition
->minFree
=RoundInt64ToInt32(dp
->minFree
);
432 osi_auditU(acid
, VS_ParInfEvent
, code
, AUD_STR
, pname
, AUD_END
);
437 SAFSVolPartitionInfo64(struct rx_call
*acid
, char *pname
, struct diskPartition64
442 code
= VolPartitionInfo(acid
, pname
, partition
);
443 osi_auditU(acid
, VS_ParInfEvent
, code
, AUD_STR
, pname
, AUD_END
);
448 VolPartitionInfo(struct rx_call
*acid
, char *pname
, struct diskPartition64
451 struct DiskPartition64
*dp
;
453 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
454 return VOLSERBAD_ACCESS
;
457 dp
= VGetPartition(pname
, 0);
459 strncpy(partition
->name
, dp
->name
, 32);
460 strncpy(partition
->devName
, dp
->devName
, 32);
461 partition
->lock_fd
= (int)dp
->lock_fd
;
462 partition
->free
= dp
->free
;
463 partition
->minFree
= dp
->totalUsable
;
466 return VOLSERILLEGAL_PARTITION
;
469 /* obliterate a volume completely, and slowly. */
471 SAFSVolNukeVolume(struct rx_call
*acid
, afs_int32 apartID
, VolumeId avolID
)
475 code
= VolNukeVolume(acid
, apartID
, avolID
);
476 osi_auditU(acid
, VS_NukVolEvent
, code
, AUD_LONG
, avolID
, AUD_END
);
481 VolNukeVolume(struct rx_call
*acid
, afs_int32 apartID
, afs_uint32 avolID
)
488 char caller
[MAXKTCNAMELEN
];
490 /* check for access */
491 if (!afsconf_SuperUser(tdir
, acid
, caller
))
492 return VOLSERBAD_ACCESS
;
495 Log("%s on %s is executing VolNukeVolume %u\n", caller
,
496 callerAddress(acid
, buffer
), avolID
);
499 if (volutil_PartitionName2_r(apartID
, partName
, sizeof(partName
)) != 0)
501 /* we first try to attach the volume in update mode, so that the file
502 * server doesn't try to use it (and abort) while (or after) we delete it.
503 * If we don't get the volume, that's fine, too. We just won't put it back.
505 tvp
= XAttachVolume(&error
, avolID
, apartID
, V_VOLUPD
);
506 code
= nuke(partName
, avolID
);
508 VDetachVolume(&verror
, tvp
);
512 /* create a new volume, with name aname, on the specified partition (1..n)
513 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
514 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
515 * for the volume id (useful for things like volume restore).
516 * Return the new volume id in *avolid.
519 SAFSVolCreateVolume(struct rx_call
*acid
, afs_int32 apart
, char *aname
,
520 afs_int32 atype
, VolumeId aparent
, VolumeId
*avolid
,
526 VolCreateVolume(acid
, apart
, aname
, atype
, aparent
, avolid
, atrans
);
527 osi_auditU(acid
, VS_CrVolEvent
, code
, AUD_LONG
, *atrans
, AUD_LONG
,
528 *avolid
, AUD_STR
, aname
, AUD_LONG
, atype
, AUD_LONG
, aparent
,
534 VolCreateVolume(struct rx_call
*acid
, afs_int32 apart
, char *aname
,
535 afs_int32 atype
, afs_uint32 aparent
, afs_uint32
*avolid
,
540 Error junk
; /* discardable error code */
542 afs_int32 doCreateRoot
= 1;
543 struct volser_trans
*tt
;
545 char caller
[MAXKTCNAMELEN
];
547 if (strlen(aname
) > 31)
548 return VOLSERBADNAME
;
549 if (!afsconf_SuperUser(tdir
, acid
, caller
))
550 return VOLSERBAD_ACCESS
;
553 Log("%s on %s is executing CreateVolume '%s'\n", caller
,
554 callerAddress(acid
, buffer
), aname
);
556 if ((error
= ConvertPartition(apart
, ppath
, sizeof(ppath
))))
557 return error
; /*a standard unix error */
558 if (atype
!= readwriteVolume
&& atype
!= readonlyVolume
559 && atype
!= backupVolume
)
561 if ((volumeID
= *avolid
) == 0) {
563 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname
);
567 if ((aparent
== volumeID
) && (atype
== readwriteVolume
)) {
572 tt
= NewTrans(volumeID
, apart
);
574 Log("1 createvolume: failed to create trans\n");
575 return VOLSERVOLBUSY
; /* volume already busy! */
577 vp
= VCreateVolume(&error
, ppath
, volumeID
, aparent
);
579 #ifdef AFS_DEMAND_ATTACH_FS
580 if (error
!= VVOLEXISTS
&& error
!= EXDEV
) {
581 SalvageUnknownVolume(volumeID
, ppath
);
584 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error
);
589 V_uniquifier(vp
) = 1;
590 V_updateDate(vp
) = V_creationDate(vp
) = V_copyDate(vp
);
591 V_inService(vp
) = V_blessed(vp
) = 1;
593 AssignVolumeName(&V_disk(vp
), aname
, 0);
595 error
= ViceCreateRoot(vp
);
597 Log("1 Volser: CreateVolume: Unable to create volume root dir; "
598 "error code %u\n", (unsigned)error
);
600 V_needsSalvaged(vp
) = 1;
601 VDetachVolume(&junk
, vp
);
605 V_destroyMe(vp
) = DESTROY_ME
;
607 V_maxquota(vp
) = 5000; /* set a quota of 5000 at init time */
608 VUpdateVolume(&error
, vp
);
610 Log("1 Volser: create UpdateVolume failed, code %d\n", error
);
613 VDetachVolume(&junk
, vp
); /* rather return the real error code */
619 TSetRxCall_r(tt
, acid
, "CreateVolume");
620 VTRANS_OBJ_UNLOCK(tt
);
621 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID
, aname
);
624 return VOLSERTRELE_ERROR
;
628 /* delete the volume associated with this transaction */
630 SAFSVolDeleteVolume(struct rx_call
*acid
, afs_int32 atrans
)
634 code
= VolDeleteVolume(acid
, atrans
);
635 osi_auditU(acid
, VS_DelVolEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
640 VolDeleteVolume(struct rx_call
*acid
, afs_int32 atrans
)
642 struct volser_trans
*tt
;
644 char caller
[MAXKTCNAMELEN
];
646 if (!afsconf_SuperUser(tdir
, acid
, caller
))
647 return VOLSERBAD_ACCESS
;
648 tt
= FindTrans(atrans
);
651 if (tt
->vflags
& VTDeleted
) {
652 Log("1 Volser: Delete: volume %" AFS_VOLID_FMT
" already deleted \n",
653 afs_printable_VolumeId_lu(tt
->volid
));
659 Log("%s on %s is executing Delete Volume %" AFS_VOLID_FMT
"\n", caller
,
660 callerAddress(acid
, buffer
), afs_printable_VolumeId_lu(tt
->volid
));
662 TSetRxCall(tt
, acid
, "DeleteVolume");
663 VPurgeVolume(&error
, tt
->volume
); /* don't check error code, it is not set! */
664 V_destroyMe(tt
->volume
) = DESTROY_ME
;
665 if (tt
->volume
->needsPutBack
) {
666 tt
->volume
->needsPutBack
= VOL_PUTBACK_DELETE
; /* so endtrans does the right fssync opcode */
669 tt
->vflags
|= VTDeleted
; /* so we know not to do anything else to it */
671 VTRANS_OBJ_UNLOCK(tt
);
673 return VOLSERTRELE_ERROR
;
675 Log("1 Volser: Delete: volume %" AFS_VOLID_FMT
" deleted \n",
676 afs_printable_VolumeId_lu(tt
->volid
));
677 return 0; /* vpurgevolume doesn't set an error code */
680 /* make a clone of the volume associated with atrans, possibly giving it a new
681 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
682 * for the clone's id). The new clone is given the name newName. Finally,
683 * due to efficiency considerations, if purgeId is non-zero, we purge that
684 * volume when doing the clone operation. This may be useful when making
685 * new backup volumes, for instance since the net result of a clone and a
686 * purge generally leaves many inode ref counts the same, while doing them
687 * separately would result in far more iincs and idecs being peformed
688 * (and they are slow operations).
690 /* for efficiency reasons, sometimes faster to piggyback a purge here */
692 SAFSVolClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId purgeId
,
693 afs_int32 newType
, char *newName
, VolumeId
*newNumber
)
696 code
= VolClone(acid
, atrans
, purgeId
, newType
, newName
, newNumber
);
697 osi_auditU(acid
, VS_CloneEvent
, code
, AUD_LONG
, atrans
, AUD_LONG
, purgeId
,
698 AUD_STR
, newName
, AUD_LONG
, newType
, AUD_LONG
, *newNumber
,
704 VolClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId purgeId
,
705 afs_int32 newType
, char *newName
, VolumeId
*newNumber
)
708 struct Volume
*originalvp
, *purgevp
, *newvp
;
710 struct volser_trans
*tt
, *ttc
;
711 char caller
[MAXKTCNAMELEN
];
712 #ifdef AFS_DEMAND_ATTACH_FS
713 struct Volume
*salv_vp
= NULL
;
716 if (strlen(newName
) > 31)
717 return VOLSERBADNAME
;
718 if (!afsconf_SuperUser(tdir
, acid
, caller
))
719 return VOLSERBAD_ACCESS
; /*not a super user */
722 Log("%s on %s is executing Clone Volume new name=%s\n", caller
,
723 callerAddress(acid
, buffer
), newName
);
726 purgevp
= (Volume
*) 0;
727 newvp
= (Volume
*) 0;
728 tt
= ttc
= (struct volser_trans
*)0;
730 if (!newNumber
|| !*newNumber
) {
731 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
736 tt
= FindTrans(atrans
);
739 if (tt
->vflags
& VTDeleted
) {
740 Log("1 Volser: Clone: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
744 ttc
= NewTrans(newId
, tt
->partition
);
745 if (!ttc
) { /* someone is messing with the clone already */
747 return VOLSERVOLBUSY
;
749 TSetRxCall(tt
, acid
, "Clone");
753 purgevp
= VAttachVolume_retry(&error
, purgeId
, V_VOLUPD
);
755 Log("1 Volser: Clone: Could not attach 'purge' volume %" AFS_VOLID_FMT
"; clone aborted\n", afs_printable_VolumeId_lu(purgeId
));
761 originalvp
= tt
->volume
;
762 if ((V_destroyMe(originalvp
) == DESTROY_ME
) || !V_inService(originalvp
)) {
763 Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT
" is offline and cannot be cloned\n",
764 afs_printable_VolumeId_lu(V_id(originalvp
)));
769 if (originalvp
->device
!= purgevp
->device
) {
770 Log("1 Volser: Clone: Volumes %" AFS_VOLID_FMT
" and %" AFS_VOLID_FMT
" are on different devices\n", afs_printable_VolumeId_lu(tt
->volid
), afs_printable_VolumeId_lu(purgeId
));
774 if (V_type(purgevp
) != readonlyVolume
) {
775 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
779 if (V_parentId(originalvp
) != V_parentId(purgevp
)) {
780 Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT
" and volume %" AFS_VOLID_FMT
" were not originally cloned from the same parent; aborted\n", afs_printable_VolumeId_lu(purgeId
), afs_printable_VolumeId_lu(tt
->volid
));
787 #ifdef AFS_DEMAND_ATTACH_FS
788 salv_vp
= originalvp
;
791 if (purgeId
== newId
) {
795 VCreateVolume(&error
, originalvp
->partition
->name
, newId
,
796 V_parentId(originalvp
));
798 Log("1 Volser: Clone: Couldn't create new volume %" AFS_VOLID_FMT
" for parent %" AFS_VOLID_FMT
"; clone aborted\n",
799 afs_printable_VolumeId_lu(newId
), afs_printable_VolumeId_lu(V_parentId(originalvp
)));
800 newvp
= (Volume
*) 0;
804 if (newType
== readonlyVolume
)
805 V_cloneId(originalvp
) = newId
;
806 Log("1 Volser: Clone: Cloning volume %" AFS_VOLID_FMT
" to new volume %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(tt
->volid
),
807 afs_printable_VolumeId_lu(newId
));
809 Log("1 Volser: Clone: Purging old read only volume %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(purgeId
));
810 CloneVolume(&error
, originalvp
, newvp
, purgevp
);
811 purgevp
= NULL
; /* clone releases it, maybe even if error */
813 Log("1 Volser: Clone: clone operation failed with code %u\n", error
);
817 if (newType
== readonlyVolume
) {
818 V_type(newvp
) = readonlyVolume
;
819 } else if (newType
== backupVolume
) {
820 V_type(newvp
) = backupVolume
;
821 V_backupId(originalvp
) = newId
;
823 strcpy(V_name(newvp
), newName
);
824 V_creationDate(newvp
) = V_copyDate(newvp
);
825 ClearVolumeStats(&V_disk(newvp
));
826 V_destroyMe(newvp
) = DESTROY_ME
;
827 V_inService(newvp
) = 0;
828 if (newType
== backupVolume
) {
829 V_backupDate(originalvp
) = V_copyDate(newvp
);
830 V_backupDate(newvp
) = V_copyDate(newvp
);
833 VUpdateVolume(&error
, newvp
);
835 Log("1 Volser: Clone: VUpdate failed code %u\n", error
);
839 VDetachVolume(&error
, newvp
); /* allow file server to get it's hands on it */
841 VUpdateVolume(&error
, originalvp
);
843 Log("1 Volser: Clone: original update %u\n", error
);
848 #ifdef AFS_DEMAND_ATTACH_FS
852 /* Clients could have callbacks to the clone ID */
853 FSYNC_VolOp(newId
, NULL
, FSYNC_VOL_BREAKCBKS
, 0l, NULL
);
856 tt
= (struct volser_trans
*)0;
857 error
= VOLSERTRELE_ERROR
;
865 VDetachVolume(&code
, purgevp
);
867 VDetachVolume(&code
, newvp
);
874 #ifdef AFS_DEMAND_ATTACH_FS
875 if (salv_vp
&& error
!= VVOLEXISTS
&& error
!= EXDEV
) {
876 V_needsSalvaged(salv_vp
) = 1;
878 #endif /* AFS_DEMAND_ATTACH_FS */
882 /* reclone this volume into the specified id */
884 SAFSVolReClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId cloneId
)
888 code
= VolReClone(acid
, atrans
, cloneId
);
889 osi_auditU(acid
, VS_ReCloneEvent
, code
, AUD_LONG
, atrans
, AUD_LONG
,
895 VolReClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId cloneId
)
897 struct Volume
*originalvp
, *clonevp
;
900 struct volser_trans
*tt
, *ttc
;
901 char caller
[MAXKTCNAMELEN
];
902 VolumeDiskData saved_header
;
904 /*not a super user */
905 if (!afsconf_SuperUser(tdir
, acid
, caller
))
906 return VOLSERBAD_ACCESS
;
909 Log("%s on %s is executing Reclone Volume %" AFS_VOLID_FMT
"\n", caller
,
910 callerAddress(acid
, buffer
), afs_printable_VolumeId_lu(cloneId
));
913 clonevp
= originalvp
= (Volume
*) 0;
915 tt
= FindTrans(atrans
);
918 if (tt
->vflags
& VTDeleted
) {
919 Log("1 Volser: VolReClone: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
923 ttc
= NewTrans(cloneId
, tt
->partition
);
924 if (!ttc
) { /* someone is messing with the clone already */
926 return VOLSERVOLBUSY
;
928 TSetRxCall(tt
, acid
, "ReClone");
930 originalvp
= tt
->volume
;
931 if ((V_destroyMe(originalvp
) == DESTROY_ME
) || !V_inService(originalvp
)) {
932 Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT
" is offline and cannot be cloned\n",
933 afs_printable_VolumeId_lu(V_id(originalvp
)));
938 clonevp
= VAttachVolume_retry(&error
, cloneId
, V_VOLUPD
);
940 Log("1 Volser: can't attach clone %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(cloneId
));
944 newType
= V_type(clonevp
); /* type of the new volume */
946 if (originalvp
->device
!= clonevp
->device
) {
947 Log("1 Volser: Clone: Volumes %" AFS_VOLID_FMT
" and %" AFS_VOLID_FMT
" are on different devices\n",
948 afs_printable_VolumeId_lu(tt
->volid
), afs_printable_VolumeId_lu(cloneId
));
952 if (V_parentId(originalvp
) != V_parentId(clonevp
)) {
953 Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT
" was not originally cloned from volume %" AFS_VOLID_FMT
"; aborted\n", afs_printable_VolumeId_lu(cloneId
), afs_printable_VolumeId_lu(tt
->volid
));
958 if (DoPreserveVolumeStats
) {
959 CopyVolumeStats(&V_disk(clonevp
), &saved_header
);
963 Log("1 Volser: Clone: Recloning volume %" AFS_VOLID_FMT
" to volume %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(tt
->volid
),
964 afs_printable_VolumeId_lu(cloneId
));
965 CloneVolume(&error
, originalvp
, clonevp
, clonevp
);
967 Log("1 Volser: Clone: reclone operation failed with code %d\n",
973 /* fix up volume name and type, CloneVolume just propagated RW's */
974 if (newType
== readonlyVolume
) {
975 AssignVolumeName(&V_disk(clonevp
), V_name(originalvp
), ".readonly");
976 V_type(clonevp
) = readonlyVolume
;
977 } else if (newType
== backupVolume
) {
978 AssignVolumeName(&V_disk(clonevp
), V_name(originalvp
), ".backup");
979 V_type(clonevp
) = backupVolume
;
980 V_backupId(originalvp
) = cloneId
;
982 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
984 /* update the creationDate, since this represents the last cloning date
985 * for ROs. But do not update copyDate; let it stay so we can identify
986 * when the clone was first created. */
987 V_creationDate(clonevp
) = time(0);
988 if (DoPreserveVolumeStats
) {
989 CopyVolumeStats(&saved_header
, &V_disk(clonevp
));
991 ClearVolumeStats(&V_disk(clonevp
));
993 V_destroyMe(clonevp
) = 0;
994 V_inService(clonevp
) = 0;
995 if (newType
== backupVolume
) {
996 V_backupDate(originalvp
) = V_creationDate(clonevp
);
997 V_backupDate(clonevp
) = V_creationDate(clonevp
);
999 V_inUse(clonevp
) = 0;
1000 VUpdateVolume(&error
, clonevp
);
1002 Log("1 Volser: Clone: VUpdate failed code %u\n", error
);
1006 /* VUpdateVolume succeeded. Mark it in service so there's no window
1007 * between FSYNC_VOL_ON and VolSetFlags where it's offline with no
1008 * specialStatus; this is a reclone and this volume started online
1010 V_inService(clonevp
) = 1;
1011 VDetachVolume(&error
, clonevp
); /* allow file server to get it's hands on it */
1013 VUpdateVolume(&error
, originalvp
);
1015 Log("1 Volser: Clone: original update %u\n", error
);
1021 tt
= (struct volser_trans
*)0;
1022 error
= VOLSERTRELE_ERROR
;
1026 DeleteTrans(ttc
, 1);
1029 struct DiskPartition64
*tpartp
= originalvp
->partition
;
1030 FSYNC_VolOp(cloneId
, tpartp
->name
, FSYNC_VOL_BREAKCBKS
, 0, NULL
);
1036 VDetachVolume(&code
, clonevp
);
1042 DeleteTrans(ttc
, 1);
1046 /* create a new transaction, associated with volume and partition. Type of
1047 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
1048 * See volser.h for definition of iflags (the constants are named IT*).
1051 SAFSVolTransCreate(struct rx_call
*acid
, VolumeId volume
, afs_int32 partition
,
1052 afs_int32 iflags
, afs_int32
*ttid
)
1056 code
= VolTransCreate(acid
, volume
, partition
, iflags
, ttid
);
1057 osi_auditU(acid
, VS_TransCrEvent
, code
, AUD_LONG
, *ttid
, AUD_LONG
, volume
,
1063 VolTransCreate(struct rx_call
*acid
, VolumeId volume
, afs_int32 partition
,
1064 afs_int32 iflags
, afs_int32
*ttid
)
1066 struct volser_trans
*tt
;
1071 char caller
[MAXKTCNAMELEN
];
1073 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1074 return VOLSERBAD_ACCESS
; /*not a super user */
1075 if (iflags
& ITCreate
)
1077 else if (iflags
& ITBusy
)
1079 else if (iflags
& ITReadOnly
)
1081 else if (iflags
& ITOffline
)
1084 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
1089 tt
= NewTrans(volume
, partition
);
1091 /* can't create a transaction? put the volume back */
1092 Log("1 transcreate: can't create transaction\n");
1093 return VOLSERVOLBUSY
;
1095 tv
= XAttachVolume(&error
, volume
, partition
, mode
);
1099 VDetachVolume(&code
, tv
);
1103 VTRANS_OBJ_LOCK(tt
);
1106 tt
->iflags
= iflags
;
1108 TSetRxCall_r(tt
, NULL
, "TransCreate");
1109 VTRANS_OBJ_UNLOCK(tt
);
1111 return VOLSERTRELE_ERROR
;
1116 /* using aindex as a 0-based index, return the aindex'th volume on this server
1117 * Both the volume number and partition number (one-based) are returned.
1120 SAFSVolGetNthVolume(struct rx_call
*acid
, afs_int32 aindex
, VolumeId
*avolume
,
1125 code
= VolGetNthVolume(acid
, aindex
, avolume
, apart
);
1126 osi_auditU(acid
, VS_GetNVolEvent
, code
, AUD_LONG
, *avolume
, AUD_END
);
1131 VolGetNthVolume(struct rx_call
*acid
, afs_int32 aindex
, afs_uint32
*avolume
,
1134 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1135 return VOLSERBAD_ACCESS
;
1137 Log("1 Volser: GetNthVolume: Not yet implemented\n");
1141 /* return the volume flags (VT* constants in volser.h) associated with this
1145 SAFSVolGetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32
*aflags
)
1149 code
= VolGetFlags(acid
, atid
, aflags
);
1150 osi_auditU(acid
, VS_GetFlgsEvent
, code
, AUD_LONG
, atid
, AUD_END
);
1155 VolGetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32
*aflags
)
1157 struct volser_trans
*tt
;
1159 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1160 return VOLSERBAD_ACCESS
;
1162 tt
= FindTrans(atid
);
1165 if (tt
->vflags
& VTDeleted
) {
1166 Log("1 Volser: VolGetFlags: volume %" AFS_VOLID_FMT
" has been deleted \n",
1167 afs_printable_VolumeId_lu(tt
->volid
));
1171 TSetRxCall(tt
, acid
, "GetFlags");
1172 *aflags
= tt
->vflags
;
1175 return VOLSERTRELE_ERROR
;
1180 /* Change the volume flags (VT* constants in volser.h) associated with this
1181 * transaction. Effects take place immediately on volume, although volume
1182 * remains attached as usual by the transaction.
1185 SAFSVolSetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32 aflags
)
1189 code
= VolSetFlags(acid
, atid
, aflags
);
1190 osi_auditU(acid
, VS_SetFlgsEvent
, code
, AUD_LONG
, atid
, AUD_LONG
, aflags
,
1196 VolSetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32 aflags
)
1198 struct volser_trans
*tt
;
1201 char caller
[MAXKTCNAMELEN
];
1203 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1204 return VOLSERBAD_ACCESS
; /*not a super user */
1205 /* find the trans */
1206 tt
= FindTrans(atid
);
1209 if (tt
->vflags
& VTDeleted
) {
1210 Log("1 Volser: VolSetFlags: volume %" AFS_VOLID_FMT
" has been deleted \n",
1211 afs_printable_VolumeId_lu(tt
->volid
));
1215 TSetRxCall(tt
, acid
, "SetFlags");
1216 vp
= tt
->volume
; /* pull volume out of transaction */
1218 /* check if we're allowed to make any updates */
1219 if (tt
->iflags
& ITReadOnly
) {
1224 /* handle delete-on-salvage flag */
1225 if (aflags
& VTDeleteOnSalvage
) {
1226 V_destroyMe(tt
->volume
) = DESTROY_ME
;
1228 V_destroyMe(tt
->volume
) = 0;
1231 if (aflags
& VTOutOfService
) {
1232 V_inService(vp
) = 0;
1234 V_inService(vp
) = 1;
1236 VUpdateVolume(&error
, vp
);
1237 VTRANS_OBJ_LOCK(tt
);
1238 tt
->vflags
= aflags
;
1240 VTRANS_OBJ_UNLOCK(tt
);
1241 if (TRELE(tt
) && !error
)
1242 return VOLSERTRELE_ERROR
;
1247 /* dumpS the volume associated with a particular transaction from a particular
1248 * date. Send the dump to a different transaction (destTrans) on the server
1249 * specified by the destServer structure.
1252 SAFSVolForward(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1253 struct destServer
*destination
, afs_int32 destTrans
,
1254 struct restoreCookie
*cookie
)
1259 VolForward(acid
, fromTrans
, fromDate
, destination
, destTrans
, cookie
);
1260 osi_auditU(acid
, VS_ForwardEvent
, code
, AUD_LONG
, fromTrans
, AUD_HOST
,
1261 htonl(destination
->destHost
), AUD_LONG
, destTrans
, AUD_END
);
1265 static_inline afs_int32
1266 MakeClient(struct rx_call
*acid
, struct rx_securityClass
**securityObject
,
1267 afs_int32
*securityIndex
)
1269 rxkad_level enc_level
= rxkad_clear
;
1278 rxkad_GetServerInfo(rx_ConnectionOf(acid
), &enc_level
, 0, 0, 0, 0, 0);
1279 docrypt
= (enc_level
== rxkad_crypt
? 1 : 0);
1285 opr_Assert(0 && "doCrypt corrupt?");
1288 code
= afsconf_ClientAuthSecure(tdir
, securityObject
, securityIndex
);
1290 code
= afsconf_ClientAuth(tdir
, securityObject
, securityIndex
);
1295 VolForward(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1296 struct destServer
*destination
, afs_int32 destTrans
,
1297 struct restoreCookie
*cookie
)
1299 struct volser_trans
*tt
;
1301 struct rx_connection
*tcon
;
1302 struct rx_call
*tcall
;
1304 struct rx_securityClass
*securityObject
;
1305 afs_int32 securityIndex
;
1306 char caller
[MAXKTCNAMELEN
];
1308 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1309 return VOLSERBAD_ACCESS
; /*not a super user */
1311 /* find the local transaction */
1312 tt
= FindTrans(fromTrans
);
1315 if (tt
->vflags
& VTDeleted
) {
1316 Log("1 Volser: VolForward: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1321 TSetRxCall(tt
, NULL
, "Forward");
1323 /* get auth info for the this connection (uses afs from ticket file) */
1324 code
= MakeClient(acid
, &securityObject
, &securityIndex
);
1330 /* make an rpc connection to the other server */
1332 rx_NewConnection(htonl(destination
->destHost
),
1333 htons(destination
->destPort
), VOLSERVICE_ID
,
1334 securityObject
, securityIndex
);
1336 RXS_Close(securityObject
); /* will be freed after connection destroyed */
1343 tcall
= rx_NewCall(tcon
);
1344 TSetRxCall(tt
, tcall
, "Forward");
1345 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1346 code
= StartAFSVolRestore(tcall
, destTrans
, (fromDate
? 1 : 0), cookie
);
1351 /* these next calls implictly call rx_Write when writing out data */
1352 code
= DumpVolume(tcall
, vp
, fromDate
, 0); /* last field = don't dump all dirs */
1355 EndAFSVolRestore(tcall
); /* probably doesn't do much */
1357 code
= rx_EndCall(tcall
, 0);
1358 rx_DestroyConnection(tcon
); /* done with the connection */
1363 return VOLSERTRELE_ERROR
;
1369 (void)rx_EndCall(tcall
, 0);
1370 rx_DestroyConnection(tcon
);
1379 /* Start a dump and send it to multiple places simultaneously.
1380 * If this returns an error (eg, return ENOENT), it means that
1381 * none of the releases worked. If this returns 0, that means
1382 * that one or more of the releases worked, and the caller has
1383 * to examine the results array to see which one(s).
1384 * This will only do EITHER incremental or full, not both, so it's
1385 * the caller's responsibility to be sure that all the destinations
1386 * need just an incremental (and from the same time), if that's
1390 SAFSVolForwardMultiple(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32
1391 fromDate
, manyDests
*destinations
, afs_int32 spare
,
1392 struct restoreCookie
*cookie
, manyResults
*results
)
1394 afs_int32 securityIndex
;
1395 struct rx_securityClass
*securityObject
;
1396 char caller
[MAXKTCNAMELEN
];
1397 struct volser_trans
*tt
;
1398 afs_int32 ec
, code
, *codes
;
1399 struct rx_connection
**tcons
;
1400 struct rx_call
**tcalls
;
1402 int i
, is_incremental
;
1405 memset(results
, 0, sizeof(manyResults
));
1406 i
= results
->manyResults_len
= destinations
->manyDests_len
;
1407 results
->manyResults_val
= codes
= malloc(i
* sizeof(afs_int32
));
1409 if (!results
|| !results
->manyResults_val
)
1412 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1413 return VOLSERBAD_ACCESS
; /*not a super user */
1414 tt
= FindTrans(fromTrans
);
1417 if (tt
->vflags
& VTDeleted
) {
1418 Log("1 Volser: VolForward: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1423 TSetRxCall(tt
, NULL
, "ForwardMulti");
1425 /* (fromDate == 0) ==> full dump */
1426 is_incremental
= (fromDate
? 1 : 0);
1428 tcons
= malloc(i
* sizeof(struct rx_connection
*));
1432 tcalls
= malloc(i
* sizeof(struct rx_call
*));
1438 /* get auth info for this connection (uses afs from ticket file) */
1439 code
= MakeClient(acid
, &securityObject
, &securityIndex
);
1441 goto fail
; /* in order to audit each failure */
1444 /* make connections to all the other servers */
1445 for (i
= 0; i
< destinations
->manyDests_len
; i
++) {
1446 struct replica
*dest
= &(destinations
->manyDests_val
[i
]);
1448 rx_NewConnection(htonl(dest
->server
.destHost
),
1449 htons(dest
->server
.destPort
), VOLSERVICE_ID
,
1450 securityObject
, securityIndex
);
1452 codes
[i
] = ENOTCONN
;
1454 if (!(tcalls
[i
] = rx_NewCall(tcons
[i
])))
1455 codes
[i
] = ENOTCONN
;
1458 StartAFSVolRestore(tcalls
[i
], dest
->trans
, is_incremental
,
1461 (void)rx_EndCall(tcalls
[i
], 0);
1463 rx_DestroyConnection(tcons
[i
]);
1470 /* Security object will be freed when all connections destroyed */
1471 RXS_Close(securityObject
);
1473 /* these next calls implictly call rx_Write when writing out data */
1474 code
= DumpVolMulti(tcalls
, i
, vp
, fromDate
, 0, codes
);
1478 for (i
--; i
>= 0; i
--) {
1479 struct replica
*dest
= &(destinations
->manyDests_val
[i
]);
1481 if (!code
&& tcalls
[i
] && !codes
[i
]) {
1482 EndAFSVolRestore(tcalls
[i
]);
1485 ec
= rx_EndCall(tcalls
[i
], 0);
1490 rx_DestroyConnection(tcons
[i
]); /* done with the connection */
1493 osi_auditU(acid
, VS_ForwardEvent
, (code
? code
: codes
[i
]), AUD_LONG
,
1494 fromTrans
, AUD_HOST
, htonl(dest
->server
.destHost
), AUD_LONG
,
1495 dest
->trans
, AUD_END
);
1502 if (TRELE(tt
) && !code
) /* return the first code if it's set */
1503 return VOLSERTRELE_ERROR
;
1510 SAFSVolDump(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
)
1514 code
= VolDump(acid
, fromTrans
, fromDate
, 0);
1515 osi_auditU(acid
, VS_DumpEvent
, code
, AUD_LONG
, fromTrans
, AUD_END
);
1520 SAFSVolDumpV2(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1525 code
= VolDump(acid
, fromTrans
, fromDate
, flags
);
1526 osi_auditU(acid
, VS_DumpEvent
, code
, AUD_LONG
, fromTrans
, AUD_END
);
1531 VolDump(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1535 struct volser_trans
*tt
;
1536 char caller
[MAXKTCNAMELEN
];
1538 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1539 return VOLSERBAD_ACCESS
; /*not a super user */
1540 tt
= FindTrans(fromTrans
);
1543 if (tt
->vflags
& VTDeleted
) {
1544 Log("1 Volser: VolDump: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1548 TSetRxCall(tt
, acid
, "Dump");
1549 code
= DumpVolume(acid
, tt
->volume
, fromDate
, (flags
& VOLDUMPV2_OMITDIRS
)
1550 ? 0 : 1); /* squirt out the volume's data, too */
1559 return VOLSERTRELE_ERROR
;
1565 * Ha! No more helper process!
1568 SAFSVolRestore(struct rx_call
*acid
, afs_int32 atrans
, afs_int32 aflags
,
1569 struct restoreCookie
*cookie
)
1573 code
= VolRestore(acid
, atrans
, aflags
, cookie
);
1574 osi_auditU(acid
, VS_RestoreEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1579 VolRestore(struct rx_call
*acid
, afs_int32 atrans
, afs_int32 aflags
,
1580 struct restoreCookie
*cookie
)
1582 struct volser_trans
*tt
;
1583 afs_int32 code
, tcode
;
1584 char caller
[MAXKTCNAMELEN
];
1586 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1587 return VOLSERBAD_ACCESS
; /*not a super user */
1588 tt
= FindTrans(atrans
);
1591 if (tt
->vflags
& VTDeleted
) {
1592 Log("1 Volser: VolRestore: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1598 Log("%s on %s is executing Restore %" AFS_VOLID_FMT
"\n", caller
,
1599 callerAddress(acid
, buffer
), afs_printable_VolumeId_lu(tt
->volid
));
1601 TSetRxCall(tt
, acid
, "Restore");
1603 DFlushVolume(V_parentId(tt
->volume
)); /* Ensure dir buffers get dropped */
1605 code
= RestoreVolume(acid
, tt
->volume
, (aflags
& 1), cookie
); /* last is incrementalp */
1606 FSYNC_VolOp(tt
->volid
, NULL
, FSYNC_VOL_BREAKCBKS
, 0l, NULL
);
1610 return (code
? code
: tcode
);
1613 /* end a transaction, returning the transaction's final error code in rcode */
1615 SAFSVolEndTrans(struct rx_call
*acid
, afs_int32 destTrans
, afs_int32
*rcode
)
1619 code
= VolEndTrans(acid
, destTrans
, rcode
);
1620 osi_auditU(acid
, VS_EndTrnEvent
, code
, AUD_LONG
, destTrans
, AUD_END
);
1625 VolEndTrans(struct rx_call
*acid
, afs_int32 destTrans
, afs_int32
*rcode
)
1627 struct volser_trans
*tt
;
1628 char caller
[MAXKTCNAMELEN
];
1630 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1631 return VOLSERBAD_ACCESS
; /*not a super user */
1632 tt
= FindTrans(destTrans
);
1636 *rcode
= tt
->returnCode
;
1637 DeleteTrans(tt
, 1); /* this does an implicit TRELE */
1643 SAFSVolSetForwarding(struct rx_call
*acid
, afs_int32 atid
, afs_int32 anewsite
)
1647 code
= VolSetForwarding(acid
, atid
, anewsite
);
1648 osi_auditU(acid
, VS_SetForwEvent
, code
, AUD_LONG
, atid
, AUD_HOST
,
1649 htonl(anewsite
), AUD_END
);
1654 VolSetForwarding(struct rx_call
*acid
, afs_int32 atid
, afs_int32 anewsite
)
1656 struct volser_trans
*tt
;
1657 char caller
[MAXKTCNAMELEN
];
1660 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1661 return VOLSERBAD_ACCESS
; /*not a super user */
1662 tt
= FindTrans(atid
);
1665 if (tt
->vflags
& VTDeleted
) {
1666 Log("1 Volser: VolSetForwarding: volume %" AFS_VOLID_FMT
" has been deleted \n",
1667 afs_printable_VolumeId_lu(tt
->volid
));
1671 TSetRxCall(tt
, acid
, "SetForwarding");
1672 if (volutil_PartitionName2_r(tt
->partition
, partName
, sizeof(partName
)) != 0) {
1675 FSYNC_VolOp(tt
->volid
, partName
, FSYNC_VOL_MOVE
, anewsite
, NULL
);
1678 return VOLSERTRELE_ERROR
;
1684 SAFSVolGetStatus(struct rx_call
*acid
, afs_int32 atrans
,
1685 struct volser_status
*astatus
)
1689 code
= VolGetStatus(acid
, atrans
, astatus
);
1690 osi_auditU(acid
, VS_GetStatEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1695 VolGetStatus(struct rx_call
*acid
, afs_int32 atrans
,
1696 struct volser_status
*astatus
)
1699 struct VolumeDiskData
*td
;
1700 struct volser_trans
*tt
;
1702 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1703 return VOLSERBAD_ACCESS
;
1705 tt
= FindTrans(atrans
);
1708 if (tt
->vflags
& VTDeleted
) {
1709 Log("1 Volser: VolGetStatus: volume %" AFS_VOLID_FMT
" has been deleted \n",
1710 afs_printable_VolumeId_lu(tt
->volid
));
1714 TSetRxCall(tt
, acid
, "GetStatus");
1723 astatus
->volID
= td
->id
;
1724 astatus
->nextUnique
= td
->uniquifier
;
1725 astatus
->type
= td
->type
;
1726 astatus
->parentID
= td
->parentId
;
1727 astatus
->cloneID
= td
->cloneId
;
1728 astatus
->backupID
= td
->backupId
;
1729 astatus
->restoredFromID
= td
->restoredFromId
;
1730 astatus
->maxQuota
= td
->maxquota
;
1731 astatus
->minQuota
= td
->minquota
;
1732 astatus
->owner
= td
->owner
;
1733 astatus
->creationDate
= td
->creationDate
;
1734 astatus
->accessDate
= td
->accessDate
;
1735 astatus
->updateDate
= td
->updateDate
;
1736 astatus
->expirationDate
= td
->expirationDate
;
1737 astatus
->backupDate
= td
->backupDate
;
1738 astatus
->copyDate
= td
->copyDate
;
1741 return VOLSERTRELE_ERROR
;
1747 SAFSVolSetInfo(struct rx_call
*acid
, afs_int32 atrans
,
1748 struct volintInfo
*astatus
)
1752 code
= VolSetInfo(acid
, atrans
, astatus
);
1753 osi_auditU(acid
, VS_SetInfoEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1758 VolSetInfo(struct rx_call
*acid
, afs_int32 atrans
,
1759 struct volintInfo
*astatus
)
1762 struct VolumeDiskData
*td
;
1763 struct volser_trans
*tt
;
1764 char caller
[MAXKTCNAMELEN
];
1767 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1768 return VOLSERBAD_ACCESS
; /*not a super user */
1769 tt
= FindTrans(atrans
);
1772 if (tt
->vflags
& VTDeleted
) {
1773 Log("1 Volser: VolSetInfo: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1777 TSetRxCall(tt
, acid
, "SetStatus");
1787 * Add more fields as necessary
1789 if (astatus
->maxquota
!= -1)
1790 td
->maxquota
= astatus
->maxquota
;
1791 if (astatus
->dayUse
!= -1)
1792 td
->dayUse
= astatus
->dayUse
;
1793 if (astatus
->creationDate
!= -1)
1794 td
->creationDate
= astatus
->creationDate
;
1795 if (astatus
->updateDate
!= -1)
1796 td
->updateDate
= astatus
->updateDate
;
1797 if (astatus
->spare2
!= -1)
1798 td
->volUpdateCounter
= (unsigned int)astatus
->spare2
;
1799 VUpdateVolume(&error
, tv
);
1802 return VOLSERTRELE_ERROR
;
1808 SAFSVolGetName(struct rx_call
*acid
, afs_int32 atrans
, char **aname
)
1812 code
= VolGetName(acid
, atrans
, aname
);
1813 osi_auditU(acid
, VS_GetNameEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1818 VolGetName(struct rx_call
*acid
, afs_int32 atrans
, char **aname
)
1821 struct VolumeDiskData
*td
;
1822 struct volser_trans
*tt
;
1825 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1826 return VOLSERBAD_ACCESS
;
1828 /* We need to at least fill it in */
1832 tt
= FindTrans(atrans
);
1835 if (tt
->vflags
& VTDeleted
) {
1836 Log("1 Volser: VolGetName: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1840 TSetRxCall(tt
, acid
, "GetName");
1849 len
= strlen(td
->name
) + 1; /* don't forget the null */
1855 *aname
= realloc(*aname
, len
);
1856 strcpy(*aname
, td
->name
);
1859 return VOLSERTRELE_ERROR
;
1864 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1867 SAFSVolSignalRestore(struct rx_call
*acid
, char volname
[], int volType
,
1868 VolumeId parentId
, VolumeId cloneId
)
1874 /*return a list of all partitions on the server. The non mounted
1875 *partitions are returned as -1 in the corresponding slot in partIds*/
1877 SAFSVolListPartitions(struct rx_call
*acid
, struct pIDs
*partIds
)
1881 code
= VolListPartitions(acid
, partIds
);
1882 osi_auditU(acid
, VS_ListParEvent
, code
, AUD_END
);
1887 VolListPartitions(struct rx_call
*acid
, struct pIDs
*partIds
)
1892 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1893 return VOLSERBAD_ACCESS
;
1895 strcpy(namehead
, "/vicep"); /*7 including null terminator */
1897 /* Just return attached partitions. */
1899 for (i
= 0; i
< 26; i
++) {
1900 namehead
[6] = i
+ 'a';
1901 partIds
->partIds
[i
] = VGetPartition(namehead
, 0) ? i
: -1;
1907 /*return a list of all partitions on the server. The non mounted
1908 *partitions are returned as -1 in the corresponding slot in partIds*/
1910 SAFSVolXListPartitions(struct rx_call
*acid
, struct partEntries
*pEntries
)
1914 code
= XVolListPartitions(acid
, pEntries
);
1915 osi_auditU(acid
, VS_ListParEvent
, code
, AUD_END
);
1920 XVolListPartitions(struct rx_call
*acid
, struct partEntries
*pEntries
)
1923 struct partList partList
;
1924 struct DiskPartition64
*dp
;
1927 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1928 return VOLSERBAD_ACCESS
;
1930 strcpy(namehead
, "/vicep"); /*7 including null terminator */
1932 /* Only report attached partitions */
1933 for (i
= 0; i
< VOLMAXPARTS
; i
++) {
1934 #ifdef AFS_DEMAND_ATTACH_FS
1935 dp
= VGetPartitionById(i
, 0);
1938 namehead
[6] = i
+ 'a';
1944 namehead
[6] = 'a' + (k
/ 26);
1945 namehead
[7] = 'a' + (k
% 26);
1948 dp
= VGetPartition(namehead
, 0);
1951 partList
.partId
[j
++] = i
;
1954 pEntries
->partEntries_val
= malloc(j
* sizeof(int));
1955 if (!pEntries
->partEntries_val
)
1957 memcpy(pEntries
->partEntries_val
, partList
.partId
,
1959 pEntries
->partEntries_len
= j
;
1961 pEntries
->partEntries_val
= NULL
;
1962 pEntries
->partEntries_len
= 0;
1969 * Scan a directory for possible volume headers.
1970 * in: DIR *dirp -- a directory handle from opendir()
1971 * out: char *volname -- set to name of directory entry
1972 * afs_uint32 *volid -- set to volume ID parsed from name
1974 * true if volname and volid have been set to valid values
1975 * false if we got to the end of the directory
1978 GetNextVol(DIR *dirp
, char *volname
, VolumeId
*volid
)
1982 while ((dp
= readdir(dirp
)) != NULL
) {
1983 /* could be optimized on platforms with dp->d_namlen */
1984 if (dp
->d_name
[0] == 'V' && strlen(dp
->d_name
) == VHDRNAMELEN
1985 && strcmp(&(dp
->d_name
[VFORMATDIGITS
+ 1]), VHDREXT
) == 0) {
1986 *volid
= VolumeNumber(dp
->d_name
);
1987 strcpy(volname
, dp
->d_name
);
1995 * volint vol info structure type.
1998 VOLINT_INFO_TYPE_BASE
, /**< volintInfo type */
1999 VOLINT_INFO_TYPE_EXT
/**< volintXInfo type */
2000 } volint_info_type_t
;
2003 * handle to various on-wire vol info types.
2006 volint_info_type_t volinfo_type
;
2012 } volint_info_handle_t
;
2015 * store value to a field at the appropriate location in on-wire structure.
2017 #define VOLINT_INFO_STORE(handle, name, val) \
2019 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
2020 (handle)->volinfo_ptr.base->name = (val); \
2022 (handle)->volinfo_ptr.ext->name = (val); \
2027 * get pointer to appropriate offset of field in on-wire structure.
2029 #define VOLINT_INFO_PTR(handle, name) \
2030 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
2031 &((handle)->volinfo_ptr.base->name) : \
2032 &((handle)->volinfo_ptr.ext->name))
2035 * fill in appropriate type of on-wire volume metadata structure.
2037 * @param vp pointer to volume object
2038 * @param handle pointer to wire format handle object
2040 * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
2041 * @pre handle object must have a valid pointer and enumeration value
2043 * @note passing a NULL value for vp means that the fileserver doesn't
2044 * know about this particular volume, thus implying it is offline.
2046 * @return operation status
2051 FillVolInfo(Volume
* vp
, volint_info_handle_t
* handle
)
2053 unsigned int numStatBytes
, now
;
2054 struct VolumeDiskData
*hdr
= &(V_disk(vp
));
2056 /*read in the relevant info */
2057 strcpy((char *)VOLINT_INFO_PTR(handle
, name
), hdr
->name
);
2058 VOLINT_INFO_STORE(handle
, status
, VOK
); /*its ok */
2059 VOLINT_INFO_STORE(handle
, volid
, hdr
->id
);
2060 VOLINT_INFO_STORE(handle
, type
, hdr
->type
); /*if ro volume */
2061 VOLINT_INFO_STORE(handle
, cloneID
, hdr
->cloneId
); /*if rw volume */
2062 VOLINT_INFO_STORE(handle
, backupID
, hdr
->backupId
);
2063 VOLINT_INFO_STORE(handle
, parentID
, hdr
->parentId
);
2064 VOLINT_INFO_STORE(handle
, copyDate
, hdr
->copyDate
);
2065 VOLINT_INFO_STORE(handle
, size
, hdr
->diskused
);
2066 VOLINT_INFO_STORE(handle
, maxquota
, hdr
->maxquota
);
2067 VOLINT_INFO_STORE(handle
, filecount
, hdr
->filecount
);
2068 now
= FT_ApproxTime();
2069 if ((now
- hdr
->dayUseDate
) > OneDay
) {
2070 VOLINT_INFO_STORE(handle
, dayUse
, 0);
2072 VOLINT_INFO_STORE(handle
, dayUse
, hdr
->dayUse
);
2074 VOLINT_INFO_STORE(handle
, creationDate
, hdr
->creationDate
);
2075 VOLINT_INFO_STORE(handle
, accessDate
, hdr
->accessDate
);
2076 VOLINT_INFO_STORE(handle
, updateDate
, hdr
->updateDate
);
2077 VOLINT_INFO_STORE(handle
, backupDate
, hdr
->backupDate
);
2079 #ifdef AFS_DEMAND_ATTACH_FS
2081 * for DAFS, we "lie" about volume state --
2082 * instead of returning the raw state from the disk header,
2083 * we compute state based upon the fileserver's internal
2084 * in-core state enumeration value reported to us via fssync,
2085 * along with the blessed and inService flags from the header.
2086 * -- tkeiser 11/27/2007
2089 /* Conditions that offline status is based on:
2090 volume is unattached state
2091 volume state is in (one of several error states)
2092 volume not in service
2093 volume is not marked as blessed (not on hold)
2094 volume in salvage req. state
2095 volume needsSalvaged
2096 next op would set volume offline
2097 next op would not leave volume online (based on several conditions)
2100 (V_attachState(vp
) == VOL_STATE_UNATTACHED
) ||
2101 VIsErrorState(V_attachState(vp
)) ||
2104 (V_attachState(vp
) == VOL_STATE_SALVSYNC_REQ
) ||
2105 hdr
->needsSalvaged
||
2106 (vp
->pending_vol_op
&&
2107 (vp
->pending_vol_op
->com
.command
== FSYNC_VOL_OFF
||
2108 !VVolOpLeaveOnline_r(vp
, vp
->pending_vol_op
) )
2111 VOLINT_INFO_STORE(handle
, inUse
, 0);
2113 VOLINT_INFO_STORE(handle
, inUse
, 1);
2116 /* offline status based on program type, where != fileServer enum (1) is offline */
2117 if (hdr
->inUse
== fileServer
) {
2118 VOLINT_INFO_STORE(handle
, inUse
, 1);
2120 VOLINT_INFO_STORE(handle
, inUse
, 0);
2125 switch(handle
->volinfo_type
) {
2126 /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
2127 case VOLINT_INFO_TYPE_BASE
:
2129 #ifdef AFS_DEMAND_ATTACH_FS
2130 /* see comment above where we set inUse bit */
2131 if (hdr
->needsSalvaged
||
2132 (vp
&& VIsErrorState(V_attachState(vp
)))) {
2133 handle
->volinfo_ptr
.base
->needsSalvaged
= 1;
2135 handle
->volinfo_ptr
.base
->needsSalvaged
= 0;
2138 handle
->volinfo_ptr
.base
->needsSalvaged
= hdr
->needsSalvaged
;
2140 handle
->volinfo_ptr
.base
->destroyMe
= hdr
->destroyMe
;
2141 handle
->volinfo_ptr
.base
->spare0
= hdr
->minquota
;
2142 handle
->volinfo_ptr
.base
->spare1
=
2143 (long)hdr
->weekUse
[0] +
2144 (long)hdr
->weekUse
[1] +
2145 (long)hdr
->weekUse
[2] +
2146 (long)hdr
->weekUse
[3] +
2147 (long)hdr
->weekUse
[4] +
2148 (long)hdr
->weekUse
[5] +
2149 (long)hdr
->weekUse
[6];
2150 handle
->volinfo_ptr
.base
->flags
= 0;
2151 handle
->volinfo_ptr
.base
->spare2
= hdr
->volUpdateCounter
;
2152 handle
->volinfo_ptr
.base
->spare3
= 0;
2156 case VOLINT_INFO_TYPE_EXT
:
2158 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS
) +
2159 (4 * VOLINT_STATS_NUM_TIME_FIELDS
));
2162 * Copy out the stat fields in a single operation.
2164 if ((now
- hdr
->dayUseDate
) > OneDay
) {
2165 memset(&(handle
->volinfo_ptr
.ext
->stat_reads
[0]),
2168 memcpy((char *)&(handle
->volinfo_ptr
.ext
->stat_reads
[0]),
2169 (char *)&(hdr
->stat_reads
[0]),
2178 #ifdef AFS_DEMAND_ATTACH_FS
2181 * get struct Volume out of the fileserver.
2183 * @param[in] volumeId volumeId for which we want state information
2184 * @param[in] pname partition name string
2185 * @param[inout] vp pointer to pointer to Volume object which
2186 * will be populated (see note)
2188 * @return operation status
2190 * @retval non-zero failure
2192 * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
2197 GetVolObject(VolumeId volumeId
, char * pname
, Volume
** vp
)
2202 res
.hdr
.response_len
= sizeof(res
.hdr
);
2203 res
.payload
.buf
= *vp
;
2204 res
.payload
.len
= sizeof(Volume
);
2206 code
= FSYNC_VolOp(volumeId
,
2212 if (code
!= SYNC_OK
) {
2213 switch (res
.hdr
.reason
) {
2214 case FSYNC_WRONG_PART
:
2215 case FSYNC_UNKNOWN_VOLID
:
2228 * mode of volume list operation.
2231 VOL_INFO_LIST_SINGLE
, /**< performing a single volume list op */
2232 VOL_INFO_LIST_MULTIPLE
/**< performing a multi-volume list op */
2233 } vol_info_list_mode_t
;
2236 * abstract interface to populate wire-format volume metadata structures.
2238 * @param[in] partId partition id
2239 * @param[in] volumeId volume id
2240 * @param[in] pname partition name
2241 * @param[in] volname volume file name
2242 * @param[in] handle handle to on-wire volume metadata object
2243 * @param[in] mode listing mode
2245 * @return operation status
2247 * @retval -2 DESTROY_ME flag is set
2248 * @retval -1 general failure; some data filled in
2249 * @retval -3 couldn't create vtrans; some data filled in
2252 GetVolInfo(afs_uint32 partId
,
2256 volint_info_handle_t
* handle
,
2257 vol_info_list_mode_t mode
)
2261 struct volser_trans
*ttc
= NULL
;
2262 struct Volume
*fill_tv
, *tv
= NULL
;
2263 #ifdef AFS_DEMAND_ATTACH_FS
2264 struct Volume fs_tv_buf
, *fs_tv
= &fs_tv_buf
; /* Create a structure, and a pointer to that structure */
2265 SYNC_PROTO_BUF_DECL(fs_res_buf
); /* Buffer for the pending_vol_op */
2266 SYNC_response fs_res
; /* Response handle for the pending_vol_op */
2267 FSSYNC_VolOp_info pending_vol_op_res
; /* Pending vol ops to full in volume */
2269 /* Set up response handle for pending_vol_op */
2270 fs_res
.hdr
.response_len
= sizeof(fs_res
.hdr
);
2271 fs_res
.payload
.buf
= fs_res_buf
;
2272 fs_res
.payload
.len
= SYNC_PROTO_MAX_LEN
;
2275 ttc
= NewTrans(volumeId
, partId
);
2278 VOLINT_INFO_STORE(handle
, status
, VBUSY
);
2279 VOLINT_INFO_STORE(handle
, volid
, volumeId
);
2283 /* Get volume from volserver */
2284 if (mode
== VOL_INFO_LIST_MULTIPLE
)
2285 tv
= VAttachVolumeByName(&error
, pname
, volname
, V_PEEK
);
2287 #ifdef AFS_DEMAND_ATTACH_FS
2290 int mode
= V_READONLY
; /* informs the fileserver to update the volume headers. */
2292 tv
= VAttachVolumeByName_retry(&error
, pname
, volname
, mode
);
2296 Log("1 Volser: GetVolInfo: Could not attach volume %" AFS_VOLID_FMT
" (%s:%s) error=%d\n",
2297 afs_printable_VolumeId_lu(volumeId
), pname
, volname
, error
);
2302 * please note that destroyMe and needsSalvaged checks used to be ordered
2303 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2304 * more correct to check destroyMe before needsSalvaged.
2305 * -- tkeiser 11/28/2007
2308 if (V_destroyMe(tv
) == DESTROY_ME
) {
2310 case VOL_INFO_LIST_MULTIPLE
:
2314 case VOL_INFO_LIST_SINGLE
:
2315 Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT
" (%s:%s) will be destroyed on next salvage\n",
2316 afs_printable_VolumeId_lu(volumeId
), pname
, volname
);
2323 if (V_needsSalvaged(tv
)) {
2324 /*this volume will be salvaged */
2325 Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT
" (%s:%s) needs to be salvaged\n",
2326 afs_printable_VolumeId_lu(volumeId
), pname
, volname
);
2329 #ifdef AFS_DEMAND_ATTACH_FS
2330 /* If using DAFS, get volume from fsserver */
2331 if (GetVolObject(volumeId
, pname
, &fs_tv
) != SYNC_OK
|| fs_tv
== NULL
) {
2336 /* fs_tv is a shallow copy, must populate certain structures before passing along */
2337 if (FSYNC_VolOp(volumeId
, pname
, FSYNC_VOL_QUERY_VOP
, 0, &fs_res
) == SYNC_OK
) {
2338 /* If we if the pending vol op */
2339 memcpy(&pending_vol_op_res
, fs_res
.payload
.buf
, sizeof(FSSYNC_VolOp_info
));
2340 fs_tv
->pending_vol_op
=&pending_vol_op_res
;
2342 fs_tv
->pending_vol_op
=NULL
;
2345 /* populate the header from the volserver copy */
2346 fs_tv
->header
=tv
->header
;
2348 /* When using DAFS, use the fs volume info, populated with required structures */
2351 /* When not using DAFS, just use the local volume info */
2355 /* ok, we have all the data we need; fill in the on-wire struct */
2356 code
= FillVolInfo(fill_tv
, handle
);
2360 VOLINT_INFO_STORE(handle
, status
, 0);
2361 strcpy((char *)VOLINT_INFO_PTR(handle
, name
), volname
);
2362 VOLINT_INFO_STORE(handle
, volid
, volumeId
);
2365 VDetachVolume(&error
, tv
);
2368 VOLINT_INFO_STORE(handle
, status
, 0);
2369 strcpy((char *)VOLINT_INFO_PTR(handle
, name
), volname
);
2370 Log("1 Volser: GetVolInfo: Could not detach volume %" AFS_VOLID_FMT
" (%s:%s)\n",
2371 afs_printable_VolumeId_lu(volumeId
), pname
, volname
);
2375 DeleteTrans(ttc
, 1);
2382 /*return the header information about the <volid> */
2384 SAFSVolListOneVolume(struct rx_call
*acid
, afs_int32 partid
,
2385 VolumeId volumeId
, volEntries
*volumeInfo
)
2389 code
= VolListOneVolume(acid
, partid
, volumeId
, volumeInfo
);
2390 osi_auditU(acid
, VS_Lst1VolEvent
, code
, AUD_LONG
, volumeId
, AUD_END
);
2395 VolListOneVolume(struct rx_call
*acid
, afs_int32 partid
,
2396 VolumeId volumeId
, volEntries
*volumeInfo
)
2398 struct DiskPartition64
*partP
;
2399 char pname
[9], volname
[20];
2403 volint_info_handle_t handle
;
2405 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
2406 return VOLSERBAD_ACCESS
;
2408 volumeInfo
->volEntries_val
= calloc(1, sizeof(volintInfo
));
2409 if (!volumeInfo
->volEntries_val
)
2412 volumeInfo
->volEntries_len
= 1;
2413 if (GetPartName(partid
, pname
))
2414 return VOLSERILLEGAL_PARTITION
;
2415 if (!(partP
= VGetPartition(pname
, 0)))
2416 return VOLSERILLEGAL_PARTITION
;
2417 dirp
= opendir(VPartitionPath(partP
));
2419 return VOLSERILLEGAL_PARTITION
;
2421 while (GetNextVol(dirp
, volname
, &volid
)) {
2422 if (volid
== volumeId
) { /*copy other things too */
2429 #ifndef AFS_PTHREAD_ENV
2430 IOMGR_Poll(); /*make sure that the client does not time out */
2433 handle
.volinfo_type
= VOLINT_INFO_TYPE_BASE
;
2434 handle
.volinfo_ptr
.base
= volumeInfo
->volEntries_val
;
2436 /* The return code from GetVolInfo is ignored; there is no error from
2437 * it that results in the whole call being aborted. Any volume
2438 * attachment failures are reported in 'status' field in the
2439 * volumeInfo payload. */
2445 VOL_INFO_LIST_SINGLE
);
2449 return (found
) ? 0 : ENODEV
;
2452 /*------------------------------------------------------------------------
2453 * EXPORTED SAFSVolXListOneVolume
2456 * Returns extended info on volume a_volID on partition a_partID.
2459 * a_rxCidP : Pointer to the Rx call we're performing.
2460 * a_partID : Partition for which we want the extended list.
2461 * a_volID : Volume ID we wish to know about.
2462 * a_volumeXInfoP : Ptr to the extended info blob.
2465 * 0 Successful operation
2466 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2469 * Nothing interesting.
2473 *------------------------------------------------------------------------*/
2476 SAFSVolXListOneVolume(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2477 VolumeId a_volID
, volXEntries
*a_volumeXInfoP
)
2481 code
= VolXListOneVolume(a_rxCidP
, a_partID
, a_volID
, a_volumeXInfoP
);
2482 osi_auditU(a_rxCidP
, VS_XLst1VlEvent
, code
, AUD_LONG
, a_volID
, AUD_END
);
2487 VolXListOneVolume(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2488 VolumeId a_volID
, volXEntries
*a_volumeXInfoP
)
2489 { /*SAFSVolXListOneVolume */
2491 struct DiskPartition64
*partP
; /*Ptr to partition */
2492 char pname
[9], volname
[20]; /*Partition, volume names */
2493 DIR *dirp
; /*Partition directory ptr */
2494 VolumeId currVolID
; /*Current volume ID */
2495 int found
= 0; /*Did we find the volume we need? */
2496 volint_info_handle_t handle
;
2498 if (!afsconf_CheckRestrictedQuery(tdir
, a_rxCidP
, restrictedQueryLevel
))
2499 return VOLSERBAD_ACCESS
;
2502 * Set up our pointers for action, marking our structure to hold exactly
2503 * one entry. Also, assume we'll fail in our quest.
2505 a_volumeXInfoP
->volXEntries_val
= calloc(1, sizeof(volintXInfo
));
2506 if (!a_volumeXInfoP
->volXEntries_val
)
2509 a_volumeXInfoP
->volXEntries_len
= 1;
2512 * If the partition name we've been given is bad, bogue out.
2514 if (GetPartName(a_partID
, pname
))
2515 return (VOLSERILLEGAL_PARTITION
);
2518 * Open the directory representing the given AFS parttion. If we can't
2521 if (!(partP
= VGetPartition(pname
, 0)))
2522 return VOLSERILLEGAL_PARTITION
;
2523 dirp
= opendir(VPartitionPath(partP
));
2525 return (VOLSERILLEGAL_PARTITION
);
2529 * Sweep through the partition directory, looking for the desired entry.
2530 * First, of course, figure out how many stat bytes to copy out of each
2533 while (GetNextVol(dirp
, volname
, &currVolID
)) {
2534 if (currVolID
== a_volID
) {
2536 * We found the volume entry we're interested. Pull out the
2537 * extended information, remembering to poll (so that the client
2538 * doesn't time out) and to set up a transaction on the volume.
2542 } /*Found desired volume */
2546 #ifndef AFS_PTHREAD_ENV
2550 handle
.volinfo_type
= VOLINT_INFO_TYPE_EXT
;
2551 handle
.volinfo_ptr
.ext
= a_volumeXInfoP
->volXEntries_val
;
2553 /* The return code from GetVolInfo is ignored; there is no error from
2554 * it that results in the whole call being aborted. Any volume
2555 * attachment failures are reported in 'status' field in the
2556 * volumeInfo payload. */
2557 GetVolInfo(a_partID
,
2562 VOL_INFO_LIST_SINGLE
);
2566 * Clean up before going to dinner: close the partition directory,
2567 * return the proper value.
2570 return (found
) ? 0 : ENODEV
;
2571 } /*SAFSVolXListOneVolume */
2573 /*returns all the volumes on partition partid. If flags = 1 then all the
2574 * relevant info about the volumes is also returned */
2576 SAFSVolListVolumes(struct rx_call
*acid
, afs_int32 partid
, afs_int32 flags
,
2577 volEntries
*volumeInfo
)
2581 code
= VolListVolumes(acid
, partid
, flags
, volumeInfo
);
2582 osi_auditU(acid
, VS_ListVolEvent
, code
, AUD_END
);
2587 VolListVolumes(struct rx_call
*acid
, afs_int32 partid
, afs_int32 flags
,
2588 volEntries
*volumeInfo
)
2591 struct DiskPartition64
*partP
;
2592 afs_int32 allocSize
= 1000; /*to be changed to a larger figure */
2593 char pname
[9], volname
[20];
2597 volint_info_handle_t handle
;
2599 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
2600 return VOLSERBAD_ACCESS
;
2602 volumeInfo
->volEntries_val
= calloc(allocSize
, sizeof(volintInfo
));
2603 if (!volumeInfo
->volEntries_val
)
2606 pntr
= volumeInfo
->volEntries_val
;
2607 volumeInfo
->volEntries_len
= 0;
2608 if (GetPartName(partid
, pname
))
2609 return VOLSERILLEGAL_PARTITION
;
2610 if (!(partP
= VGetPartition(pname
, 0)))
2611 return VOLSERILLEGAL_PARTITION
;
2612 dirp
= opendir(VPartitionPath(partP
));
2614 return VOLSERILLEGAL_PARTITION
;
2616 while (GetNextVol(dirp
, volname
, &volid
)) {
2617 if (flags
) { /*copy other things too */
2618 #ifndef AFS_PTHREAD_ENV
2619 IOMGR_Poll(); /*make sure that the client does not time out */
2622 handle
.volinfo_type
= VOLINT_INFO_TYPE_BASE
;
2623 handle
.volinfo_ptr
.base
= pntr
;
2626 code
= GetVolInfo(partid
,
2631 VOL_INFO_LIST_MULTIPLE
);
2632 if (code
== -2) /* DESTROY_ME flag set */
2635 pntr
->volid
= volid
;
2636 /*just volids are needed */
2640 volumeInfo
->volEntries_len
+= 1;
2641 if ((allocSize
- volumeInfo
->volEntries_len
) < 5) {
2642 /*running out of space, allocate more space */
2643 allocSize
= (allocSize
* 3) / 2;
2644 pntr
= realloc(volumeInfo
->volEntries_val
,
2645 allocSize
* sizeof(volintInfo
));
2648 return VOLSERNO_MEMORY
;
2650 volumeInfo
->volEntries_val
= pntr
; /* point to new block */
2651 /* set pntr to the right position */
2652 pntr
= volumeInfo
->volEntries_val
+ volumeInfo
->volEntries_len
;
2660 /*------------------------------------------------------------------------
2661 * EXPORTED SAFSVolXListVolumes
2664 * Returns all the volumes on partition a_partID. If a_flags
2665 * is set to 1, then all the relevant extended volume information
2669 * a_rxCidP : Pointer to the Rx call we're performing.
2670 * a_partID : Partition for which we want the extended list.
2671 * a_flags : Various flags.
2672 * a_volumeXInfoP : Ptr to the extended info blob.
2675 * 0 Successful operation
2676 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2677 * VOLSERNO_MEMORY if we ran out of memory allocating
2681 * Nothing interesting.
2685 *------------------------------------------------------------------------*/
2688 SAFSVolXListVolumes(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2689 afs_int32 a_flags
, volXEntries
*a_volumeXInfoP
)
2693 code
= VolXListVolumes(a_rxCidP
, a_partID
, a_flags
, a_volumeXInfoP
);
2694 osi_auditU(a_rxCidP
, VS_XLstVolEvent
, code
, AUD_END
);
2699 VolXListVolumes(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2700 afs_int32 a_flags
, volXEntries
*a_volumeXInfoP
)
2701 { /*SAFSVolXListVolumes */
2703 volintXInfo
*xInfoP
; /*Ptr to the extended vol info */
2704 struct DiskPartition64
*partP
; /*Ptr to partition */
2705 afs_int32 allocSize
= 1000; /*To be changed to a larger figure */
2706 char pname
[9], volname
[20]; /*Partition, volume names */
2707 DIR *dirp
; /*Partition directory ptr */
2708 VolumeId volid
; /*Current volume ID */
2710 volint_info_handle_t handle
;
2712 if (!afsconf_CheckRestrictedQuery(tdir
, a_rxCidP
, restrictedQueryLevel
))
2713 return VOLSERBAD_ACCESS
;
2716 * Allocate a large array of extended volume info structures, then
2717 * set it up for action.
2719 a_volumeXInfoP
->volXEntries_val
= calloc(allocSize
, sizeof(volintXInfo
));
2720 if (!a_volumeXInfoP
->volXEntries_val
)
2723 xInfoP
= a_volumeXInfoP
->volXEntries_val
;
2724 a_volumeXInfoP
->volXEntries_len
= 0;
2727 * If the partition name we've been given is bad, bogue out.
2729 if (GetPartName(a_partID
, pname
))
2730 return (VOLSERILLEGAL_PARTITION
);
2733 * Open the directory representing the given AFS parttion. If we can't
2736 if (!(partP
= VGetPartition(pname
, 0)))
2737 return VOLSERILLEGAL_PARTITION
;
2738 dirp
= opendir(VPartitionPath(partP
));
2740 return (VOLSERILLEGAL_PARTITION
);
2741 while (GetNextVol(dirp
, volname
, &volid
)) {
2744 * Full info about the volume desired. Poll to make sure the
2745 * client doesn't time out, then start up a new transaction.
2747 #ifndef AFS_PTHREAD_ENV
2751 handle
.volinfo_type
= VOLINT_INFO_TYPE_EXT
;
2752 handle
.volinfo_ptr
.ext
= xInfoP
;
2754 code
= GetVolInfo(a_partID
,
2759 VOL_INFO_LIST_MULTIPLE
);
2760 if (code
== -2) /* DESTROY_ME flag set */
2764 * Just volume IDs are needed.
2766 xInfoP
->volid
= volid
;
2770 * Bump the pointer in the data area we're building, along with
2771 * the count of the number of entries it contains.
2774 (a_volumeXInfoP
->volXEntries_len
)++;
2775 if ((allocSize
- a_volumeXInfoP
->volXEntries_len
) < 5) {
2777 * We're running out of space in the area we've built. Grow it.
2779 allocSize
= (allocSize
* 3) / 2;
2780 xInfoP
= (volintXInfo
*)
2781 realloc((char *)a_volumeXInfoP
->volXEntries_val
,
2782 (allocSize
* sizeof(volintXInfo
)));
2783 if (xInfoP
== NULL
) {
2785 * Bummer, no memory. Bag it, tell our caller what went wrong.
2788 return (VOLSERNO_MEMORY
);
2792 * Memory reallocation worked. Correct our pointers so they
2793 * now point to the new block and the current open position within
2796 a_volumeXInfoP
->volXEntries_val
= xInfoP
;
2798 a_volumeXInfoP
->volXEntries_val
+
2799 a_volumeXInfoP
->volXEntries_len
;
2804 * We've examined all entries in the partition directory. Close it,
2805 * delete our transaction (if any), and go home happy.
2810 } /*SAFSVolXListVolumes */
2812 /*this call is used to monitor the status of volser for debugging purposes.
2813 *information about all the active transactions is returned in transInfo*/
2815 SAFSVolMonitor(struct rx_call
*acid
, transDebugEntries
*transInfo
)
2819 code
= VolMonitor(acid
, transInfo
);
2820 osi_auditU(acid
, VS_MonitorEvent
, code
, AUD_END
);
2825 VolMonitor(struct rx_call
*acid
, transDebugEntries
*transInfo
)
2827 transDebugInfo
*pntr
;
2828 afs_int32 allocSize
= 50;
2829 struct volser_trans
*tt
, *nt
, *allTrans
;
2831 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
2832 return VOLSERBAD_ACCESS
;
2834 transInfo
->transDebugEntries_val
=
2835 malloc(allocSize
* sizeof(transDebugInfo
));
2836 if (!transInfo
->transDebugEntries_val
)
2838 pntr
= transInfo
->transDebugEntries_val
;
2839 transInfo
->transDebugEntries_len
= 0;
2842 allTrans
= TransList();
2843 if (allTrans
== (struct volser_trans
*)0)
2844 goto done
; /*no active transactions */
2845 for (tt
= allTrans
; tt
; tt
= nt
) { /*copy relevant info into pntr */
2847 VTRANS_OBJ_LOCK(tt
);
2848 pntr
->tid
= tt
->tid
;
2849 pntr
->time
= tt
->time
;
2850 pntr
->creationTime
= tt
->creationTime
;
2851 pntr
->returnCode
= tt
->returnCode
;
2852 pntr
->volid
= tt
->volid
;
2853 pntr
->partition
= tt
->partition
;
2854 pntr
->iflags
= tt
->iflags
;
2855 pntr
->vflags
= tt
->vflags
;
2856 pntr
->tflags
= tt
->tflags
;
2857 strcpy(pntr
->lastProcName
, tt
->lastProcName
);
2858 pntr
->callValid
= 0;
2859 if (tt
->rxCallPtr
) { /*record call related info */
2860 pntr
->callValid
= 1;
2862 pntr
->readNext
= tt
->rxCallPtr
->rnext
;
2863 pntr
->transmitNext
= tt
->rxCallPtr
->tnext
;
2864 pntr
->lastSendTime
= tt
->rxCallPtr
->lastSendTime
;
2865 pntr
->lastReceiveTime
= tt
->rxCallPtr
->lastReceiveTime
;
2868 VTRANS_OBJ_UNLOCK(tt
);
2870 transInfo
->transDebugEntries_len
+= 1;
2871 if ((allocSize
- transInfo
->transDebugEntries_len
) < 5) { /*alloc some more space */
2872 allocSize
= (allocSize
* 3) / 2;
2873 pntr
= realloc(transInfo
->transDebugEntries_val
,
2874 allocSize
* sizeof(transDebugInfo
));
2875 transInfo
->transDebugEntries_val
= pntr
;
2877 transInfo
->transDebugEntries_val
+
2878 transInfo
->transDebugEntries_len
;
2879 /*set pntr to right position */
2890 SAFSVolSetIdsTypes(struct rx_call
*acid
, afs_int32 atid
, char name
[],
2891 afs_int32 type
, afs_uint32 pId
, VolumeId cloneId
,
2896 code
= VolSetIdsTypes(acid
, atid
, name
, type
, pId
, cloneId
, backupId
);
2897 osi_auditU(acid
, VS_SetIdTyEvent
, code
, AUD_LONG
, atid
, AUD_STR
, name
,
2898 AUD_LONG
, type
, AUD_LONG
, pId
, AUD_LONG
, cloneId
, AUD_LONG
,
2904 VolSetIdsTypes(struct rx_call
*acid
, afs_int32 atid
, char name
[],
2905 afs_int32 type
, VolumeId pId
, VolumeId cloneId
,
2910 struct volser_trans
*tt
;
2911 char caller
[MAXKTCNAMELEN
];
2913 if (strlen(name
) > 31)
2914 return VOLSERBADNAME
;
2915 if (!afsconf_SuperUser(tdir
, acid
, caller
))
2916 return VOLSERBAD_ACCESS
; /*not a super user */
2917 /* find the trans */
2918 tt
= FindTrans(atid
);
2921 if (tt
->vflags
& VTDeleted
) {
2922 Log("1 Volser: VolSetIds: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
2926 TSetRxCall(tt
, acid
, "SetIdsTypes");
2930 V_backupId(tv
) = backupId
;
2931 V_cloneId(tv
) = cloneId
;
2932 V_parentId(tv
) = pId
;
2933 strcpy((&V_disk(tv
))->name
, name
);
2934 VUpdateVolume(&error
, tv
);
2936 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error
);
2941 if (TRELE(tt
) && !error
)
2942 return VOLSERTRELE_ERROR
;
2947 if (TRELE(tt
) && !error
)
2948 return VOLSERTRELE_ERROR
;
2953 SAFSVolSetDate(struct rx_call
*acid
, afs_int32 atid
, afs_int32 cdate
)
2957 code
= VolSetDate(acid
, atid
, cdate
);
2958 osi_auditU(acid
, VS_SetDateEvent
, code
, AUD_LONG
, atid
, AUD_LONG
, cdate
,
2964 VolSetDate(struct rx_call
*acid
, afs_int32 atid
, afs_int32 cdate
)
2968 struct volser_trans
*tt
;
2969 char caller
[MAXKTCNAMELEN
];
2971 if (!afsconf_SuperUser(tdir
, acid
, caller
))
2972 return VOLSERBAD_ACCESS
; /*not a super user */
2973 /* find the trans */
2974 tt
= FindTrans(atid
);
2977 if (tt
->vflags
& VTDeleted
) {
2978 Log("1 Volser: VolSetDate: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
2982 TSetRxCall(tt
, acid
, "SetDate");
2985 V_creationDate(tv
) = cdate
;
2986 VUpdateVolume(&error
, tv
);
2988 Log("1 Volser: SetDate: VUpdate failed code %d\n", error
);
2993 if (TRELE(tt
) && !error
)
2994 return VOLSERTRELE_ERROR
;
2999 if (TRELE(tt
) && !error
)
3000 return VOLSERTRELE_ERROR
;
3005 SAFSVolConvertROtoRWvolume(struct rx_call
*acid
, afs_int32 partId
,
3011 char caller
[MAXKTCNAMELEN
];
3013 struct volser_trans
*ttc
;
3014 char pname
[16], volname
[20];
3015 struct DiskPartition64
*partP
;
3016 afs_int32 ret
= ENODEV
;
3019 if (!afsconf_SuperUser(tdir
, acid
, caller
))
3020 return VOLSERBAD_ACCESS
; /*not a super user */
3021 if (GetPartName(partId
, pname
))
3022 return VOLSERILLEGAL_PARTITION
;
3023 if (!(partP
= VGetPartition(pname
, 0)))
3024 return VOLSERILLEGAL_PARTITION
;
3025 dirp
= opendir(VPartitionPath(partP
));
3027 return VOLSERILLEGAL_PARTITION
;
3028 ttc
= (struct volser_trans
*)0;
3030 while (GetNextVol(dirp
, volname
, &volid
)) {
3031 if (volid
== volumeId
) { /*copy other things too */
3032 #ifndef AFS_PTHREAD_ENV
3033 IOMGR_Poll(); /*make sure that the client doesnot time out */
3035 ttc
= NewTrans(volumeId
, partId
);
3037 return VOLSERVOLBUSY
;
3039 #ifdef AFS_NAMEI_ENV
3040 ret
= namei_ConvertROtoRWvolume(pname
, volumeId
);
3042 ret
= inode_ConvertROtoRWvolume(pname
, volumeId
);
3049 DeleteTrans(ttc
, 1);
3057 SAFSVolGetSize(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
3058 struct volintSize
*size
)
3061 struct volser_trans
*tt
;
3062 char caller
[MAXKTCNAMELEN
];
3064 if (!afsconf_SuperUser(tdir
, acid
, caller
))
3065 return VOLSERBAD_ACCESS
; /*not a super user */
3066 tt
= FindTrans(fromTrans
);
3069 if (tt
->vflags
& VTDeleted
) {
3073 TSetRxCall(tt
, acid
, "GetSize");
3074 code
= SizeDumpVolume(acid
, tt
->volume
, fromDate
, 1, size
); /* measure volume's data */
3077 return VOLSERTRELE_ERROR
;
3079 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
3084 SAFSVolSplitVolume(struct rx_call
*acall
, afs_uint32 ovid
, afs_uint32 onew
,
3085 afs_uint32 where
, afs_int32 verbose
)
3087 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
3089 Volume
*vol
=0, *newvol
=0;
3090 struct volser_trans
*tt
= 0, *tt2
= 0;
3091 char caller
[MAXKTCNAMELEN
];
3093 VolumeId
new = onew
;
3094 VolumeId vid
= ovid
;
3096 if (!afsconf_SuperUser(tdir
, acall
, caller
))
3099 vol
= VAttachVolume(&code
, vid
, V_VOLUPD
);
3105 newvol
= VAttachVolume(&code
, new, V_VOLUPD
);
3107 VDetachVolume(&code2
, vol
);
3112 if (V_device(vol
) != V_device(newvol
)
3113 || V_uniquifier(newvol
) != 2) {
3114 if (V_device(vol
) != V_device(newvol
)) {
3115 sprintf(line
, "Volumes %" AFS_VOLID_FMT
" and %" AFS_VOLID_FMT
" are not in the same partition, aborted.\n",
3116 afs_printable_VolumeId_lu(vid
),
3117 afs_printable_VolumeId_lu(new));
3118 rx_Write(acall
, line
, strlen(line
));
3120 if (V_uniquifier(newvol
) != 2) {
3121 sprintf(line
, "Volume %" AFS_VOLID_FMT
" is not freshly created, aborted.\n",
3122 afs_printable_VolumeId_lu(new));
3123 rx_Write(acall
, line
, strlen(line
));
3126 rx_Write(acall
, line
, 1);
3127 VDetachVolume(&code2
, vol
);
3128 VDetachVolume(&code2
, newvol
);
3131 tt
= NewTrans(vid
, V_device(vol
));
3133 sprintf(line
, "Couldn't create transaction for %" AFS_VOLID_FMT
", aborted.\n",
3134 afs_printable_VolumeId_lu(vid
));
3135 rx_Write(acall
, line
, strlen(line
));
3137 rx_Write(acall
, line
, 1);
3138 VDetachVolume(&code2
, vol
);
3139 VDetachVolume(&code2
, newvol
);
3140 return VOLSERVOLBUSY
;
3142 VTRANS_OBJ_LOCK(tt
);
3143 tt
->iflags
= ITBusy
;
3145 TSetRxCall_r(tt
, NULL
, "SplitVolume");
3146 VTRANS_OBJ_UNLOCK(tt
);
3148 tt2
= NewTrans(new, V_device(newvol
));
3150 sprintf(line
, "Couldn't create transaction for %" AFS_VOLID_FMT
", aborted.\n",
3151 afs_printable_VolumeId_lu(new));
3152 rx_Write(acall
, line
, strlen(line
));
3154 rx_Write(acall
, line
, 1);
3156 VDetachVolume(&code2
, vol
);
3157 VDetachVolume(&code2
, newvol
);
3158 return VOLSERVOLBUSY
;
3160 VTRANS_OBJ_LOCK(tt2
);
3161 tt2
->iflags
= ITBusy
;
3163 TSetRxCall_r(tt2
, NULL
, "SplitVolume");
3164 VTRANS_OBJ_UNLOCK(tt2
);
3166 code
= split_volume(acall
, vol
, newvol
, where
, verbose
);
3168 VDetachVolume(&code2
, vol
);
3170 VDetachVolume(&code2
, newvol
);
3171 DeleteTrans(tt2
, 1);
3178 /* GetPartName - map partid (a decimal number) into pname (a string)
3179 * Since for NT we actually want to return the drive name, we map through the
3183 GetPartName(afs_int32 partid
, char *pname
)
3188 strcpy(pname
, "/vicep");
3189 pname
[6] = 'a' + partid
;
3192 } else if (partid
< VOLMAXPARTS
) {
3193 strcpy(pname
, "/vicep");
3195 pname
[6] = 'a' + (partid
/ 26);
3196 pname
[7] = 'a' + (partid
% 26);