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 memset(partition
, 0, sizeof(*partition
));
424 code
= VolPartitionInfo(acid
, pname
, dp
);
426 strncpy(partition
->name
, dp
->name
, 32);
427 strncpy(partition
->devName
, dp
->devName
, 32);
428 partition
->lock_fd
= dp
->lock_fd
;
429 partition
->free
=RoundInt64ToInt32(dp
->free
);
430 partition
->minFree
=RoundInt64ToInt32(dp
->minFree
);
433 osi_auditU(acid
, VS_ParInfEvent
, code
, AUD_STR
, pname
, AUD_END
);
438 SAFSVolPartitionInfo64(struct rx_call
*acid
, char *pname
, struct diskPartition64
443 memset(partition
, 0, sizeof(*partition
));
444 code
= VolPartitionInfo(acid
, pname
, partition
);
445 osi_auditU(acid
, VS_ParInfEvent
, code
, AUD_STR
, pname
, AUD_END
);
450 VolPartitionInfo(struct rx_call
*acid
, char *pname
, struct diskPartition64
453 struct DiskPartition64
*dp
;
455 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
456 return VOLSERBAD_ACCESS
;
459 dp
= VGetPartition(pname
, 0);
461 strncpy(partition
->name
, dp
->name
, 32);
462 strncpy(partition
->devName
, dp
->devName
, 32);
463 partition
->lock_fd
= (int)dp
->lock_fd
;
464 partition
->free
= dp
->free
;
465 partition
->minFree
= dp
->totalUsable
;
468 return VOLSERILLEGAL_PARTITION
;
471 /* obliterate a volume completely, and slowly. */
473 SAFSVolNukeVolume(struct rx_call
*acid
, afs_int32 apartID
, VolumeId avolID
)
477 code
= VolNukeVolume(acid
, apartID
, avolID
);
478 osi_auditU(acid
, VS_NukVolEvent
, code
, AUD_LONG
, avolID
, AUD_END
);
483 VolNukeVolume(struct rx_call
*acid
, afs_int32 apartID
, afs_uint32 avolID
)
490 char caller
[MAXKTCNAMELEN
];
492 /* check for access */
493 if (!afsconf_SuperUser(tdir
, acid
, caller
))
494 return VOLSERBAD_ACCESS
;
497 Log("%s on %s is executing VolNukeVolume %u\n", caller
,
498 callerAddress(acid
, buffer
), avolID
);
501 if (volutil_PartitionName2_r(apartID
, partName
, sizeof(partName
)) != 0)
503 /* we first try to attach the volume in update mode, so that the file
504 * server doesn't try to use it (and abort) while (or after) we delete it.
505 * If we don't get the volume, that's fine, too. We just won't put it back.
507 tvp
= XAttachVolume(&error
, avolID
, apartID
, V_VOLUPD
);
508 code
= nuke(partName
, avolID
);
510 VDetachVolume(&verror
, tvp
);
514 /* create a new volume, with name aname, on the specified partition (1..n)
515 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
516 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
517 * for the volume id (useful for things like volume restore).
518 * Return the new volume id in *avolid.
521 SAFSVolCreateVolume(struct rx_call
*acid
, afs_int32 apart
, char *aname
,
522 afs_int32 atype
, VolumeId aparent
, VolumeId
*avolid
,
528 VolCreateVolume(acid
, apart
, aname
, atype
, aparent
, avolid
, atrans
);
529 osi_auditU(acid
, VS_CrVolEvent
, code
, AUD_LONG
, *atrans
, AUD_LONG
,
530 *avolid
, AUD_STR
, aname
, AUD_LONG
, atype
, AUD_LONG
, aparent
,
536 VolCreateVolume(struct rx_call
*acid
, afs_int32 apart
, char *aname
,
537 afs_int32 atype
, afs_uint32 aparent
, afs_uint32
*avolid
,
542 Error junk
; /* discardable error code */
544 afs_int32 doCreateRoot
= 1;
545 struct volser_trans
*tt
;
547 char caller
[MAXKTCNAMELEN
];
549 if (strlen(aname
) > 31)
550 return VOLSERBADNAME
;
551 if (!afsconf_SuperUser(tdir
, acid
, caller
))
552 return VOLSERBAD_ACCESS
;
555 Log("%s on %s is executing CreateVolume '%s'\n", caller
,
556 callerAddress(acid
, buffer
), aname
);
558 if ((error
= ConvertPartition(apart
, ppath
, sizeof(ppath
))))
559 return error
; /*a standard unix error */
560 if (atype
!= readwriteVolume
&& atype
!= readonlyVolume
561 && atype
!= backupVolume
)
563 if ((volumeID
= *avolid
) == 0) {
565 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname
);
569 if ((aparent
== volumeID
) && (atype
== readwriteVolume
)) {
574 tt
= NewTrans(volumeID
, apart
);
576 Log("1 createvolume: failed to create trans\n");
577 return VOLSERVOLBUSY
; /* volume already busy! */
579 vp
= VCreateVolume(&error
, ppath
, volumeID
, aparent
);
581 #ifdef AFS_DEMAND_ATTACH_FS
582 if (error
!= VVOLEXISTS
&& error
!= EXDEV
) {
583 SalvageUnknownVolume(volumeID
, ppath
);
586 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error
);
591 V_uniquifier(vp
) = 1;
592 V_updateDate(vp
) = V_creationDate(vp
) = V_copyDate(vp
);
593 V_inService(vp
) = V_blessed(vp
) = 1;
595 AssignVolumeName(&V_disk(vp
), aname
, 0);
597 error
= ViceCreateRoot(vp
);
599 Log("1 Volser: CreateVolume: Unable to create volume root dir; "
600 "error code %u\n", (unsigned)error
);
602 V_needsSalvaged(vp
) = 1;
603 VDetachVolume(&junk
, vp
);
607 V_destroyMe(vp
) = DESTROY_ME
;
609 V_maxquota(vp
) = 5000; /* set a quota of 5000 at init time */
610 VUpdateVolume(&error
, vp
);
612 Log("1 Volser: create UpdateVolume failed, code %d\n", error
);
615 VDetachVolume(&junk
, vp
); /* rather return the real error code */
621 TSetRxCall_r(tt
, acid
, "CreateVolume");
622 VTRANS_OBJ_UNLOCK(tt
);
623 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID
, aname
);
626 return VOLSERTRELE_ERROR
;
630 /* delete the volume associated with this transaction */
632 SAFSVolDeleteVolume(struct rx_call
*acid
, afs_int32 atrans
)
636 code
= VolDeleteVolume(acid
, atrans
);
637 osi_auditU(acid
, VS_DelVolEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
642 VolDeleteVolume(struct rx_call
*acid
, afs_int32 atrans
)
644 struct volser_trans
*tt
;
646 char caller
[MAXKTCNAMELEN
];
648 if (!afsconf_SuperUser(tdir
, acid
, caller
))
649 return VOLSERBAD_ACCESS
;
650 tt
= FindTrans(atrans
);
653 if (tt
->vflags
& VTDeleted
) {
654 Log("1 Volser: Delete: volume %" AFS_VOLID_FMT
" already deleted \n",
655 afs_printable_VolumeId_lu(tt
->volid
));
661 Log("%s on %s is executing Delete Volume %" AFS_VOLID_FMT
"\n", caller
,
662 callerAddress(acid
, buffer
), afs_printable_VolumeId_lu(tt
->volid
));
664 TSetRxCall(tt
, acid
, "DeleteVolume");
665 VPurgeVolume(&error
, tt
->volume
); /* don't check error code, it is not set! */
666 V_destroyMe(tt
->volume
) = DESTROY_ME
;
667 if (tt
->volume
->needsPutBack
) {
668 tt
->volume
->needsPutBack
= VOL_PUTBACK_DELETE
; /* so endtrans does the right fssync opcode */
671 tt
->vflags
|= VTDeleted
; /* so we know not to do anything else to it */
673 VTRANS_OBJ_UNLOCK(tt
);
675 return VOLSERTRELE_ERROR
;
677 Log("1 Volser: Delete: volume %" AFS_VOLID_FMT
" deleted \n",
678 afs_printable_VolumeId_lu(tt
->volid
));
679 return 0; /* vpurgevolume doesn't set an error code */
682 /* make a clone of the volume associated with atrans, possibly giving it a new
683 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
684 * for the clone's id). The new clone is given the name newName. Finally,
685 * due to efficiency considerations, if purgeId is non-zero, we purge that
686 * volume when doing the clone operation. This may be useful when making
687 * new backup volumes, for instance since the net result of a clone and a
688 * purge generally leaves many inode ref counts the same, while doing them
689 * separately would result in far more iincs and idecs being peformed
690 * (and they are slow operations).
692 /* for efficiency reasons, sometimes faster to piggyback a purge here */
694 SAFSVolClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId purgeId
,
695 afs_int32 newType
, char *newName
, VolumeId
*newNumber
)
698 code
= VolClone(acid
, atrans
, purgeId
, newType
, newName
, newNumber
);
699 osi_auditU(acid
, VS_CloneEvent
, code
, AUD_LONG
, atrans
, AUD_LONG
, purgeId
,
700 AUD_STR
, newName
, AUD_LONG
, newType
, AUD_LONG
, *newNumber
,
706 VolClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId purgeId
,
707 afs_int32 newType
, char *newName
, VolumeId
*newNumber
)
710 struct Volume
*originalvp
, *purgevp
, *newvp
;
712 struct volser_trans
*tt
, *ttc
;
713 char caller
[MAXKTCNAMELEN
];
714 #ifdef AFS_DEMAND_ATTACH_FS
715 struct Volume
*salv_vp
= NULL
;
718 if (strlen(newName
) > 31)
719 return VOLSERBADNAME
;
720 if (!afsconf_SuperUser(tdir
, acid
, caller
))
721 return VOLSERBAD_ACCESS
; /*not a super user */
724 Log("%s on %s is executing Clone Volume new name=%s\n", caller
,
725 callerAddress(acid
, buffer
), newName
);
728 purgevp
= (Volume
*) 0;
729 newvp
= (Volume
*) 0;
730 tt
= ttc
= (struct volser_trans
*)0;
732 if (!newNumber
|| !*newNumber
) {
733 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
738 tt
= FindTrans(atrans
);
741 if (tt
->vflags
& VTDeleted
) {
742 Log("1 Volser: Clone: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
746 ttc
= NewTrans(newId
, tt
->partition
);
747 if (!ttc
) { /* someone is messing with the clone already */
749 return VOLSERVOLBUSY
;
751 TSetRxCall(tt
, acid
, "Clone");
755 purgevp
= VAttachVolume_retry(&error
, purgeId
, V_VOLUPD
);
757 Log("1 Volser: Clone: Could not attach 'purge' volume %" AFS_VOLID_FMT
"; clone aborted\n", afs_printable_VolumeId_lu(purgeId
));
763 originalvp
= tt
->volume
;
764 if ((V_destroyMe(originalvp
) == DESTROY_ME
) || !V_inService(originalvp
)) {
765 Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT
" is offline and cannot be cloned\n",
766 afs_printable_VolumeId_lu(V_id(originalvp
)));
771 if (originalvp
->device
!= purgevp
->device
) {
772 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
));
776 if (V_type(purgevp
) != readonlyVolume
) {
777 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
781 if (V_parentId(originalvp
) != V_parentId(purgevp
)) {
782 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
));
789 #ifdef AFS_DEMAND_ATTACH_FS
790 salv_vp
= originalvp
;
793 if (purgeId
== newId
) {
797 VCreateVolume(&error
, originalvp
->partition
->name
, newId
,
798 V_parentId(originalvp
));
800 Log("1 Volser: Clone: Couldn't create new volume %" AFS_VOLID_FMT
" for parent %" AFS_VOLID_FMT
"; clone aborted\n",
801 afs_printable_VolumeId_lu(newId
), afs_printable_VolumeId_lu(V_parentId(originalvp
)));
802 newvp
= (Volume
*) 0;
806 if (newType
== readonlyVolume
)
807 V_cloneId(originalvp
) = newId
;
808 Log("1 Volser: Clone: Cloning volume %" AFS_VOLID_FMT
" to new volume %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(tt
->volid
),
809 afs_printable_VolumeId_lu(newId
));
811 Log("1 Volser: Clone: Purging old read only volume %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(purgeId
));
812 CloneVolume(&error
, originalvp
, newvp
, purgevp
);
813 purgevp
= NULL
; /* clone releases it, maybe even if error */
815 Log("1 Volser: Clone: clone operation failed with code %u\n", error
);
819 if (newType
== readonlyVolume
) {
820 V_type(newvp
) = readonlyVolume
;
821 } else if (newType
== backupVolume
) {
822 V_type(newvp
) = backupVolume
;
823 V_backupId(originalvp
) = newId
;
825 strcpy(V_name(newvp
), newName
);
826 V_creationDate(newvp
) = V_copyDate(newvp
);
827 ClearVolumeStats(&V_disk(newvp
));
828 V_destroyMe(newvp
) = DESTROY_ME
;
829 V_inService(newvp
) = 0;
830 if (newType
== backupVolume
) {
831 V_backupDate(originalvp
) = V_copyDate(newvp
);
832 V_backupDate(newvp
) = V_copyDate(newvp
);
835 VUpdateVolume(&error
, newvp
);
837 Log("1 Volser: Clone: VUpdate failed code %u\n", error
);
841 VDetachVolume(&error
, newvp
); /* allow file server to get it's hands on it */
843 VUpdateVolume(&error
, originalvp
);
845 Log("1 Volser: Clone: original update %u\n", error
);
850 #ifdef AFS_DEMAND_ATTACH_FS
854 /* Clients could have callbacks to the clone ID */
855 FSYNC_VolOp(newId
, NULL
, FSYNC_VOL_BREAKCBKS
, 0l, NULL
);
858 tt
= (struct volser_trans
*)0;
859 error
= VOLSERTRELE_ERROR
;
867 VDetachVolume(&code
, purgevp
);
869 VDetachVolume(&code
, newvp
);
876 #ifdef AFS_DEMAND_ATTACH_FS
877 if (salv_vp
&& error
!= VVOLEXISTS
&& error
!= EXDEV
) {
878 V_needsSalvaged(salv_vp
) = 1;
880 #endif /* AFS_DEMAND_ATTACH_FS */
884 /* reclone this volume into the specified id */
886 SAFSVolReClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId cloneId
)
890 code
= VolReClone(acid
, atrans
, cloneId
);
891 osi_auditU(acid
, VS_ReCloneEvent
, code
, AUD_LONG
, atrans
, AUD_LONG
,
897 VolReClone(struct rx_call
*acid
, afs_int32 atrans
, VolumeId cloneId
)
899 struct Volume
*originalvp
, *clonevp
;
902 struct volser_trans
*tt
, *ttc
;
903 char caller
[MAXKTCNAMELEN
];
904 VolumeDiskData saved_header
;
906 /*not a super user */
907 if (!afsconf_SuperUser(tdir
, acid
, caller
))
908 return VOLSERBAD_ACCESS
;
911 Log("%s on %s is executing Reclone Volume %" AFS_VOLID_FMT
"\n", caller
,
912 callerAddress(acid
, buffer
), afs_printable_VolumeId_lu(cloneId
));
915 clonevp
= originalvp
= (Volume
*) 0;
917 tt
= FindTrans(atrans
);
920 if (tt
->vflags
& VTDeleted
) {
921 Log("1 Volser: VolReClone: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
925 ttc
= NewTrans(cloneId
, tt
->partition
);
926 if (!ttc
) { /* someone is messing with the clone already */
928 return VOLSERVOLBUSY
;
930 TSetRxCall(tt
, acid
, "ReClone");
932 originalvp
= tt
->volume
;
933 if ((V_destroyMe(originalvp
) == DESTROY_ME
) || !V_inService(originalvp
)) {
934 Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT
" is offline and cannot be cloned\n",
935 afs_printable_VolumeId_lu(V_id(originalvp
)));
940 clonevp
= VAttachVolume_retry(&error
, cloneId
, V_VOLUPD
);
942 Log("1 Volser: can't attach clone %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(cloneId
));
946 newType
= V_type(clonevp
); /* type of the new volume */
948 if (originalvp
->device
!= clonevp
->device
) {
949 Log("1 Volser: Clone: Volumes %" AFS_VOLID_FMT
" and %" AFS_VOLID_FMT
" are on different devices\n",
950 afs_printable_VolumeId_lu(tt
->volid
), afs_printable_VolumeId_lu(cloneId
));
954 if (V_parentId(originalvp
) != V_parentId(clonevp
)) {
955 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
));
960 if (DoPreserveVolumeStats
) {
961 CopyVolumeStats(&V_disk(clonevp
), &saved_header
);
965 Log("1 Volser: Clone: Recloning volume %" AFS_VOLID_FMT
" to volume %" AFS_VOLID_FMT
"\n", afs_printable_VolumeId_lu(tt
->volid
),
966 afs_printable_VolumeId_lu(cloneId
));
967 CloneVolume(&error
, originalvp
, clonevp
, clonevp
);
969 Log("1 Volser: Clone: reclone operation failed with code %d\n",
975 /* fix up volume name and type, CloneVolume just propagated RW's */
976 if (newType
== readonlyVolume
) {
977 AssignVolumeName(&V_disk(clonevp
), V_name(originalvp
), ".readonly");
978 V_type(clonevp
) = readonlyVolume
;
979 } else if (newType
== backupVolume
) {
980 AssignVolumeName(&V_disk(clonevp
), V_name(originalvp
), ".backup");
981 V_type(clonevp
) = backupVolume
;
982 V_backupId(originalvp
) = cloneId
;
984 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
986 /* update the creationDate, since this represents the last cloning date
987 * for ROs. But do not update copyDate; let it stay so we can identify
988 * when the clone was first created. */
989 V_creationDate(clonevp
) = time(0);
990 if (DoPreserveVolumeStats
) {
991 CopyVolumeStats(&saved_header
, &V_disk(clonevp
));
993 ClearVolumeStats(&V_disk(clonevp
));
995 V_destroyMe(clonevp
) = 0;
996 V_inService(clonevp
) = 0;
997 if (newType
== backupVolume
) {
998 V_backupDate(originalvp
) = V_creationDate(clonevp
);
999 V_backupDate(clonevp
) = V_creationDate(clonevp
);
1001 V_inUse(clonevp
) = 0;
1002 VUpdateVolume(&error
, clonevp
);
1004 Log("1 Volser: Clone: VUpdate failed code %u\n", error
);
1008 /* VUpdateVolume succeeded. Mark it in service so there's no window
1009 * between FSYNC_VOL_ON and VolSetFlags where it's offline with no
1010 * specialStatus; this is a reclone and this volume started online
1012 V_inService(clonevp
) = 1;
1013 VDetachVolume(&error
, clonevp
); /* allow file server to get it's hands on it */
1015 VUpdateVolume(&error
, originalvp
);
1017 Log("1 Volser: Clone: original update %u\n", error
);
1023 tt
= (struct volser_trans
*)0;
1024 error
= VOLSERTRELE_ERROR
;
1028 DeleteTrans(ttc
, 1);
1031 struct DiskPartition64
*tpartp
= originalvp
->partition
;
1032 FSYNC_VolOp(cloneId
, tpartp
->name
, FSYNC_VOL_BREAKCBKS
, 0, NULL
);
1038 VDetachVolume(&code
, clonevp
);
1044 DeleteTrans(ttc
, 1);
1048 /* create a new transaction, associated with volume and partition. Type of
1049 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
1050 * See volser.h for definition of iflags (the constants are named IT*).
1053 SAFSVolTransCreate(struct rx_call
*acid
, VolumeId volume
, afs_int32 partition
,
1054 afs_int32 iflags
, afs_int32
*ttid
)
1058 code
= VolTransCreate(acid
, volume
, partition
, iflags
, ttid
);
1059 osi_auditU(acid
, VS_TransCrEvent
, code
, AUD_LONG
, *ttid
, AUD_LONG
, volume
,
1065 VolTransCreate(struct rx_call
*acid
, VolumeId volume
, afs_int32 partition
,
1066 afs_int32 iflags
, afs_int32
*ttid
)
1068 struct volser_trans
*tt
;
1073 char caller
[MAXKTCNAMELEN
];
1075 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1076 return VOLSERBAD_ACCESS
; /*not a super user */
1077 if (iflags
& ITCreate
)
1079 else if (iflags
& ITBusy
)
1081 else if (iflags
& ITReadOnly
)
1083 else if (iflags
& ITOffline
)
1086 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
1091 tt
= NewTrans(volume
, partition
);
1093 /* can't create a transaction? put the volume back */
1094 Log("1 transcreate: can't create transaction\n");
1095 return VOLSERVOLBUSY
;
1097 tv
= XAttachVolume(&error
, volume
, partition
, mode
);
1101 VDetachVolume(&code
, tv
);
1105 VTRANS_OBJ_LOCK(tt
);
1108 tt
->iflags
= iflags
;
1110 TSetRxCall_r(tt
, NULL
, "TransCreate");
1111 VTRANS_OBJ_UNLOCK(tt
);
1113 return VOLSERTRELE_ERROR
;
1118 /* using aindex as a 0-based index, return the aindex'th volume on this server
1119 * Both the volume number and partition number (one-based) are returned.
1122 SAFSVolGetNthVolume(struct rx_call
*acid
, afs_int32 aindex
, VolumeId
*avolume
,
1127 code
= VolGetNthVolume(acid
, aindex
, avolume
, apart
);
1128 osi_auditU(acid
, VS_GetNVolEvent
, code
, AUD_LONG
, *avolume
, AUD_END
);
1133 VolGetNthVolume(struct rx_call
*acid
, afs_int32 aindex
, afs_uint32
*avolume
,
1136 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1137 return VOLSERBAD_ACCESS
;
1139 Log("1 Volser: GetNthVolume: Not yet implemented\n");
1143 /* return the volume flags (VT* constants in volser.h) associated with this
1147 SAFSVolGetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32
*aflags
)
1151 code
= VolGetFlags(acid
, atid
, aflags
);
1152 osi_auditU(acid
, VS_GetFlgsEvent
, code
, AUD_LONG
, atid
, AUD_END
);
1157 VolGetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32
*aflags
)
1159 struct volser_trans
*tt
;
1161 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1162 return VOLSERBAD_ACCESS
;
1164 tt
= FindTrans(atid
);
1167 if (tt
->vflags
& VTDeleted
) {
1168 Log("1 Volser: VolGetFlags: volume %" AFS_VOLID_FMT
" has been deleted \n",
1169 afs_printable_VolumeId_lu(tt
->volid
));
1173 TSetRxCall(tt
, acid
, "GetFlags");
1174 *aflags
= tt
->vflags
;
1177 return VOLSERTRELE_ERROR
;
1182 /* Change the volume flags (VT* constants in volser.h) associated with this
1183 * transaction. Effects take place immediately on volume, although volume
1184 * remains attached as usual by the transaction.
1187 SAFSVolSetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32 aflags
)
1191 code
= VolSetFlags(acid
, atid
, aflags
);
1192 osi_auditU(acid
, VS_SetFlgsEvent
, code
, AUD_LONG
, atid
, AUD_LONG
, aflags
,
1198 VolSetFlags(struct rx_call
*acid
, afs_int32 atid
, afs_int32 aflags
)
1200 struct volser_trans
*tt
;
1203 char caller
[MAXKTCNAMELEN
];
1205 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1206 return VOLSERBAD_ACCESS
; /*not a super user */
1207 /* find the trans */
1208 tt
= FindTrans(atid
);
1211 if (tt
->vflags
& VTDeleted
) {
1212 Log("1 Volser: VolSetFlags: volume %" AFS_VOLID_FMT
" has been deleted \n",
1213 afs_printable_VolumeId_lu(tt
->volid
));
1217 TSetRxCall(tt
, acid
, "SetFlags");
1218 vp
= tt
->volume
; /* pull volume out of transaction */
1220 /* check if we're allowed to make any updates */
1221 if (tt
->iflags
& ITReadOnly
) {
1226 /* handle delete-on-salvage flag */
1227 if (aflags
& VTDeleteOnSalvage
) {
1228 V_destroyMe(tt
->volume
) = DESTROY_ME
;
1230 V_destroyMe(tt
->volume
) = 0;
1233 if (aflags
& VTOutOfService
) {
1234 V_inService(vp
) = 0;
1236 V_inService(vp
) = 1;
1238 VUpdateVolume(&error
, vp
);
1239 VTRANS_OBJ_LOCK(tt
);
1240 tt
->vflags
= aflags
;
1242 VTRANS_OBJ_UNLOCK(tt
);
1243 if (TRELE(tt
) && !error
)
1244 return VOLSERTRELE_ERROR
;
1249 /* dumpS the volume associated with a particular transaction from a particular
1250 * date. Send the dump to a different transaction (destTrans) on the server
1251 * specified by the destServer structure.
1254 SAFSVolForward(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1255 struct destServer
*destination
, afs_int32 destTrans
,
1256 struct restoreCookie
*cookie
)
1261 VolForward(acid
, fromTrans
, fromDate
, destination
, destTrans
, cookie
);
1262 osi_auditU(acid
, VS_ForwardEvent
, code
, AUD_LONG
, fromTrans
, AUD_HOST
,
1263 htonl(destination
->destHost
), AUD_LONG
, destTrans
, AUD_END
);
1267 static_inline afs_int32
1268 MakeClient(struct rx_call
*acid
, struct rx_securityClass
**securityObject
,
1269 afs_int32
*securityIndex
)
1271 rxkad_level enc_level
= rxkad_clear
;
1280 rxkad_GetServerInfo(rx_ConnectionOf(acid
), &enc_level
, 0, 0, 0, 0, 0);
1281 docrypt
= (enc_level
== rxkad_crypt
? 1 : 0);
1287 opr_Assert(0 && "doCrypt corrupt?");
1290 code
= afsconf_ClientAuthSecure(tdir
, securityObject
, securityIndex
);
1292 code
= afsconf_ClientAuth(tdir
, securityObject
, securityIndex
);
1297 VolForward(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1298 struct destServer
*destination
, afs_int32 destTrans
,
1299 struct restoreCookie
*cookie
)
1301 struct volser_trans
*tt
;
1303 struct rx_connection
*tcon
;
1304 struct rx_call
*tcall
;
1306 struct rx_securityClass
*securityObject
;
1307 afs_int32 securityIndex
;
1308 char caller
[MAXKTCNAMELEN
];
1310 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1311 return VOLSERBAD_ACCESS
; /*not a super user */
1313 /* find the local transaction */
1314 tt
= FindTrans(fromTrans
);
1317 if (tt
->vflags
& VTDeleted
) {
1318 Log("1 Volser: VolForward: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1323 TSetRxCall(tt
, NULL
, "Forward");
1325 /* get auth info for the this connection (uses afs from ticket file) */
1326 code
= MakeClient(acid
, &securityObject
, &securityIndex
);
1332 /* make an rpc connection to the other server */
1334 rx_NewConnection(htonl(destination
->destHost
),
1335 htons(destination
->destPort
), VOLSERVICE_ID
,
1336 securityObject
, securityIndex
);
1338 RXS_Close(securityObject
); /* will be freed after connection destroyed */
1345 tcall
= rx_NewCall(tcon
);
1346 TSetRxCall(tt
, tcall
, "Forward");
1347 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1348 code
= StartAFSVolRestore(tcall
, destTrans
, (fromDate
? 1 : 0), cookie
);
1353 /* these next calls implictly call rx_Write when writing out data */
1354 code
= DumpVolume(tcall
, vp
, fromDate
, 0); /* last field = don't dump all dirs */
1357 EndAFSVolRestore(tcall
); /* probably doesn't do much */
1359 code
= rx_EndCall(tcall
, 0);
1360 rx_DestroyConnection(tcon
); /* done with the connection */
1365 return VOLSERTRELE_ERROR
;
1371 (void)rx_EndCall(tcall
, 0);
1372 rx_DestroyConnection(tcon
);
1381 /* Start a dump and send it to multiple places simultaneously.
1382 * If this returns an error (eg, return ENOENT), it means that
1383 * none of the releases worked. If this returns 0, that means
1384 * that one or more of the releases worked, and the caller has
1385 * to examine the results array to see which one(s).
1386 * This will only do EITHER incremental or full, not both, so it's
1387 * the caller's responsibility to be sure that all the destinations
1388 * need just an incremental (and from the same time), if that's
1392 SAFSVolForwardMultiple(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32
1393 fromDate
, manyDests
*destinations
, afs_int32 spare
,
1394 struct restoreCookie
*cookie
, manyResults
*results
)
1396 afs_int32 securityIndex
;
1397 struct rx_securityClass
*securityObject
;
1398 char caller
[MAXKTCNAMELEN
];
1399 struct volser_trans
*tt
;
1400 afs_int32 ec
, code
, *codes
;
1401 struct rx_connection
**tcons
;
1402 struct rx_call
**tcalls
;
1404 int i
, is_incremental
;
1407 memset(results
, 0, sizeof(manyResults
));
1408 i
= results
->manyResults_len
= destinations
->manyDests_len
;
1409 results
->manyResults_val
= codes
= malloc(i
* sizeof(afs_int32
));
1411 if (!results
|| !results
->manyResults_val
)
1414 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1415 return VOLSERBAD_ACCESS
; /*not a super user */
1416 tt
= FindTrans(fromTrans
);
1419 if (tt
->vflags
& VTDeleted
) {
1420 Log("1 Volser: VolForward: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1425 TSetRxCall(tt
, NULL
, "ForwardMulti");
1427 /* (fromDate == 0) ==> full dump */
1428 is_incremental
= (fromDate
? 1 : 0);
1430 tcons
= malloc(i
* sizeof(struct rx_connection
*));
1434 tcalls
= malloc(i
* sizeof(struct rx_call
*));
1440 /* get auth info for this connection (uses afs from ticket file) */
1441 code
= MakeClient(acid
, &securityObject
, &securityIndex
);
1443 goto fail
; /* in order to audit each failure */
1446 /* make connections to all the other servers */
1447 for (i
= 0; i
< destinations
->manyDests_len
; i
++) {
1448 struct replica
*dest
= &(destinations
->manyDests_val
[i
]);
1450 rx_NewConnection(htonl(dest
->server
.destHost
),
1451 htons(dest
->server
.destPort
), VOLSERVICE_ID
,
1452 securityObject
, securityIndex
);
1454 codes
[i
] = ENOTCONN
;
1456 if (!(tcalls
[i
] = rx_NewCall(tcons
[i
])))
1457 codes
[i
] = ENOTCONN
;
1460 StartAFSVolRestore(tcalls
[i
], dest
->trans
, is_incremental
,
1463 (void)rx_EndCall(tcalls
[i
], 0);
1465 rx_DestroyConnection(tcons
[i
]);
1472 /* Security object will be freed when all connections destroyed */
1473 RXS_Close(securityObject
);
1475 /* these next calls implictly call rx_Write when writing out data */
1476 code
= DumpVolMulti(tcalls
, i
, vp
, fromDate
, 0, codes
);
1480 for (i
--; i
>= 0; i
--) {
1481 struct replica
*dest
= &(destinations
->manyDests_val
[i
]);
1483 if (!code
&& tcalls
[i
] && !codes
[i
]) {
1484 EndAFSVolRestore(tcalls
[i
]);
1487 ec
= rx_EndCall(tcalls
[i
], 0);
1492 rx_DestroyConnection(tcons
[i
]); /* done with the connection */
1495 osi_auditU(acid
, VS_ForwardEvent
, (code
? code
: codes
[i
]), AUD_LONG
,
1496 fromTrans
, AUD_HOST
, htonl(dest
->server
.destHost
), AUD_LONG
,
1497 dest
->trans
, AUD_END
);
1504 if (TRELE(tt
) && !code
) /* return the first code if it's set */
1505 return VOLSERTRELE_ERROR
;
1512 SAFSVolDump(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
)
1516 code
= VolDump(acid
, fromTrans
, fromDate
, 0);
1517 osi_auditU(acid
, VS_DumpEvent
, code
, AUD_LONG
, fromTrans
, AUD_END
);
1522 SAFSVolDumpV2(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1527 code
= VolDump(acid
, fromTrans
, fromDate
, flags
);
1528 osi_auditU(acid
, VS_DumpEvent
, code
, AUD_LONG
, fromTrans
, AUD_END
);
1533 VolDump(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
1537 struct volser_trans
*tt
;
1538 char caller
[MAXKTCNAMELEN
];
1540 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1541 return VOLSERBAD_ACCESS
; /*not a super user */
1542 tt
= FindTrans(fromTrans
);
1545 if (tt
->vflags
& VTDeleted
) {
1546 Log("1 Volser: VolDump: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1550 TSetRxCall(tt
, acid
, "Dump");
1551 code
= DumpVolume(acid
, tt
->volume
, fromDate
, (flags
& VOLDUMPV2_OMITDIRS
)
1552 ? 0 : 1); /* squirt out the volume's data, too */
1561 return VOLSERTRELE_ERROR
;
1567 * Ha! No more helper process!
1570 SAFSVolRestore(struct rx_call
*acid
, afs_int32 atrans
, afs_int32 aflags
,
1571 struct restoreCookie
*cookie
)
1575 code
= VolRestore(acid
, atrans
, aflags
, cookie
);
1576 osi_auditU(acid
, VS_RestoreEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1581 VolRestore(struct rx_call
*acid
, afs_int32 atrans
, afs_int32 aflags
,
1582 struct restoreCookie
*cookie
)
1584 struct volser_trans
*tt
;
1585 afs_int32 code
, tcode
;
1586 char caller
[MAXKTCNAMELEN
];
1588 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1589 return VOLSERBAD_ACCESS
; /*not a super user */
1590 tt
= FindTrans(atrans
);
1593 if (tt
->vflags
& VTDeleted
) {
1594 Log("1 Volser: VolRestore: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1600 Log("%s on %s is executing Restore %" AFS_VOLID_FMT
"\n", caller
,
1601 callerAddress(acid
, buffer
), afs_printable_VolumeId_lu(tt
->volid
));
1603 TSetRxCall(tt
, acid
, "Restore");
1605 DFlushVolume(V_parentId(tt
->volume
)); /* Ensure dir buffers get dropped */
1607 code
= RestoreVolume(acid
, tt
->volume
, (aflags
& 1), cookie
); /* last is incrementalp */
1608 FSYNC_VolOp(tt
->volid
, NULL
, FSYNC_VOL_BREAKCBKS
, 0l, NULL
);
1612 return (code
? code
: tcode
);
1615 /* end a transaction, returning the transaction's final error code in rcode */
1617 SAFSVolEndTrans(struct rx_call
*acid
, afs_int32 destTrans
, afs_int32
*rcode
)
1621 code
= VolEndTrans(acid
, destTrans
, rcode
);
1622 osi_auditU(acid
, VS_EndTrnEvent
, code
, AUD_LONG
, destTrans
, AUD_END
);
1627 VolEndTrans(struct rx_call
*acid
, afs_int32 destTrans
, afs_int32
*rcode
)
1629 struct volser_trans
*tt
;
1630 char caller
[MAXKTCNAMELEN
];
1632 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1633 return VOLSERBAD_ACCESS
; /*not a super user */
1634 tt
= FindTrans(destTrans
);
1638 *rcode
= tt
->returnCode
;
1639 DeleteTrans(tt
, 1); /* this does an implicit TRELE */
1645 SAFSVolSetForwarding(struct rx_call
*acid
, afs_int32 atid
, afs_int32 anewsite
)
1649 code
= VolSetForwarding(acid
, atid
, anewsite
);
1650 osi_auditU(acid
, VS_SetForwEvent
, code
, AUD_LONG
, atid
, AUD_HOST
,
1651 htonl(anewsite
), AUD_END
);
1656 VolSetForwarding(struct rx_call
*acid
, afs_int32 atid
, afs_int32 anewsite
)
1658 struct volser_trans
*tt
;
1659 char caller
[MAXKTCNAMELEN
];
1662 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1663 return VOLSERBAD_ACCESS
; /*not a super user */
1664 tt
= FindTrans(atid
);
1667 if (tt
->vflags
& VTDeleted
) {
1668 Log("1 Volser: VolSetForwarding: volume %" AFS_VOLID_FMT
" has been deleted \n",
1669 afs_printable_VolumeId_lu(tt
->volid
));
1673 TSetRxCall(tt
, acid
, "SetForwarding");
1674 if (volutil_PartitionName2_r(tt
->partition
, partName
, sizeof(partName
)) != 0) {
1677 FSYNC_VolOp(tt
->volid
, partName
, FSYNC_VOL_MOVE
, anewsite
, NULL
);
1680 return VOLSERTRELE_ERROR
;
1686 SAFSVolGetStatus(struct rx_call
*acid
, afs_int32 atrans
,
1687 struct volser_status
*astatus
)
1691 code
= VolGetStatus(acid
, atrans
, astatus
);
1692 osi_auditU(acid
, VS_GetStatEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1697 VolGetStatus(struct rx_call
*acid
, afs_int32 atrans
,
1698 struct volser_status
*astatus
)
1701 struct VolumeDiskData
*td
;
1702 struct volser_trans
*tt
;
1704 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1705 return VOLSERBAD_ACCESS
;
1707 tt
= FindTrans(atrans
);
1710 if (tt
->vflags
& VTDeleted
) {
1711 Log("1 Volser: VolGetStatus: volume %" AFS_VOLID_FMT
" has been deleted \n",
1712 afs_printable_VolumeId_lu(tt
->volid
));
1716 TSetRxCall(tt
, acid
, "GetStatus");
1725 astatus
->volID
= td
->id
;
1726 astatus
->nextUnique
= td
->uniquifier
;
1727 astatus
->type
= td
->type
;
1728 astatus
->parentID
= td
->parentId
;
1729 astatus
->cloneID
= td
->cloneId
;
1730 astatus
->backupID
= td
->backupId
;
1731 astatus
->restoredFromID
= td
->restoredFromId
;
1732 astatus
->maxQuota
= td
->maxquota
;
1733 astatus
->minQuota
= td
->minquota
;
1734 astatus
->owner
= td
->owner
;
1735 astatus
->creationDate
= td
->creationDate
;
1736 astatus
->accessDate
= td
->accessDate
;
1737 astatus
->updateDate
= td
->updateDate
;
1738 astatus
->expirationDate
= td
->expirationDate
;
1739 astatus
->backupDate
= td
->backupDate
;
1740 astatus
->copyDate
= td
->copyDate
;
1743 return VOLSERTRELE_ERROR
;
1749 SAFSVolSetInfo(struct rx_call
*acid
, afs_int32 atrans
,
1750 struct volintInfo
*astatus
)
1754 code
= VolSetInfo(acid
, atrans
, astatus
);
1755 osi_auditU(acid
, VS_SetInfoEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1760 VolSetInfo(struct rx_call
*acid
, afs_int32 atrans
,
1761 struct volintInfo
*astatus
)
1764 struct VolumeDiskData
*td
;
1765 struct volser_trans
*tt
;
1766 char caller
[MAXKTCNAMELEN
];
1769 if (!afsconf_SuperUser(tdir
, acid
, caller
))
1770 return VOLSERBAD_ACCESS
; /*not a super user */
1771 tt
= FindTrans(atrans
);
1774 if (tt
->vflags
& VTDeleted
) {
1775 Log("1 Volser: VolSetInfo: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1779 TSetRxCall(tt
, acid
, "SetStatus");
1789 * Add more fields as necessary
1791 if (astatus
->maxquota
!= -1)
1792 td
->maxquota
= astatus
->maxquota
;
1793 if (astatus
->dayUse
!= -1)
1794 td
->dayUse
= astatus
->dayUse
;
1795 if (astatus
->creationDate
!= -1)
1796 td
->creationDate
= astatus
->creationDate
;
1797 if (astatus
->updateDate
!= -1)
1798 td
->updateDate
= astatus
->updateDate
;
1799 if (astatus
->spare2
!= -1)
1800 td
->volUpdateCounter
= (unsigned int)astatus
->spare2
;
1801 VUpdateVolume(&error
, tv
);
1804 return VOLSERTRELE_ERROR
;
1810 SAFSVolGetName(struct rx_call
*acid
, afs_int32 atrans
, char **aname
)
1814 code
= VolGetName(acid
, atrans
, aname
);
1815 osi_auditU(acid
, VS_GetNameEvent
, code
, AUD_LONG
, atrans
, AUD_END
);
1820 VolGetName(struct rx_call
*acid
, afs_int32 atrans
, char **aname
)
1823 struct VolumeDiskData
*td
;
1824 struct volser_trans
*tt
;
1827 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1828 return VOLSERBAD_ACCESS
;
1830 /* We need to at least fill it in */
1834 tt
= FindTrans(atrans
);
1837 if (tt
->vflags
& VTDeleted
) {
1838 Log("1 Volser: VolGetName: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
1842 TSetRxCall(tt
, acid
, "GetName");
1851 len
= strlen(td
->name
) + 1; /* don't forget the null */
1857 *aname
= realloc(*aname
, len
);
1858 strcpy(*aname
, td
->name
);
1861 return VOLSERTRELE_ERROR
;
1866 /*this is a handshake to indicate that the next call will be SAFSVolRestore
1869 SAFSVolSignalRestore(struct rx_call
*acid
, char volname
[], int volType
,
1870 VolumeId parentId
, VolumeId cloneId
)
1876 /*return a list of all partitions on the server. The non mounted
1877 *partitions are returned as -1 in the corresponding slot in partIds*/
1879 SAFSVolListPartitions(struct rx_call
*acid
, struct pIDs
*partIds
)
1883 code
= VolListPartitions(acid
, partIds
);
1884 osi_auditU(acid
, VS_ListParEvent
, code
, AUD_END
);
1889 VolListPartitions(struct rx_call
*acid
, struct pIDs
*partIds
)
1894 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1895 return VOLSERBAD_ACCESS
;
1897 strcpy(namehead
, "/vicep"); /*7 including null terminator */
1899 /* Just return attached partitions. */
1901 for (i
= 0; i
< 26; i
++) {
1902 namehead
[6] = i
+ 'a';
1903 partIds
->partIds
[i
] = VGetPartition(namehead
, 0) ? i
: -1;
1909 /*return a list of all partitions on the server. The non mounted
1910 *partitions are returned as -1 in the corresponding slot in partIds*/
1912 SAFSVolXListPartitions(struct rx_call
*acid
, struct partEntries
*pEntries
)
1916 code
= XVolListPartitions(acid
, pEntries
);
1917 osi_auditU(acid
, VS_ListParEvent
, code
, AUD_END
);
1922 XVolListPartitions(struct rx_call
*acid
, struct partEntries
*pEntries
)
1925 struct partList partList
;
1926 struct DiskPartition64
*dp
;
1929 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
1930 return VOLSERBAD_ACCESS
;
1932 strcpy(namehead
, "/vicep"); /*7 including null terminator */
1934 /* Only report attached partitions */
1935 for (i
= 0; i
< VOLMAXPARTS
; i
++) {
1936 #ifdef AFS_DEMAND_ATTACH_FS
1937 dp
= VGetPartitionById(i
, 0);
1940 namehead
[6] = i
+ 'a';
1946 namehead
[6] = 'a' + (k
/ 26);
1947 namehead
[7] = 'a' + (k
% 26);
1950 dp
= VGetPartition(namehead
, 0);
1953 partList
.partId
[j
++] = i
;
1956 pEntries
->partEntries_val
= malloc(j
* sizeof(int));
1957 if (!pEntries
->partEntries_val
)
1959 memcpy(pEntries
->partEntries_val
, partList
.partId
,
1961 pEntries
->partEntries_len
= j
;
1963 pEntries
->partEntries_val
= NULL
;
1964 pEntries
->partEntries_len
= 0;
1971 * Scan a directory for possible volume headers.
1972 * in: DIR *dirp -- a directory handle from opendir()
1973 * out: char *volname -- set to name of directory entry
1974 * afs_uint32 *volid -- set to volume ID parsed from name
1976 * true if volname and volid have been set to valid values
1977 * false if we got to the end of the directory
1980 GetNextVol(DIR *dirp
, char *volname
, VolumeId
*volid
)
1984 while ((dp
= readdir(dirp
)) != NULL
) {
1985 /* could be optimized on platforms with dp->d_namlen */
1986 if (dp
->d_name
[0] == 'V' && strlen(dp
->d_name
) == VHDRNAMELEN
1987 && strcmp(&(dp
->d_name
[VFORMATDIGITS
+ 1]), VHDREXT
) == 0) {
1988 *volid
= VolumeNumber(dp
->d_name
);
1989 strcpy(volname
, dp
->d_name
);
1997 * volint vol info structure type.
2000 VOLINT_INFO_TYPE_BASE
, /**< volintInfo type */
2001 VOLINT_INFO_TYPE_EXT
/**< volintXInfo type */
2002 } volint_info_type_t
;
2005 * handle to various on-wire vol info types.
2008 volint_info_type_t volinfo_type
;
2014 } volint_info_handle_t
;
2017 * store value to a field at the appropriate location in on-wire structure.
2019 #define VOLINT_INFO_STORE(handle, name, val) \
2021 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
2022 (handle)->volinfo_ptr.base->name = (val); \
2024 (handle)->volinfo_ptr.ext->name = (val); \
2029 * get pointer to appropriate offset of field in on-wire structure.
2031 #define VOLINT_INFO_PTR(handle, name) \
2032 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
2033 &((handle)->volinfo_ptr.base->name) : \
2034 &((handle)->volinfo_ptr.ext->name))
2037 * fill in appropriate type of on-wire volume metadata structure.
2039 * @param vp pointer to volume object
2040 * @param handle pointer to wire format handle object
2042 * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
2043 * @pre handle object must have a valid pointer and enumeration value
2045 * @note passing a NULL value for vp means that the fileserver doesn't
2046 * know about this particular volume, thus implying it is offline.
2048 * @return operation status
2053 FillVolInfo(Volume
* vp
, volint_info_handle_t
* handle
)
2055 unsigned int numStatBytes
, now
;
2056 struct VolumeDiskData
*hdr
= &(V_disk(vp
));
2058 /*read in the relevant info */
2059 strcpy((char *)VOLINT_INFO_PTR(handle
, name
), hdr
->name
);
2060 VOLINT_INFO_STORE(handle
, status
, VOK
); /*its ok */
2061 VOLINT_INFO_STORE(handle
, volid
, hdr
->id
);
2062 VOLINT_INFO_STORE(handle
, type
, hdr
->type
); /*if ro volume */
2063 VOLINT_INFO_STORE(handle
, cloneID
, hdr
->cloneId
); /*if rw volume */
2064 VOLINT_INFO_STORE(handle
, backupID
, hdr
->backupId
);
2065 VOLINT_INFO_STORE(handle
, parentID
, hdr
->parentId
);
2066 VOLINT_INFO_STORE(handle
, copyDate
, hdr
->copyDate
);
2067 VOLINT_INFO_STORE(handle
, size
, hdr
->diskused
);
2068 VOLINT_INFO_STORE(handle
, maxquota
, hdr
->maxquota
);
2069 VOLINT_INFO_STORE(handle
, filecount
, hdr
->filecount
);
2070 now
= FT_ApproxTime();
2071 if ((now
- hdr
->dayUseDate
) > OneDay
) {
2072 VOLINT_INFO_STORE(handle
, dayUse
, 0);
2074 VOLINT_INFO_STORE(handle
, dayUse
, hdr
->dayUse
);
2076 VOLINT_INFO_STORE(handle
, creationDate
, hdr
->creationDate
);
2077 VOLINT_INFO_STORE(handle
, accessDate
, hdr
->accessDate
);
2078 VOLINT_INFO_STORE(handle
, updateDate
, hdr
->updateDate
);
2079 VOLINT_INFO_STORE(handle
, backupDate
, hdr
->backupDate
);
2081 #ifdef AFS_DEMAND_ATTACH_FS
2083 * for DAFS, we "lie" about volume state --
2084 * instead of returning the raw state from the disk header,
2085 * we compute state based upon the fileserver's internal
2086 * in-core state enumeration value reported to us via fssync,
2087 * along with the blessed and inService flags from the header.
2088 * -- tkeiser 11/27/2007
2091 /* Conditions that offline status is based on:
2092 volume is unattached state
2093 volume state is in (one of several error states)
2094 volume not in service
2095 volume is not marked as blessed (not on hold)
2096 volume in salvage req. state
2097 volume needsSalvaged
2098 next op would set volume offline
2099 next op would not leave volume online (based on several conditions)
2102 (V_attachState(vp
) == VOL_STATE_UNATTACHED
) ||
2103 VIsErrorState(V_attachState(vp
)) ||
2106 (V_attachState(vp
) == VOL_STATE_SALVSYNC_REQ
) ||
2107 hdr
->needsSalvaged
||
2108 (vp
->pending_vol_op
&&
2109 (vp
->pending_vol_op
->com
.command
== FSYNC_VOL_OFF
||
2110 !VVolOpLeaveOnline_r(vp
, vp
->pending_vol_op
) )
2113 VOLINT_INFO_STORE(handle
, inUse
, 0);
2115 VOLINT_INFO_STORE(handle
, inUse
, 1);
2118 /* offline status based on program type, where != fileServer enum (1) is offline */
2119 if (hdr
->inUse
== fileServer
) {
2120 VOLINT_INFO_STORE(handle
, inUse
, 1);
2122 VOLINT_INFO_STORE(handle
, inUse
, 0);
2127 switch(handle
->volinfo_type
) {
2128 /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
2129 case VOLINT_INFO_TYPE_BASE
:
2131 #ifdef AFS_DEMAND_ATTACH_FS
2132 /* see comment above where we set inUse bit */
2133 if (hdr
->needsSalvaged
||
2134 (vp
&& VIsErrorState(V_attachState(vp
)))) {
2135 handle
->volinfo_ptr
.base
->needsSalvaged
= 1;
2137 handle
->volinfo_ptr
.base
->needsSalvaged
= 0;
2140 handle
->volinfo_ptr
.base
->needsSalvaged
= hdr
->needsSalvaged
;
2142 handle
->volinfo_ptr
.base
->destroyMe
= hdr
->destroyMe
;
2143 handle
->volinfo_ptr
.base
->spare0
= hdr
->minquota
;
2144 handle
->volinfo_ptr
.base
->spare1
=
2145 (long)hdr
->weekUse
[0] +
2146 (long)hdr
->weekUse
[1] +
2147 (long)hdr
->weekUse
[2] +
2148 (long)hdr
->weekUse
[3] +
2149 (long)hdr
->weekUse
[4] +
2150 (long)hdr
->weekUse
[5] +
2151 (long)hdr
->weekUse
[6];
2152 handle
->volinfo_ptr
.base
->flags
= 0;
2153 handle
->volinfo_ptr
.base
->spare2
= hdr
->volUpdateCounter
;
2154 handle
->volinfo_ptr
.base
->spare3
= 0;
2158 case VOLINT_INFO_TYPE_EXT
:
2160 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS
) +
2161 (4 * VOLINT_STATS_NUM_TIME_FIELDS
));
2164 * Copy out the stat fields in a single operation.
2166 if ((now
- hdr
->dayUseDate
) > OneDay
) {
2167 memset(&(handle
->volinfo_ptr
.ext
->stat_reads
[0]),
2170 memcpy((char *)&(handle
->volinfo_ptr
.ext
->stat_reads
[0]),
2171 (char *)&(hdr
->stat_reads
[0]),
2180 #ifdef AFS_DEMAND_ATTACH_FS
2183 * get struct Volume out of the fileserver.
2185 * @param[in] volumeId volumeId for which we want state information
2186 * @param[in] pname partition name string
2187 * @param[inout] vp pointer to pointer to Volume object which
2188 * will be populated (see note)
2190 * @return operation status
2192 * @retval non-zero failure
2194 * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
2199 GetVolObject(VolumeId volumeId
, char * pname
, Volume
** vp
)
2204 res
.hdr
.response_len
= sizeof(res
.hdr
);
2205 res
.payload
.buf
= *vp
;
2206 res
.payload
.len
= sizeof(Volume
);
2208 code
= FSYNC_VolOp(volumeId
,
2214 if (code
!= SYNC_OK
) {
2215 switch (res
.hdr
.reason
) {
2216 case FSYNC_WRONG_PART
:
2217 case FSYNC_UNKNOWN_VOLID
:
2230 * mode of volume list operation.
2233 VOL_INFO_LIST_SINGLE
, /**< performing a single volume list op */
2234 VOL_INFO_LIST_MULTIPLE
/**< performing a multi-volume list op */
2235 } vol_info_list_mode_t
;
2238 * abstract interface to populate wire-format volume metadata structures.
2240 * @param[in] partId partition id
2241 * @param[in] volumeId volume id
2242 * @param[in] pname partition name
2243 * @param[in] volname volume file name
2244 * @param[in] handle handle to on-wire volume metadata object
2245 * @param[in] mode listing mode
2247 * @return operation status
2249 * @retval -2 DESTROY_ME flag is set
2250 * @retval -1 general failure; some data filled in
2251 * @retval -3 couldn't create vtrans; some data filled in
2254 GetVolInfo(afs_uint32 partId
,
2258 volint_info_handle_t
* handle
,
2259 vol_info_list_mode_t mode
)
2263 struct volser_trans
*ttc
= NULL
;
2264 struct Volume
*fill_tv
, *tv
= NULL
;
2265 #ifdef AFS_DEMAND_ATTACH_FS
2266 struct Volume fs_tv_buf
, *fs_tv
= &fs_tv_buf
; /* Create a structure, and a pointer to that structure */
2267 SYNC_PROTO_BUF_DECL(fs_res_buf
); /* Buffer for the pending_vol_op */
2268 SYNC_response fs_res
; /* Response handle for the pending_vol_op */
2269 FSSYNC_VolOp_info pending_vol_op_res
; /* Pending vol ops to full in volume */
2271 /* Set up response handle for pending_vol_op */
2272 fs_res
.hdr
.response_len
= sizeof(fs_res
.hdr
);
2273 fs_res
.payload
.buf
= fs_res_buf
;
2274 fs_res
.payload
.len
= SYNC_PROTO_MAX_LEN
;
2277 ttc
= NewTrans(volumeId
, partId
);
2280 VOLINT_INFO_STORE(handle
, status
, VBUSY
);
2281 VOLINT_INFO_STORE(handle
, volid
, volumeId
);
2285 /* Get volume from volserver */
2286 if (mode
== VOL_INFO_LIST_MULTIPLE
)
2287 tv
= VAttachVolumeByName(&error
, pname
, volname
, V_PEEK
);
2289 #ifdef AFS_DEMAND_ATTACH_FS
2292 int mode
= V_READONLY
; /* informs the fileserver to update the volume headers. */
2294 tv
= VAttachVolumeByName_retry(&error
, pname
, volname
, mode
);
2298 Log("1 Volser: GetVolInfo: Could not attach volume %" AFS_VOLID_FMT
" (%s:%s) error=%d\n",
2299 afs_printable_VolumeId_lu(volumeId
), pname
, volname
, error
);
2304 * please note that destroyMe and needsSalvaged checks used to be ordered
2305 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2306 * more correct to check destroyMe before needsSalvaged.
2307 * -- tkeiser 11/28/2007
2310 if (V_destroyMe(tv
) == DESTROY_ME
) {
2312 case VOL_INFO_LIST_MULTIPLE
:
2316 case VOL_INFO_LIST_SINGLE
:
2317 Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT
" (%s:%s) will be destroyed on next salvage\n",
2318 afs_printable_VolumeId_lu(volumeId
), pname
, volname
);
2325 if (V_needsSalvaged(tv
)) {
2326 /*this volume will be salvaged */
2327 Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT
" (%s:%s) needs to be salvaged\n",
2328 afs_printable_VolumeId_lu(volumeId
), pname
, volname
);
2331 #ifdef AFS_DEMAND_ATTACH_FS
2332 /* If using DAFS, get volume from fsserver */
2333 if (GetVolObject(volumeId
, pname
, &fs_tv
) != SYNC_OK
|| fs_tv
== NULL
) {
2338 /* fs_tv is a shallow copy, must populate certain structures before passing along */
2339 if (FSYNC_VolOp(volumeId
, pname
, FSYNC_VOL_QUERY_VOP
, 0, &fs_res
) == SYNC_OK
) {
2340 /* If we if the pending vol op */
2341 memcpy(&pending_vol_op_res
, fs_res
.payload
.buf
, sizeof(FSSYNC_VolOp_info
));
2342 fs_tv
->pending_vol_op
=&pending_vol_op_res
;
2344 fs_tv
->pending_vol_op
=NULL
;
2347 /* populate the header from the volserver copy */
2348 fs_tv
->header
=tv
->header
;
2350 /* When using DAFS, use the fs volume info, populated with required structures */
2353 /* When not using DAFS, just use the local volume info */
2357 /* ok, we have all the data we need; fill in the on-wire struct */
2358 code
= FillVolInfo(fill_tv
, handle
);
2362 VOLINT_INFO_STORE(handle
, status
, 0);
2363 strcpy((char *)VOLINT_INFO_PTR(handle
, name
), volname
);
2364 VOLINT_INFO_STORE(handle
, volid
, volumeId
);
2367 VDetachVolume(&error
, tv
);
2370 VOLINT_INFO_STORE(handle
, status
, 0);
2371 strcpy((char *)VOLINT_INFO_PTR(handle
, name
), volname
);
2372 Log("1 Volser: GetVolInfo: Could not detach volume %" AFS_VOLID_FMT
" (%s:%s)\n",
2373 afs_printable_VolumeId_lu(volumeId
), pname
, volname
);
2377 DeleteTrans(ttc
, 1);
2384 /*return the header information about the <volid> */
2386 SAFSVolListOneVolume(struct rx_call
*acid
, afs_int32 partid
,
2387 VolumeId volumeId
, volEntries
*volumeInfo
)
2391 code
= VolListOneVolume(acid
, partid
, volumeId
, volumeInfo
);
2392 osi_auditU(acid
, VS_Lst1VolEvent
, code
, AUD_LONG
, volumeId
, AUD_END
);
2397 VolListOneVolume(struct rx_call
*acid
, afs_int32 partid
,
2398 VolumeId volumeId
, volEntries
*volumeInfo
)
2400 struct DiskPartition64
*partP
;
2401 char pname
[9], volname
[20];
2405 volint_info_handle_t handle
;
2407 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
2408 return VOLSERBAD_ACCESS
;
2410 volumeInfo
->volEntries_val
= calloc(1, sizeof(volintInfo
));
2411 if (!volumeInfo
->volEntries_val
)
2414 volumeInfo
->volEntries_len
= 1;
2415 if (GetPartName(partid
, pname
))
2416 return VOLSERILLEGAL_PARTITION
;
2417 if (!(partP
= VGetPartition(pname
, 0)))
2418 return VOLSERILLEGAL_PARTITION
;
2419 dirp
= opendir(VPartitionPath(partP
));
2421 return VOLSERILLEGAL_PARTITION
;
2423 while (GetNextVol(dirp
, volname
, &volid
)) {
2424 if (volid
== volumeId
) { /*copy other things too */
2431 #ifndef AFS_PTHREAD_ENV
2432 IOMGR_Poll(); /*make sure that the client does not time out */
2435 handle
.volinfo_type
= VOLINT_INFO_TYPE_BASE
;
2436 handle
.volinfo_ptr
.base
= volumeInfo
->volEntries_val
;
2438 /* The return code from GetVolInfo is ignored; there is no error from
2439 * it that results in the whole call being aborted. Any volume
2440 * attachment failures are reported in 'status' field in the
2441 * volumeInfo payload. */
2447 VOL_INFO_LIST_SINGLE
);
2451 return (found
) ? 0 : ENODEV
;
2454 /*------------------------------------------------------------------------
2455 * EXPORTED SAFSVolXListOneVolume
2458 * Returns extended info on volume a_volID on partition a_partID.
2461 * a_rxCidP : Pointer to the Rx call we're performing.
2462 * a_partID : Partition for which we want the extended list.
2463 * a_volID : Volume ID we wish to know about.
2464 * a_volumeXInfoP : Ptr to the extended info blob.
2467 * 0 Successful operation
2468 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2471 * Nothing interesting.
2475 *------------------------------------------------------------------------*/
2478 SAFSVolXListOneVolume(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2479 VolumeId a_volID
, volXEntries
*a_volumeXInfoP
)
2483 code
= VolXListOneVolume(a_rxCidP
, a_partID
, a_volID
, a_volumeXInfoP
);
2484 osi_auditU(a_rxCidP
, VS_XLst1VlEvent
, code
, AUD_LONG
, a_volID
, AUD_END
);
2489 VolXListOneVolume(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2490 VolumeId a_volID
, volXEntries
*a_volumeXInfoP
)
2491 { /*SAFSVolXListOneVolume */
2493 struct DiskPartition64
*partP
; /*Ptr to partition */
2494 char pname
[9], volname
[20]; /*Partition, volume names */
2495 DIR *dirp
; /*Partition directory ptr */
2496 VolumeId currVolID
; /*Current volume ID */
2497 int found
= 0; /*Did we find the volume we need? */
2498 volint_info_handle_t handle
;
2500 if (!afsconf_CheckRestrictedQuery(tdir
, a_rxCidP
, restrictedQueryLevel
))
2501 return VOLSERBAD_ACCESS
;
2504 * Set up our pointers for action, marking our structure to hold exactly
2505 * one entry. Also, assume we'll fail in our quest.
2507 a_volumeXInfoP
->volXEntries_val
= calloc(1, sizeof(volintXInfo
));
2508 if (!a_volumeXInfoP
->volXEntries_val
)
2511 a_volumeXInfoP
->volXEntries_len
= 1;
2514 * If the partition name we've been given is bad, bogue out.
2516 if (GetPartName(a_partID
, pname
))
2517 return (VOLSERILLEGAL_PARTITION
);
2520 * Open the directory representing the given AFS parttion. If we can't
2523 if (!(partP
= VGetPartition(pname
, 0)))
2524 return VOLSERILLEGAL_PARTITION
;
2525 dirp
= opendir(VPartitionPath(partP
));
2527 return (VOLSERILLEGAL_PARTITION
);
2531 * Sweep through the partition directory, looking for the desired entry.
2532 * First, of course, figure out how many stat bytes to copy out of each
2535 while (GetNextVol(dirp
, volname
, &currVolID
)) {
2536 if (currVolID
== a_volID
) {
2538 * We found the volume entry we're interested. Pull out the
2539 * extended information, remembering to poll (so that the client
2540 * doesn't time out) and to set up a transaction on the volume.
2544 } /*Found desired volume */
2548 #ifndef AFS_PTHREAD_ENV
2552 handle
.volinfo_type
= VOLINT_INFO_TYPE_EXT
;
2553 handle
.volinfo_ptr
.ext
= a_volumeXInfoP
->volXEntries_val
;
2555 /* The return code from GetVolInfo is ignored; there is no error from
2556 * it that results in the whole call being aborted. Any volume
2557 * attachment failures are reported in 'status' field in the
2558 * volumeInfo payload. */
2559 GetVolInfo(a_partID
,
2564 VOL_INFO_LIST_SINGLE
);
2568 * Clean up before going to dinner: close the partition directory,
2569 * return the proper value.
2572 return (found
) ? 0 : ENODEV
;
2573 } /*SAFSVolXListOneVolume */
2575 /*returns all the volumes on partition partid. If flags = 1 then all the
2576 * relevant info about the volumes is also returned */
2578 SAFSVolListVolumes(struct rx_call
*acid
, afs_int32 partid
, afs_int32 flags
,
2579 volEntries
*volumeInfo
)
2583 code
= VolListVolumes(acid
, partid
, flags
, volumeInfo
);
2584 osi_auditU(acid
, VS_ListVolEvent
, code
, AUD_END
);
2589 VolListVolumes(struct rx_call
*acid
, afs_int32 partid
, afs_int32 flags
,
2590 volEntries
*volumeInfo
)
2593 struct DiskPartition64
*partP
;
2594 afs_int32 allocSize
= 1000; /*to be changed to a larger figure */
2595 char pname
[9], volname
[20];
2599 volint_info_handle_t handle
;
2601 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
2602 return VOLSERBAD_ACCESS
;
2604 volumeInfo
->volEntries_val
= calloc(allocSize
, sizeof(volintInfo
));
2605 if (!volumeInfo
->volEntries_val
)
2608 pntr
= volumeInfo
->volEntries_val
;
2609 volumeInfo
->volEntries_len
= 0;
2610 if (GetPartName(partid
, pname
))
2611 return VOLSERILLEGAL_PARTITION
;
2612 if (!(partP
= VGetPartition(pname
, 0)))
2613 return VOLSERILLEGAL_PARTITION
;
2614 dirp
= opendir(VPartitionPath(partP
));
2616 return VOLSERILLEGAL_PARTITION
;
2618 while (GetNextVol(dirp
, volname
, &volid
)) {
2619 if (flags
) { /*copy other things too */
2620 #ifndef AFS_PTHREAD_ENV
2621 IOMGR_Poll(); /*make sure that the client does not time out */
2624 handle
.volinfo_type
= VOLINT_INFO_TYPE_BASE
;
2625 handle
.volinfo_ptr
.base
= pntr
;
2628 code
= GetVolInfo(partid
,
2633 VOL_INFO_LIST_MULTIPLE
);
2634 if (code
== -2) /* DESTROY_ME flag set */
2637 pntr
->volid
= volid
;
2638 /*just volids are needed */
2642 volumeInfo
->volEntries_len
+= 1;
2643 if ((allocSize
- volumeInfo
->volEntries_len
) < 5) {
2644 /*running out of space, allocate more space */
2645 allocSize
= (allocSize
* 3) / 2;
2646 pntr
= realloc(volumeInfo
->volEntries_val
,
2647 allocSize
* sizeof(volintInfo
));
2650 return VOLSERNO_MEMORY
;
2652 volumeInfo
->volEntries_val
= pntr
; /* point to new block */
2653 /* set pntr to the right position */
2654 pntr
= volumeInfo
->volEntries_val
+ volumeInfo
->volEntries_len
;
2662 /*------------------------------------------------------------------------
2663 * EXPORTED SAFSVolXListVolumes
2666 * Returns all the volumes on partition a_partID. If a_flags
2667 * is set to 1, then all the relevant extended volume information
2671 * a_rxCidP : Pointer to the Rx call we're performing.
2672 * a_partID : Partition for which we want the extended list.
2673 * a_flags : Various flags.
2674 * a_volumeXInfoP : Ptr to the extended info blob.
2677 * 0 Successful operation
2678 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2679 * VOLSERNO_MEMORY if we ran out of memory allocating
2683 * Nothing interesting.
2687 *------------------------------------------------------------------------*/
2690 SAFSVolXListVolumes(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2691 afs_int32 a_flags
, volXEntries
*a_volumeXInfoP
)
2695 code
= VolXListVolumes(a_rxCidP
, a_partID
, a_flags
, a_volumeXInfoP
);
2696 osi_auditU(a_rxCidP
, VS_XLstVolEvent
, code
, AUD_END
);
2701 VolXListVolumes(struct rx_call
*a_rxCidP
, afs_int32 a_partID
,
2702 afs_int32 a_flags
, volXEntries
*a_volumeXInfoP
)
2703 { /*SAFSVolXListVolumes */
2705 volintXInfo
*xInfoP
; /*Ptr to the extended vol info */
2706 struct DiskPartition64
*partP
; /*Ptr to partition */
2707 afs_int32 allocSize
= 1000; /*To be changed to a larger figure */
2708 char pname
[9], volname
[20]; /*Partition, volume names */
2709 DIR *dirp
; /*Partition directory ptr */
2710 VolumeId volid
; /*Current volume ID */
2712 volint_info_handle_t handle
;
2714 if (!afsconf_CheckRestrictedQuery(tdir
, a_rxCidP
, restrictedQueryLevel
))
2715 return VOLSERBAD_ACCESS
;
2718 * Allocate a large array of extended volume info structures, then
2719 * set it up for action.
2721 a_volumeXInfoP
->volXEntries_val
= calloc(allocSize
, sizeof(volintXInfo
));
2722 if (!a_volumeXInfoP
->volXEntries_val
)
2725 xInfoP
= a_volumeXInfoP
->volXEntries_val
;
2726 a_volumeXInfoP
->volXEntries_len
= 0;
2729 * If the partition name we've been given is bad, bogue out.
2731 if (GetPartName(a_partID
, pname
))
2732 return (VOLSERILLEGAL_PARTITION
);
2735 * Open the directory representing the given AFS parttion. If we can't
2738 if (!(partP
= VGetPartition(pname
, 0)))
2739 return VOLSERILLEGAL_PARTITION
;
2740 dirp
= opendir(VPartitionPath(partP
));
2742 return (VOLSERILLEGAL_PARTITION
);
2743 while (GetNextVol(dirp
, volname
, &volid
)) {
2746 * Full info about the volume desired. Poll to make sure the
2747 * client doesn't time out, then start up a new transaction.
2749 #ifndef AFS_PTHREAD_ENV
2753 handle
.volinfo_type
= VOLINT_INFO_TYPE_EXT
;
2754 handle
.volinfo_ptr
.ext
= xInfoP
;
2756 code
= GetVolInfo(a_partID
,
2761 VOL_INFO_LIST_MULTIPLE
);
2762 if (code
== -2) /* DESTROY_ME flag set */
2766 * Just volume IDs are needed.
2768 xInfoP
->volid
= volid
;
2772 * Bump the pointer in the data area we're building, along with
2773 * the count of the number of entries it contains.
2776 (a_volumeXInfoP
->volXEntries_len
)++;
2777 if ((allocSize
- a_volumeXInfoP
->volXEntries_len
) < 5) {
2779 * We're running out of space in the area we've built. Grow it.
2781 allocSize
= (allocSize
* 3) / 2;
2782 xInfoP
= (volintXInfo
*)
2783 realloc((char *)a_volumeXInfoP
->volXEntries_val
,
2784 (allocSize
* sizeof(volintXInfo
)));
2785 if (xInfoP
== NULL
) {
2787 * Bummer, no memory. Bag it, tell our caller what went wrong.
2790 return (VOLSERNO_MEMORY
);
2794 * Memory reallocation worked. Correct our pointers so they
2795 * now point to the new block and the current open position within
2798 a_volumeXInfoP
->volXEntries_val
= xInfoP
;
2800 a_volumeXInfoP
->volXEntries_val
+
2801 a_volumeXInfoP
->volXEntries_len
;
2806 * We've examined all entries in the partition directory. Close it,
2807 * delete our transaction (if any), and go home happy.
2812 } /*SAFSVolXListVolumes */
2814 /*this call is used to monitor the status of volser for debugging purposes.
2815 *information about all the active transactions is returned in transInfo*/
2817 SAFSVolMonitor(struct rx_call
*acid
, transDebugEntries
*transInfo
)
2821 code
= VolMonitor(acid
, transInfo
);
2822 osi_auditU(acid
, VS_MonitorEvent
, code
, AUD_END
);
2827 VolMonitor(struct rx_call
*acid
, transDebugEntries
*transInfo
)
2829 transDebugInfo
*pntr
;
2830 afs_int32 allocSize
= 50;
2831 struct volser_trans
*tt
, *nt
, *allTrans
;
2833 if (!afsconf_CheckRestrictedQuery(tdir
, acid
, restrictedQueryLevel
))
2834 return VOLSERBAD_ACCESS
;
2836 transInfo
->transDebugEntries_val
=
2837 malloc(allocSize
* sizeof(transDebugInfo
));
2838 if (!transInfo
->transDebugEntries_val
)
2840 pntr
= transInfo
->transDebugEntries_val
;
2841 transInfo
->transDebugEntries_len
= 0;
2844 allTrans
= TransList();
2845 if (allTrans
== (struct volser_trans
*)0)
2846 goto done
; /*no active transactions */
2847 for (tt
= allTrans
; tt
; tt
= nt
) { /*copy relevant info into pntr */
2849 memset(pntr
, 0, sizeof(*pntr
));
2850 VTRANS_OBJ_LOCK(tt
);
2851 pntr
->tid
= tt
->tid
;
2852 pntr
->time
= tt
->time
;
2853 pntr
->creationTime
= tt
->creationTime
;
2854 pntr
->returnCode
= tt
->returnCode
;
2855 pntr
->volid
= tt
->volid
;
2856 pntr
->partition
= tt
->partition
;
2857 pntr
->iflags
= tt
->iflags
;
2858 pntr
->vflags
= tt
->vflags
;
2859 pntr
->tflags
= tt
->tflags
;
2860 strcpy(pntr
->lastProcName
, tt
->lastProcName
);
2861 pntr
->callValid
= 0;
2862 if (tt
->rxCallPtr
) { /*record call related info */
2863 pntr
->callValid
= 1;
2864 rx_GetCallStatus(tt
->rxCallPtr
, &(pntr
->readNext
), &(pntr
->transmitNext
),
2865 &(pntr
->lastSendTime
), &(pntr
->lastReceiveTime
));
2867 VTRANS_OBJ_UNLOCK(tt
);
2869 transInfo
->transDebugEntries_len
+= 1;
2870 if ((allocSize
- transInfo
->transDebugEntries_len
) < 5) { /*alloc some more space */
2871 allocSize
= (allocSize
* 3) / 2;
2872 pntr
= realloc(transInfo
->transDebugEntries_val
,
2873 allocSize
* sizeof(transDebugInfo
));
2874 transInfo
->transDebugEntries_val
= pntr
;
2876 transInfo
->transDebugEntries_val
+
2877 transInfo
->transDebugEntries_len
;
2878 /*set pntr to right position */
2889 SAFSVolSetIdsTypes(struct rx_call
*acid
, afs_int32 atid
, char name
[],
2890 afs_int32 type
, afs_uint32 pId
, VolumeId cloneId
,
2895 code
= VolSetIdsTypes(acid
, atid
, name
, type
, pId
, cloneId
, backupId
);
2896 osi_auditU(acid
, VS_SetIdTyEvent
, code
, AUD_LONG
, atid
, AUD_STR
, name
,
2897 AUD_LONG
, type
, AUD_LONG
, pId
, AUD_LONG
, cloneId
, AUD_LONG
,
2903 VolSetIdsTypes(struct rx_call
*acid
, afs_int32 atid
, char name
[],
2904 afs_int32 type
, VolumeId pId
, VolumeId cloneId
,
2909 struct volser_trans
*tt
;
2910 char caller
[MAXKTCNAMELEN
];
2912 if (strlen(name
) > 31)
2913 return VOLSERBADNAME
;
2914 if (!afsconf_SuperUser(tdir
, acid
, caller
))
2915 return VOLSERBAD_ACCESS
; /*not a super user */
2916 /* find the trans */
2917 tt
= FindTrans(atid
);
2920 if (tt
->vflags
& VTDeleted
) {
2921 Log("1 Volser: VolSetIds: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
2925 TSetRxCall(tt
, acid
, "SetIdsTypes");
2929 V_backupId(tv
) = backupId
;
2930 V_cloneId(tv
) = cloneId
;
2931 V_parentId(tv
) = pId
;
2932 strcpy((&V_disk(tv
))->name
, name
);
2933 VUpdateVolume(&error
, tv
);
2935 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error
);
2940 if (TRELE(tt
) && !error
)
2941 return VOLSERTRELE_ERROR
;
2946 if (TRELE(tt
) && !error
)
2947 return VOLSERTRELE_ERROR
;
2952 SAFSVolSetDate(struct rx_call
*acid
, afs_int32 atid
, afs_int32 cdate
)
2956 code
= VolSetDate(acid
, atid
, cdate
);
2957 osi_auditU(acid
, VS_SetDateEvent
, code
, AUD_LONG
, atid
, AUD_LONG
, cdate
,
2963 VolSetDate(struct rx_call
*acid
, afs_int32 atid
, afs_int32 cdate
)
2967 struct volser_trans
*tt
;
2968 char caller
[MAXKTCNAMELEN
];
2970 if (!afsconf_SuperUser(tdir
, acid
, caller
))
2971 return VOLSERBAD_ACCESS
; /*not a super user */
2972 /* find the trans */
2973 tt
= FindTrans(atid
);
2976 if (tt
->vflags
& VTDeleted
) {
2977 Log("1 Volser: VolSetDate: volume %" AFS_VOLID_FMT
" has been deleted \n", afs_printable_VolumeId_lu(tt
->volid
));
2981 TSetRxCall(tt
, acid
, "SetDate");
2984 V_creationDate(tv
) = cdate
;
2985 VUpdateVolume(&error
, tv
);
2987 Log("1 Volser: SetDate: VUpdate failed code %d\n", error
);
2992 if (TRELE(tt
) && !error
)
2993 return VOLSERTRELE_ERROR
;
2998 if (TRELE(tt
) && !error
)
2999 return VOLSERTRELE_ERROR
;
3004 SAFSVolConvertROtoRWvolume(struct rx_call
*acid
, afs_int32 partId
,
3010 char caller
[MAXKTCNAMELEN
];
3012 struct volser_trans
*ttc
;
3013 char pname
[16], volname
[20];
3014 struct DiskPartition64
*partP
;
3015 afs_int32 ret
= ENODEV
;
3018 if (!afsconf_SuperUser(tdir
, acid
, caller
))
3019 return VOLSERBAD_ACCESS
; /*not a super user */
3020 if (GetPartName(partId
, pname
))
3021 return VOLSERILLEGAL_PARTITION
;
3022 if (!(partP
= VGetPartition(pname
, 0)))
3023 return VOLSERILLEGAL_PARTITION
;
3024 dirp
= opendir(VPartitionPath(partP
));
3026 return VOLSERILLEGAL_PARTITION
;
3027 ttc
= (struct volser_trans
*)0;
3029 while (GetNextVol(dirp
, volname
, &volid
)) {
3030 if (volid
== volumeId
) { /*copy other things too */
3031 #ifndef AFS_PTHREAD_ENV
3032 IOMGR_Poll(); /*make sure that the client doesnot time out */
3034 ttc
= NewTrans(volumeId
, partId
);
3036 return VOLSERVOLBUSY
;
3038 #ifdef AFS_NAMEI_ENV
3039 ret
= namei_ConvertROtoRWvolume(pname
, volumeId
);
3041 ret
= inode_ConvertROtoRWvolume(pname
, volumeId
);
3048 DeleteTrans(ttc
, 1);
3056 SAFSVolGetSize(struct rx_call
*acid
, afs_int32 fromTrans
, afs_int32 fromDate
,
3057 struct volintSize
*size
)
3060 struct volser_trans
*tt
;
3061 char caller
[MAXKTCNAMELEN
];
3063 if (!afsconf_SuperUser(tdir
, acid
, caller
))
3064 return VOLSERBAD_ACCESS
; /*not a super user */
3065 tt
= FindTrans(fromTrans
);
3068 if (tt
->vflags
& VTDeleted
) {
3072 TSetRxCall(tt
, acid
, "GetSize");
3073 code
= SizeDumpVolume(acid
, tt
->volume
, fromDate
, 1, size
); /* measure volume's data */
3076 return VOLSERTRELE_ERROR
;
3078 /* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
3083 SAFSVolSplitVolume(struct rx_call
*acall
, afs_uint32 ovid
, afs_uint32 onew
,
3084 afs_uint32 where
, afs_int32 verbose
)
3086 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
3088 Volume
*vol
=0, *newvol
=0;
3089 struct volser_trans
*tt
= 0, *tt2
= 0;
3090 char caller
[MAXKTCNAMELEN
];
3092 VolumeId
new = onew
;
3093 VolumeId vid
= ovid
;
3095 if (!afsconf_SuperUser(tdir
, acall
, caller
))
3098 vol
= VAttachVolume(&code
, vid
, V_VOLUPD
);
3104 newvol
= VAttachVolume(&code
, new, V_VOLUPD
);
3106 VDetachVolume(&code2
, vol
);
3111 if (V_device(vol
) != V_device(newvol
)
3112 || V_uniquifier(newvol
) != 2) {
3113 if (V_device(vol
) != V_device(newvol
)) {
3114 sprintf(line
, "Volumes %" AFS_VOLID_FMT
" and %" AFS_VOLID_FMT
" are not in the same partition, aborted.\n",
3115 afs_printable_VolumeId_lu(vid
),
3116 afs_printable_VolumeId_lu(new));
3117 rx_Write(acall
, line
, strlen(line
));
3119 if (V_uniquifier(newvol
) != 2) {
3120 sprintf(line
, "Volume %" AFS_VOLID_FMT
" is not freshly created, aborted.\n",
3121 afs_printable_VolumeId_lu(new));
3122 rx_Write(acall
, line
, strlen(line
));
3125 rx_Write(acall
, line
, 1);
3126 VDetachVolume(&code2
, vol
);
3127 VDetachVolume(&code2
, newvol
);
3130 tt
= NewTrans(vid
, V_device(vol
));
3132 sprintf(line
, "Couldn't create transaction for %" AFS_VOLID_FMT
", aborted.\n",
3133 afs_printable_VolumeId_lu(vid
));
3134 rx_Write(acall
, line
, strlen(line
));
3136 rx_Write(acall
, line
, 1);
3137 VDetachVolume(&code2
, vol
);
3138 VDetachVolume(&code2
, newvol
);
3139 return VOLSERVOLBUSY
;
3141 VTRANS_OBJ_LOCK(tt
);
3142 tt
->iflags
= ITBusy
;
3144 TSetRxCall_r(tt
, NULL
, "SplitVolume");
3145 VTRANS_OBJ_UNLOCK(tt
);
3147 tt2
= NewTrans(new, V_device(newvol
));
3149 sprintf(line
, "Couldn't create transaction for %" AFS_VOLID_FMT
", aborted.\n",
3150 afs_printable_VolumeId_lu(new));
3151 rx_Write(acall
, line
, strlen(line
));
3153 rx_Write(acall
, line
, 1);
3155 VDetachVolume(&code2
, vol
);
3156 VDetachVolume(&code2
, newvol
);
3157 return VOLSERVOLBUSY
;
3159 VTRANS_OBJ_LOCK(tt2
);
3160 tt2
->iflags
= ITBusy
;
3162 TSetRxCall_r(tt2
, NULL
, "SplitVolume");
3163 VTRANS_OBJ_UNLOCK(tt2
);
3165 code
= split_volume(acall
, vol
, newvol
, where
, verbose
);
3167 VDetachVolume(&code2
, vol
);
3169 VDetachVolume(&code2
, newvol
);
3170 DeleteTrans(tt2
, 1);
3177 /* GetPartName - map partid (a decimal number) into pname (a string)
3178 * Since for NT we actually want to return the drive name, we map through the
3182 GetPartName(afs_int32 partid
, char *pname
)
3187 strcpy(pname
, "/vicep");
3188 pname
[6] = 'a' + partid
;
3191 } else if (partid
< VOLMAXPARTS
) {
3192 strcpy(pname
, "/vicep");
3194 pname
[6] = 'a' + (partid
/ 26);
3195 pname
[7] = 'a' + (partid
% 26);