/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * Portions Copyright (c) 2007-2008 Sine Nomine Associates
*/
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <errno.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#include <winsock2.h>
-#else
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#endif
+#include <roken.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
+#include <afs/opr.h>
+#ifdef AFS_PTHREAD_ENV
+# include <opr/lock.h>
#endif
-#include <dirent.h>
-#include <sys/stat.h>
-#include <rx/xdr.h>
#include <rx/rx.h>
#include <rx/rxkad.h>
+#include <rx/rx_queue.h>
#include <afs/afsint.h>
-#include <signal.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else /* AFS_PTHREAD_ENV */
-#include <afs/assert.h>
-#endif /* AFS_PTHREAD_ENV */
#include <afs/prs_fs.h>
#include <afs/nfs.h>
#include <lwp.h>
#include <lock.h>
-#include <afs/auth.h>
#include <afs/cellconfig.h>
#include <afs/keys.h>
#include <ubik.h>
#endif
#include <afs/vnode.h>
#include <afs/volume.h>
+#include <afs/volume_inline.h>
#include <afs/partition.h>
#include "vol.h"
+#include <afs/daemon_com.h>
#include <afs/fssync.h>
#include <afs/acl.h>
#include "afs/audit.h"
#include <afs/dir.h>
+#include <afs/afsutil.h>
+#include <afs/com_err.h>
+#include <afs/vol_prototypes.h>
+#include <afs/errors.h>
#include "volser.h"
+#include "voltrans_inline.h"
#include "volint.h"
-#include <volser_prototypes.h>
+#include "volser_internal.h"
+#include "physio.h"
+#include "dumpstuff.h"
extern int DoLogging;
-extern struct volser_trans *FindTrans(), *NewTrans(), *TransList();
extern struct afsconf_dir *tdir;
-extern char *volutil_PartitionName();
+extern int DoPreserveVolumeStats;
extern void LogError(afs_int32 errcode);
#endif
afs_int32 localTid = 1;
-afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
-VolDeleteVolume(), VolClone();
-afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
-VolForward(), VolDump();
-afs_int32 VolForwardMultiple();
-afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
-VolSetInfo(), VolGetName();
-afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(),
-VolXListOneVolume(), VolXListVolumes();
-afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
-VolSetIdsTypes(), VolSetDate(), VolSetFlags();
+
+static afs_int32 VolPartitionInfo(struct rx_call *, char *pname,
+ struct diskPartition64 *);
+static afs_int32 VolNukeVolume(struct rx_call *, afs_int32, afs_uint32);
+static afs_int32 VolCreateVolume(struct rx_call *, afs_int32, char *,
+ afs_int32, afs_uint32, afs_uint32 *,
+ afs_int32 *);
+static afs_int32 VolDeleteVolume(struct rx_call *, afs_int32);
+static afs_int32 VolClone(struct rx_call *, afs_int32, VolumeId,
+ afs_int32, char *, VolumeId *);
+static afs_int32 VolReClone(struct rx_call *, afs_int32, VolumeId);
+static afs_int32 VolTransCreate(struct rx_call *, VolumeId, afs_int32,
+ afs_int32, afs_int32 *);
+static afs_int32 VolGetNthVolume(struct rx_call *, afs_int32, afs_uint32 *,
+ afs_int32 *);
+static afs_int32 VolGetFlags(struct rx_call *, afs_int32, afs_int32 *);
+static afs_int32 VolSetFlags(struct rx_call *, afs_int32, afs_int32 );
+static afs_int32 VolForward(struct rx_call *, afs_int32, afs_int32,
+ struct destServer *destination, afs_int32,
+ struct restoreCookie *cookie);
+static afs_int32 VolDump(struct rx_call *, afs_int32, afs_int32, afs_int32);
+static afs_int32 VolRestore(struct rx_call *, afs_int32, afs_int32,
+ struct restoreCookie *);
+static afs_int32 VolEndTrans(struct rx_call *, afs_int32, afs_int32 *);
+static afs_int32 VolSetForwarding(struct rx_call *, afs_int32, afs_int32);
+static afs_int32 VolGetStatus(struct rx_call *, afs_int32,
+ struct volser_status *);
+static afs_int32 VolSetInfo(struct rx_call *, afs_int32, struct volintInfo *);
+static afs_int32 VolGetName(struct rx_call *, afs_int32, char **);
+static afs_int32 VolListPartitions(struct rx_call *, struct pIDs *);
+static afs_int32 XVolListPartitions(struct rx_call *, struct partEntries *);
+static afs_int32 VolListOneVolume(struct rx_call *, afs_int32, VolumeId,
+ volEntries *);
+static afs_int32 VolXListOneVolume(struct rx_call *, afs_int32, VolumeId,
+ volXEntries *);
+static afs_int32 VolListVolumes(struct rx_call *, afs_int32, afs_int32,
+ volEntries *);
+static afs_int32 VolXListVolumes(struct rx_call *, afs_int32, afs_int32,
+ volXEntries *);
+static afs_int32 VolMonitor(struct rx_call *, transDebugEntries *);
+static afs_int32 VolSetIdsTypes(struct rx_call *, afs_int32, char [],
+ afs_int32, VolumeId, VolumeId,
+ VolumeId);
+static afs_int32 VolSetDate(struct rx_call *, afs_int32, afs_int32);
+
+/**
+ * Return the host address of the caller as a string.
+ *
+ * @param[in] acid incoming rx call
+ * @param[out] buffer buffer to be filled with the addess string
+ *
+ * @return address as formatted by inet_ntoa
+ */
+static_inline char *
+callerAddress(struct rx_call *acid, char *buffer)
+{
+ afs_uint32 ip = rx_HostOf(rx_PeerOf(rx_ConnectionOf(acid)));
+ return afs_inet_ntoa_r(ip, buffer);
+}
/* this call unlocks all of the partition locks we've set */
-int
-VPFullUnlock()
+int
+VPFullUnlock_r(void)
{
- register struct DiskPartition *tp;
+ struct DiskPartition64 *tp;
for (tp = DiskPartitionList; tp; tp = tp->next) {
- if (tp->lock_fd != -1) {
- close(tp->lock_fd); /* releases flock held on this partition */
- tp->lock_fd = -1;
+ if (tp->lock_fd != INVALID_FD) {
+ OS_CLOSE(tp->lock_fd);
+ tp->lock_fd = INVALID_FD;
}
}
return 0;
}
+int
+VPFullUnlock(void)
+{
+ int code;
+ VOL_LOCK;
+ code = VPFullUnlock_r();
+ VOL_UNLOCK;
+ return code;
+}
+
/* get partition id from a name */
afs_int32
PartitionID(char *aname)
{
- register char tc;
- register int code = 0;
+ char tc;
+ int code = 0;
char ascii[3];
tc = *aname;
}
static int
-ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
+ConvertVolume(VolumeId avol, char *aname, afs_int32 asize)
{
if (asize < 18)
return -1;
/* 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 */
- (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
+ snprintf(aname, asize, VFORMAT, afs_printable_VolumeId_lu(avol));
return 0;
}
return 0;
}
+#ifdef AFS_DEMAND_ATTACH_FS
+/* normally we should use the regular salvaging functions from the volume
+ * package, but this is a special case where we have a volume ID, but no
+ * volume structure to give the volume package */
+static void
+SalvageUnknownVolume(VolumeId volid, char *part)
+{
+ afs_int32 code;
+
+ Log("Scheduling salvage for allegedly nonexistent volume %lu part %s\n",
+ afs_printable_uint32_lu(volid), part);
+
+ code = FSYNC_VolOp(volid, part, FSYNC_VOL_FORCE_ERROR,
+ FSYNC_SALVAGE, NULL);
+ if (code) {
+ Log("SalvageUnknownVolume: error %ld trying to salvage vol %lu part %s\n",
+ afs_printable_int32_ld(code), afs_printable_uint32_lu(volid),
+ part);
+ }
+}
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+static struct Volume *
+VAttachVolumeByName_retry(Error *ec, char *partition, char *name, int mode)
+{
+ struct Volume *vp;
+
+ *ec = 0;
+ vp = VAttachVolumeByName(ec, partition, name, mode);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ {
+ int i;
+ /*
+ * The fileserver will take care of keeping track of how many
+ * demand-salvages have been performed, and will force the volume to
+ * ERROR if we've done too many. The limit on This loop is just a
+ * failsafe to prevent trying to salvage forever. We want to attempt
+ * attachment at least SALVAGE_COUNT_MAX times, since we want to
+ * avoid prematurely exiting this loop, if we can.
+ */
+ for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING; i++) {
+ sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
+ vp = VAttachVolumeByName(ec, partition, name, mode);
+ }
+
+ if (*ec == VSALVAGING) {
+ *ec = VSALVAGE;
+ }
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+ return vp;
+}
+
+static struct Volume *
+VAttachVolume_retry(Error *ec, afs_uint32 avolid, int amode)
+{
+ struct Volume *vp;
+
+ *ec = 0;
+ vp = VAttachVolume(ec, avolid, amode);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ {
+ int i;
+ /* see comment above in VAttachVolumeByName_retry */
+ for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING; i++) {
+ sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
+ vp = VAttachVolume(ec, avolid, amode);
+ }
+
+ if (*ec == VSALVAGING) {
+ *ec = VSALVAGE;
+ }
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+ return vp;
+}
+
/* the only attach function that takes a partition is "...ByName", so we use it */
-struct Volume *
-XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
+static struct Volume *
+XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int amode)
{
char pbuf[30], vbuf[20];
- register struct Volume *tv;
if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
*error = EINVAL;
*error = EINVAL;
return NULL;
}
- tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
- return tv;
+
+ return VAttachVolumeByName_retry((Error *)error, pbuf, vbuf, amode);
}
/* Adapted from the file server; create a root directory for this volume */
-static int
+static Error
ViceCreateRoot(Volume *vp)
{
DirHandle dir;
struct acl_accessList *ACL;
- ViceFid did;
- Inode inodeNumber, nearInode;
- char buf[SIZEOF_LARGEDISKVNODE];
- struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
+ AFSFid did;
+ Inode inodeNumber, AFS_UNUSED nearInode;
+ struct VnodeDiskObject *vnode;
struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
IHandle_t *h;
FdHandle_t *fdP;
- int code;
afs_fsize_t length;
+ ssize_t nBytes;
- memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
+ vnode = calloc(1, SIZEOF_LARGEDISKVNODE);
+ if (!vnode)
+ return ENOMEM;
V_pref(vp, nearInode);
inodeNumber =
IH_CREATE(V_linkHandle(vp), V_device(vp),
VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
1, 1, 0);
- assert(VALID_INO(inodeNumber));
+ if (!VALID_INO(inodeNumber)) {
+ Log("ViceCreateRoot: IH_CREATE: %s\n", afs_error_message(errno));
+ free(vnode);
+ return EIO;
+ }
SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
did.Volume = V_id(vp);
did.Vnode = (VnodeId) 1;
did.Unique = 1;
- assert(!(MakeDir(&dir, &did, &did)));
+ opr_Verify(!(afs_dir_MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
DFlush(); /* flush all modified dir buffers out */
DZap(&dir); /* Remove all buffers for this dir */
- length = Length(&dir); /* Remember size of this directory */
+ length = afs_dir_Length(&dir); /* Remember size of this directory */
FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
IH_INIT(h, vp->device, V_parentId(vp),
vp->vnodeIndex[vLarge].handle->ih_ino);
fdP = IH_OPEN(h);
- assert(fdP != NULL);
- code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
- assert(code >= 0);
- code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
- assert(code == SIZEOF_LARGEDISKVNODE);
+ opr_Assert(fdP != NULL);
+ nBytes = FDH_PWRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE, vnodeIndexOffset(vcp, 1));
+ opr_Assert(nBytes == SIZEOF_LARGEDISKVNODE);
FDH_REALLYCLOSE(fdP);
IH_RELEASE(h);
VNDISK_GET_LEN(length, vnode);
V_diskused(vp) = nBlocks(length);
- return 1;
+ free(vnode);
+ return 0;
}
afs_int32
-SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
+SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
+ *partition)
+{
+ afs_int32 code;
+ struct diskPartition64 *dp = malloc(sizeof(struct diskPartition64));
+
+ code = VolPartitionInfo(acid, pname, dp);
+ if (!code) {
+ strncpy(partition->name, dp->name, 32);
+ strncpy(partition->devName, dp->devName, 32);
+ partition->lock_fd = dp->lock_fd;
+ partition->free=RoundInt64ToInt32(dp->free);
+ partition->minFree=RoundInt64ToInt32(dp->minFree);
+ }
+ free(dp);
+ osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
+ return code;
+}
+
+afs_int32
+SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
*partition)
{
afs_int32 code;
}
afs_int32
-VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
+VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
*partition)
{
- register struct DiskPartition *dp;
+ struct DiskPartition64 *dp;
-/*
- if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
-*/
VResetDiskUsage();
dp = VGetPartition(pname, 0);
if (dp) {
strncpy(partition->name, dp->name, 32);
strncpy(partition->devName, dp->devName, 32);
- partition->lock_fd = dp->lock_fd;
+ partition->lock_fd = (int)dp->lock_fd;
partition->free = dp->free;
partition->minFree = dp->totalUsable;
return 0;
/* obliterate a volume completely, and slowly. */
afs_int32
-SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
+SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, VolumeId avolID)
{
afs_int32 code;
return code;
}
-afs_int32
-VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
+static afs_int32
+VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
{
- register char *tp;
char partName[50];
afs_int32 error;
- register afs_int32 code;
+ Error verror;
+ afs_int32 code;
struct Volume *tvp;
char caller[MAXKTCNAMELEN];
/* check for access */
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS;
- if (DoLogging)
- Log("%s is executing VolNukeVolume %u\n", caller, avolID);
+ if (DoLogging) {
+ char buffer[16];
+ Log("%s on %s is executing VolNukeVolume %u\n", caller,
+ callerAddress(acid, buffer), avolID);
+ }
- tp = volutil_PartitionName(apartID);
- if (!tp)
+ if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
return VOLSERNOVOL;
- strcpy(partName, tp); /* remember it for later */
/* we first try to attach the volume in update mode, so that the file
* server doesn't try to use it (and abort) while (or after) we delete it.
* If we don't get the volume, that's fine, too. We just won't put it back.
tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
code = nuke(partName, avolID);
if (tvp)
- VDetachVolume(&error, tvp);
+ VDetachVolume(&verror, tvp);
return code;
}
* Return the new volume id in *avolid.
*/
afs_int32
-SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
- afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
+SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
+ afs_int32 atype, VolumeId aparent, VolumeId *avolid,
afs_int32 *atrans)
{
afs_int32 code;
return code;
}
-afs_int32
-VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
- afs_int32 atype, afs_int32 aparent, afs_int32 *avolid,
+static afs_int32
+VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
+ afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
afs_int32 *atrans)
{
- afs_int32 error;
- register Volume *vp;
- afs_int32 junk; /* discardable error code */
- register afs_int32 volumeID, doCreateRoot = 1;
- register struct volser_trans *tt;
+ Error error;
+ Volume *vp;
+ Error junk; /* discardable error code */
+ afs_uint32 volumeID;
+ afs_int32 doCreateRoot = 1;
+ struct volser_trans *tt;
char ppath[30];
char caller[MAXKTCNAMELEN];
return VOLSERBADNAME;
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS;
- if (DoLogging)
- Log("%s is executing CreateVolume '%s'\n", caller, aname);
+ if (DoLogging) {
+ char buffer[16];
+ Log("%s on %s is executing CreateVolume '%s'\n", caller,
+ callerAddress(acid, buffer), aname);
+ }
if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
return error; /*a standard unix error */
if (atype != readwriteVolume && atype != readonlyVolume
}
vp = VCreateVolume(&error, ppath, volumeID, aparent);
if (error) {
+#ifdef AFS_DEMAND_ATTACH_FS
+ if (error != VVOLEXISTS && error != EXDEV) {
+ SalvageUnknownVolume(volumeID, ppath);
+ }
+#endif
Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
LogError(error);
- DeleteTrans(tt);
+ DeleteTrans(tt, 1);
return EIO;
}
V_uniquifier(vp) = 1;
- V_creationDate(vp) = V_copyDate(vp);
+ V_updateDate(vp) = V_creationDate(vp) = V_copyDate(vp);
V_inService(vp) = V_blessed(vp) = 1;
V_type(vp) = atype;
AssignVolumeName(&V_disk(vp), aname, 0);
- if (doCreateRoot)
- ViceCreateRoot(vp);
+ if (doCreateRoot) {
+ error = ViceCreateRoot(vp);
+ if (error) {
+ Log("1 Volser: CreateVolume: Unable to create volume root dir; "
+ "error code %u\n", (unsigned)error);
+ DeleteTrans(tt, 1);
+ V_needsSalvaged(vp) = 1;
+ VDetachVolume(&junk, vp);
+ return EIO;
+ }
+ }
V_destroyMe(vp) = DESTROY_ME;
V_inService(vp) = 0;
V_maxquota(vp) = 5000; /* set a quota of 5000 at init time */
if (error) {
Log("1 Volser: create UpdateVolume failed, code %d\n", error);
LogError(error);
- DeleteTrans(tt);
+ DeleteTrans(tt, 1);
VDetachVolume(&junk, vp); /* rather return the real error code */
return error;
}
+ VTRANS_OBJ_LOCK(tt);
tt->volume = vp;
*atrans = tt->tid;
- strcpy(tt->lastProcName, "CreateVolume");
- tt->rxCallPtr = acid;
+ TSetRxCall_r(tt, acid, "CreateVolume");
+ VTRANS_OBJ_UNLOCK(tt);
Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
return 0;
return code;
}
-afs_int32
+static afs_int32
VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
{
- register struct volser_trans *tt;
- afs_int32 error;
+ struct volser_trans *tt;
+ Error error;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
+ Log("1 Volser: Delete: volume %" AFS_VOLID_FMT " already deleted \n",
+ afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- if (DoLogging)
- Log("%s is executing Delete Volume %u\n", caller, tt->volid);
- strcpy(tt->lastProcName, "DeleteVolume");
- tt->rxCallPtr = acid;
+ if (DoLogging) {
+ char buffer[16];
+ Log("%s on %s is executing Delete Volume %" AFS_VOLID_FMT "\n", caller,
+ callerAddress(acid, buffer), afs_printable_VolumeId_lu(tt->volid));
+ }
+ TSetRxCall(tt, acid, "DeleteVolume");
VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
+ V_destroyMe(tt->volume) = DESTROY_ME;
+ if (tt->volume->needsPutBack) {
+ tt->volume->needsPutBack = VOL_PUTBACK_DELETE; /* so endtrans does the right fssync opcode */
+ }
+ VTRANS_OBJ_LOCK(tt);
tt->vflags |= VTDeleted; /* so we know not to do anything else to it */
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall_r(tt);
+ VTRANS_OBJ_UNLOCK(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
- Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
+ Log("1 Volser: Delete: volume %" AFS_VOLID_FMT " deleted \n",
+ afs_printable_VolumeId_lu(tt->volid));
return 0; /* vpurgevolume doesn't set an error code */
}
/* make a clone of the volume associated with atrans, possibly giving it a new
* number (allocate a new number if *newNumber==0, otherwise use *newNumber
- * for the clone's id). The new clone is given the name newName. Finally, due to
- * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
- * the clone operation. This may be useful when making new backup volumes, for instance
- * since the net result of a clone and a purge generally leaves many inode ref counts
- * the same, while doing them separately would result in far more iincs and idecs being
- * peformed (and they are slow operations).
+ * for the clone's id). The new clone is given the name newName. Finally,
+ * due to efficiency considerations, if purgeId is non-zero, we purge that
+ * volume when doing the clone operation. This may be useful when making
+ * new backup volumes, for instance since the net result of a clone and a
+ * purge generally leaves many inode ref counts the same, while doing them
+ * separately would result in far more iincs and idecs being peformed
+ * (and they are slow operations).
*/
/* for efficiency reasons, sometimes faster to piggyback a purge here */
afs_int32
-SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
- afs_int32 newType, char *newName, afs_int32 *newNumber)
+SAFSVolClone(struct rx_call *acid, afs_int32 atrans, VolumeId purgeId,
+ afs_int32 newType, char *newName, VolumeId *newNumber)
{
afs_int32 code;
-
code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
return code;
}
-afs_int32
-VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
- afs_int32 newType, char *newName, afs_int32 *newNumber)
+static afs_int32
+VolClone(struct rx_call *acid, afs_int32 atrans, VolumeId purgeId,
+ afs_int32 newType, char *newName, VolumeId *newNumber)
{
VolumeId newId;
- register struct Volume *originalvp, *purgevp, *newvp;
+ struct Volume *originalvp, *purgevp, *newvp;
Error error, code;
- register struct volser_trans *tt, *ttc;
+ struct volser_trans *tt, *ttc;
char caller[MAXKTCNAMELEN];
+#ifdef AFS_DEMAND_ATTACH_FS
+ struct Volume *salv_vp = NULL;
+#endif
if (strlen(newName) > 31)
return VOLSERBADNAME;
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS; /*not a super user */
- if (DoLogging)
- Log("%s is executing Clone Volume new name=%s\n", caller, newName);
+ if (DoLogging) {
+ char buffer[16];
+ Log("%s on %s is executing Clone Volume new name=%s\n", caller,
+ callerAddress(acid, buffer), newName);
+ }
error = 0;
- originalvp = (Volume *) 0;
purgevp = (Volume *) 0;
newvp = (Volume *) 0;
tt = ttc = (struct volser_trans *)0;
}
newId = *newNumber;
- if (newType != readonlyVolume && newType != backupVolume)
- return EINVAL;
tt = FindTrans(atrans);
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: Clone: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
ttc = NewTrans(newId, tt->partition);
if (!ttc) { /* someone is messing with the clone already */
TRELE(tt);
- return VBUSY;
+ return VOLSERVOLBUSY;
}
- strcpy(tt->lastProcName, "Clone");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "Clone");
if (purgeId) {
- purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
+ purgevp = VAttachVolume_retry(&error, purgeId, V_VOLUPD);
if (error) {
- Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
+ Log("1 Volser: Clone: Could not attach 'purge' volume %" AFS_VOLID_FMT "; clone aborted\n", afs_printable_VolumeId_lu(purgeId));
goto fail;
}
} else {
purgevp = NULL;
}
originalvp = tt->volume;
- if ((V_type(originalvp) == backupVolume)
- || (V_type(originalvp) == readonlyVolume)) {
- Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
- error = EROFS;
- goto fail;
- }
if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
- Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
- V_id(originalvp));
+ Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT " is offline and cannot be cloned\n",
+ afs_printable_VolumeId_lu(V_id(originalvp)));
error = VOFFLINE;
goto fail;
}
if (purgevp) {
if (originalvp->device != purgevp->device) {
- Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
+ 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));
error = EXDEV;
goto fail;
}
error = EINVAL;
goto fail;
}
- if (V_type(originalvp) == readonlyVolume
- && V_parentId(originalvp) != V_parentId(purgevp)) {
- Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
- error = EXDEV;
- goto fail;
- }
- if (V_type(originalvp) == readwriteVolume
- && tt->volid != V_parentId(purgevp)) {
- Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
+ if (V_parentId(originalvp) != V_parentId(purgevp)) {
+ 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));
error = EXDEV;
goto fail;
}
}
error = 0;
+#ifdef AFS_DEMAND_ATTACH_FS
+ salv_vp = originalvp;
+#endif
- newvp =
- VCreateVolume(&error, originalvp->partition->name, newId,
- V_parentId(originalvp));
- if (error) {
- Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
- newvp = (Volume *) 0;
- goto fail;
+ if (purgeId == newId) {
+ newvp = purgevp;
+ } else {
+ newvp =
+ VCreateVolume(&error, originalvp->partition->name, newId,
+ V_parentId(originalvp));
+ if (error) {
+ Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
+ newvp = (Volume *) 0;
+ goto fail;
+ }
}
if (newType == readonlyVolume)
V_cloneId(originalvp) = newId;
- Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
- newId);
+ Log("1 Volser: Clone: Cloning volume %" AFS_VOLID_FMT " to new volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(tt->volid),
+ afs_printable_VolumeId_lu(newId));
if (purgevp)
- Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
+ Log("1 Volser: Clone: Purging old read only volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(purgeId));
CloneVolume(&error, originalvp, newvp, purgevp);
purgevp = NULL; /* clone releases it, maybe even if error */
if (error) {
V_type(newvp) = backupVolume;
V_backupId(originalvp) = newId;
}
- strcpy(newvp->header->diskstuff.name, newName);
+ strcpy(V_name(newvp), newName);
V_creationDate(newvp) = V_copyDate(newvp);
ClearVolumeStats(&V_disk(newvp));
V_destroyMe(newvp) = DESTROY_ME;
LogError(error);
goto fail;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
+#ifdef AFS_DEMAND_ATTACH_FS
+ salv_vp = NULL;
+#endif
if (TRELE(tt)) {
tt = (struct volser_trans *)0;
error = VOLSERTRELE_ERROR;
goto fail;
}
- DeleteTrans(ttc);
+ DeleteTrans(ttc, 1);
return 0;
fail:
if (newvp)
VDetachVolume(&code, newvp);
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
}
if (ttc)
- DeleteTrans(ttc);
+ DeleteTrans(ttc, 1);
+#ifdef AFS_DEMAND_ATTACH_FS
+ if (salv_vp && error != VVOLEXISTS && error != EXDEV) {
+ V_needsSalvaged(salv_vp) = 1;
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
return error;
}
/* reclone this volume into the specified id */
afs_int32
-SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
+SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, VolumeId cloneId)
{
afs_int32 code;
return code;
}
-afs_int32
-VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
+static afs_int32
+VolReClone(struct rx_call *acid, afs_int32 atrans, VolumeId cloneId)
{
- register struct Volume *originalvp, *clonevp;
+ struct Volume *originalvp, *clonevp;
Error error, code;
afs_int32 newType;
- register struct volser_trans *tt, *ttc;
+ struct volser_trans *tt, *ttc;
char caller[MAXKTCNAMELEN];
+ VolumeDiskData saved_header;
/*not a super user */
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS;
- if (DoLogging)
- Log("%s is executing Reclone Volume %u\n", caller, cloneId);
+ if (DoLogging) {
+ char buffer[16];
+ Log("%s on %s is executing Reclone Volume %" AFS_VOLID_FMT "\n", caller,
+ callerAddress(acid, buffer), afs_printable_VolumeId_lu(cloneId));
+ }
error = 0;
clonevp = originalvp = (Volume *) 0;
- tt = (struct volser_trans *)0;
tt = FindTrans(atrans);
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolReClone: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
ttc = NewTrans(cloneId, tt->partition);
if (!ttc) { /* someone is messing with the clone already */
TRELE(tt);
- return VBUSY;
+ return VOLSERVOLBUSY;
}
- strcpy(tt->lastProcName, "ReClone");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "ReClone");
originalvp = tt->volume;
- if ((V_type(originalvp) == backupVolume)
- || (V_type(originalvp) == readonlyVolume)) {
- Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
- error = EROFS;
- goto fail;
- }
if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
- Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
- V_id(originalvp));
+ Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT " is offline and cannot be cloned\n",
+ afs_printable_VolumeId_lu(V_id(originalvp)));
error = VOFFLINE;
goto fail;
}
- clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
+ clonevp = VAttachVolume_retry(&error, cloneId, V_VOLUPD);
if (error) {
- Log("1 Volser: can't attach clone %d\n", cloneId);
+ Log("1 Volser: can't attach clone %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(cloneId));
goto fail;
}
newType = V_type(clonevp); /* type of the new volume */
if (originalvp->device != clonevp->device) {
- Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
- tt->volid, cloneId);
+ 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(cloneId));
error = EXDEV;
goto fail;
}
- if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
- Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
- error = EINVAL;
- goto fail;
- }
- if (V_type(originalvp) == readonlyVolume
- && V_parentId(originalvp) != V_parentId(clonevp)) {
- Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
+ if (V_parentId(originalvp) != V_parentId(clonevp)) {
+ 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));
error = EXDEV;
goto fail;
}
- if (V_type(originalvp) == readwriteVolume
- && tt->volid != V_parentId(clonevp)) {
- Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
- error = EXDEV;
- goto fail;
+
+ if (DoPreserveVolumeStats) {
+ CopyVolumeStats(&V_disk(clonevp), &saved_header);
}
error = 0;
- Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
- cloneId);
+ Log("1 Volser: Clone: Recloning volume %" AFS_VOLID_FMT " to volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(tt->volid),
+ afs_printable_VolumeId_lu(cloneId));
CloneVolume(&error, originalvp, clonevp, clonevp);
if (error) {
Log("1 Volser: Clone: reclone operation failed with code %d\n",
}
/* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
- /* pretend recloned volume is a totally new instance */
- V_copyDate(clonevp) = time(0);
- V_creationDate(clonevp) = V_copyDate(clonevp);
- ClearVolumeStats(&V_disk(clonevp));
+ /* update the creationDate, since this represents the last cloning date
+ * for ROs. But do not update copyDate; let it stay so we can identify
+ * when the clone was first created. */
+ V_creationDate(clonevp) = time(0);
+ if (DoPreserveVolumeStats) {
+ CopyVolumeStats(&saved_header, &V_disk(clonevp));
+ } else {
+ ClearVolumeStats(&V_disk(clonevp));
+ }
V_destroyMe(clonevp) = 0;
V_inService(clonevp) = 0;
if (newType == backupVolume) {
- V_backupDate(originalvp) = V_copyDate(clonevp);
- V_backupDate(clonevp) = V_copyDate(clonevp);
+ V_backupDate(originalvp) = V_creationDate(clonevp);
+ V_backupDate(clonevp) = V_creationDate(clonevp);
}
V_inUse(clonevp) = 0;
VUpdateVolume(&error, clonevp);
LogError(error);
goto fail;
}
+ /* VUpdateVolume succeeded. Mark it in service so there's no window
+ * between FSYNC_VOL_ON and VolSetFlags where it's offline with no
+ * specialStatus; this is a reclone and this volume started online
+ */
+ V_inService(clonevp) = 1;
VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
clonevp = NULL;
VUpdateVolume(&error, originalvp);
LogError(error);
goto fail;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt)) {
tt = (struct volser_trans *)0;
error = VOLSERTRELE_ERROR;
goto fail;
}
- DeleteTrans(ttc);
+ DeleteTrans(ttc, 1);
{
- struct DiskPartition *tpartp = originalvp->partition;
- FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
+ struct DiskPartition64 *tpartp = originalvp->partition;
+ FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
}
return 0;
if (clonevp)
VDetachVolume(&code, clonevp);
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
}
if (ttc)
- DeleteTrans(ttc);
+ DeleteTrans(ttc, 1);
return error;
}
* See volser.h for definition of iflags (the constants are named IT*).
*/
afs_int32
-SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
+SAFSVolTransCreate(struct rx_call *acid, VolumeId volume, afs_int32 partition,
afs_int32 iflags, afs_int32 *ttid)
{
afs_int32 code;
return code;
}
-afs_int32
-VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
+static afs_int32
+VolTransCreate(struct rx_call *acid, VolumeId volume, afs_int32 partition,
afs_int32 iflags, afs_int32 *ttid)
{
- register struct volser_trans *tt;
- register Volume *tv;
- afs_int32 error, code;
+ struct volser_trans *tt;
+ Volume *tv;
+ afs_int32 error;
+ Error code;
afs_int32 mode;
char caller[MAXKTCNAMELEN];
/* give up */
if (tv)
VDetachVolume(&code, tv);
- DeleteTrans(tt);
+ DeleteTrans(tt, 1);
return error;
}
+ VTRANS_OBJ_LOCK(tt);
tt->volume = tv;
*ttid = tt->tid;
tt->iflags = iflags;
tt->vflags = 0;
- strcpy(tt->lastProcName, "TransCreate");
+ TSetRxCall_r(tt, NULL, "TransCreate");
+ VTRANS_OBJ_UNLOCK(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
* Both the volume number and partition number (one-based) are returned.
*/
afs_int32
-SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
+SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, VolumeId *avolume,
afs_int32 *apart)
{
afs_int32 code;
return code;
}
-afs_int32
-VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
+static afs_int32
+VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
afs_int32 *apart)
{
Log("1 Volser: GetNthVolume: Not yet implemented\n");
return code;
}
-afs_int32
+static afs_int32
VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
{
- register struct volser_trans *tt;
+ struct volser_trans *tt;
tt = FindTrans(atid);
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
- tt->volid);
+ Log("1 Volser: VolGetFlags: volume %" AFS_VOLID_FMT " has been deleted \n",
+ afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "GetFlags");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "GetFlags");
*aflags = tt->vflags;
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
return code;
}
-afs_int32
+static afs_int32
VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
{
- register struct volser_trans *tt;
- register struct Volume *vp;
- afs_int32 error;
+ struct volser_trans *tt;
+ struct Volume *vp;
+ Error error;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
- tt->volid);
+ Log("1 Volser: VolSetFlags: volume %" AFS_VOLID_FMT " has been deleted \n",
+ afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetFlags");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "SetFlags");
vp = tt->volume; /* pull volume out of transaction */
/* check if we're allowed to make any updates */
V_inService(vp) = 1;
}
VUpdateVolume(&error, vp);
+ VTRANS_OBJ_LOCK(tt);
tt->vflags = aflags;
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall_r(tt);
+ VTRANS_OBJ_UNLOCK(tt);
if (TRELE(tt) && !error)
return VOLSERTRELE_ERROR;
*/
afs_int32
SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
- struct destServer *destination, afs_int32 destTrans,
+ struct destServer *destination, afs_int32 destTrans,
struct restoreCookie *cookie)
{
afs_int32 code;
code =
VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
- destination->destHost, AUD_LONG, destTrans, AUD_END);
+ htonl(destination->destHost), AUD_LONG, destTrans, AUD_END);
return code;
}
-afs_int32
+static afs_int32
VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
- struct destServer *destination, afs_int32 destTrans,
+ struct destServer *destination, afs_int32 destTrans,
struct restoreCookie *cookie)
{
- register struct volser_trans *tt;
- register afs_int32 code;
- register struct rx_connection *tcon;
+ struct volser_trans *tt;
+ afs_int32 code;
+ struct rx_connection *tcon;
struct rx_call *tcall;
- register struct Volume *vp;
+ struct Volume *vp;
struct rx_securityClass *securityObject;
afs_int32 securityIndex;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS; /*not a super user */
- /* initialize things */
- tcon = (struct rx_connection *)0;
- tt = (struct volser_trans *)0;
/* find the local transaction */
tt = FindTrans(fromTrans);
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolForward: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
vp = tt->volume;
- strcpy(tt->lastProcName, "Forward");
+ TSetRxCall(tt, NULL, "Forward");
/* get auth info for the this connection (uses afs from ticket file) */
code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
htons(destination->destPort), VOLSERVICE_ID,
securityObject, securityIndex);
if (!tcon) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
return ENOTCONN;
}
tcall = rx_NewCall(tcon);
- tt->rxCallPtr = tcall;
+ TSetRxCall(tt, tcall, "Forward");
/* start restore going. fromdate == 0 --> doing an incremental dump/restore */
code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
if (code) {
if (code)
goto fail;
EndAFSVolRestore(tcall); /* probably doesn't do much */
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
code = rx_EndCall(tcall, 0);
rx_DestroyConnection(tcon); /* done with the connection */
tcon = NULL;
rx_DestroyConnection(tcon);
}
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
}
return code;
/* Start a dump and send it to multiple places simultaneously.
* If this returns an error (eg, return ENOENT), it means that
- * none of the releases worked. If this returns 0, that means
+ * none of the releases worked. If this returns 0, that means
* that one or more of the releases worked, and the caller has
* to examine the results array to see which one(s).
* This will only do EITHER incremental or full, not both, so it's
* the caller's responsibility to be sure that all the destinations
- * need just an incremental (and from the same time), if that's
- * what we're doing.
+ * need just an incremental (and from the same time), if that's
+ * what we're doing.
*/
afs_int32
-SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
+SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
fromDate, manyDests *destinations, afs_int32 spare,
struct restoreCookie *cookie, manyResults *results)
{
struct rx_connection **tcons;
struct rx_call **tcalls;
struct Volume *vp;
- int i, nconns, is_incremental;
+ int i, is_incremental;
- if (results)
+ if (results) {
memset(results, 0, sizeof(manyResults));
+ i = results->manyResults_len = destinations->manyDests_len;
+ results->manyResults_val = codes = malloc(i * sizeof(afs_int32));
+ }
+ if (!results || !results->manyResults_val)
+ return ENOMEM;
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS; /*not a super user */
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolForward: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
vp = tt->volume;
- strcpy(tt->lastProcName, "ForwardMulti");
+ TSetRxCall(tt, NULL, "ForwardMulti");
- /* (fromDate == 0) ==> incremental dump */
+ /* (fromDate == 0) ==> full dump */
is_incremental = (fromDate ? 1 : 0);
- i = results->manyResults_len = destinations->manyDests_len;
- results->manyResults_val = codes =
- (afs_int32 *) malloc(i * sizeof(afs_int32));
- tcons =
- (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
- tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
+ tcons = malloc(i * sizeof(struct rx_connection *));
+ if (!tcons) {
+ return ENOMEM;
+ }
+ tcalls = malloc(i * sizeof(struct rx_call *));
+ if (!tcalls) {
+ free(tcons);
+ return ENOMEM;
+ }
/* get auth info for this connection (uses afs from ticket file) */
code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
}
osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
- fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
+ fromTrans, AUD_HOST, htonl(dest->server.destHost), AUD_LONG,
dest->trans, AUD_END);
}
free(tcons);
free(tcalls);
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt) && !code) /* return the first code if it's set */
return VOLSERTRELE_ERROR;
}
{
afs_int32 code;
- code = VolDump(acid, fromTrans, fromDate);
+ code = VolDump(acid, fromTrans, fromDate, 0);
osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
return code;
}
afs_int32
-VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
+SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+ afs_int32 flags)
+{
+ afs_int32 code;
+
+ code = VolDump(acid, fromTrans, fromDate, flags);
+ osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
+ return code;
+}
+
+static afs_int32
+VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+ afs_int32 flags)
{
int code = 0;
- register struct volser_trans *tt;
+ struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolDump: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "Dump");
- tt->rxCallPtr = acid;
- code = DumpVolume(acid, tt->volume, fromDate, 1); /* squirt out the volume's data, too */
+ TSetRxCall(tt, acid, "Dump");
+ code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
+ ? 0 : 1); /* squirt out the volume's data, too */
if (code) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
return code;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
return 0;
}
-/*
+/*
* Ha! No more helper process!
*/
afs_int32
-SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
+SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
struct restoreCookie *cookie)
{
afs_int32 code;
return code;
}
-afs_int32
-VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
- struct restoreCookie *cookie)
+static afs_int32
+VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
+ struct restoreCookie *cookie)
{
- register struct volser_trans *tt;
- register afs_int32 code, tcode;
+ struct volser_trans *tt;
+ afs_int32 code, tcode;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolRestore: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "Restore");
- tt->rxCallPtr = acid;
+ if (DoLogging) {
+ char buffer[16];
+ Log("%s on %s is executing Restore %" AFS_VOLID_FMT "\n", caller,
+ callerAddress(acid, buffer), afs_printable_VolumeId_lu(tt->volid));
+ }
+ TSetRxCall(tt, acid, "Restore");
DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
- FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l); /*break call backs on the
- * restored volume */
- tt->rxCallPtr = (struct rx_call *)0;
+ FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
+ TClearRxCall(tt);
tcode = TRELE(tt);
return (code ? code : tcode);
return code;
}
-afs_int32
+static afs_int32
VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
{
- register struct volser_trans *tt;
+ struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
return ENOENT;
}
*rcode = tt->returnCode;
- DeleteTrans(tt); /* this does an implicit TRELE */
+ DeleteTrans(tt, 1); /* this does an implicit TRELE */
return 0;
}
code = VolSetForwarding(acid, atid, anewsite);
osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
- anewsite, AUD_END);
+ htonl(anewsite), AUD_END);
return code;
}
-afs_int32
+static afs_int32
VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
{
- register struct volser_trans *tt;
+ struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
+ char partName[16];
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS; /*not a super user */
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
- tt->volid);
+ Log("1 Volser: VolSetForwarding: volume %" AFS_VOLID_FMT " has been deleted \n",
+ afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetForwarding");
- tt->rxCallPtr = acid;
- FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
- tt->rxCallPtr = (struct rx_call *)0;
+ TSetRxCall(tt, acid, "SetForwarding");
+ if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
+ partName[0] = '\0';
+ }
+ FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
}
afs_int32
-SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
- register struct volser_status *astatus)
+SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
+ struct volser_status *astatus)
{
afs_int32 code;
return code;
}
-afs_int32
-VolGetStatus(struct rx_call *acid, afs_int32 atrans,
- register struct volser_status *astatus)
+static afs_int32
+VolGetStatus(struct rx_call *acid, afs_int32 atrans,
+ struct volser_status *astatus)
{
- register struct Volume *tv;
- register struct VolumeDiskData *td;
+ struct Volume *tv;
+ struct VolumeDiskData *td;
struct volser_trans *tt;
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
- tt->volid);
+ Log("1 Volser: VolGetStatus: volume %" AFS_VOLID_FMT " has been deleted \n",
+ afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "GetStatus");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "GetStatus");
tv = tt->volume;
if (!tv) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
return ENOENT;
}
- td = &tv->header->diskstuff;
+ td = &(V_disk(tv));
astatus->volID = td->id;
astatus->nextUnique = td->uniquifier;
astatus->type = td->type;
astatus->expirationDate = td->expirationDate;
astatus->backupDate = td->backupDate;
astatus->copyDate = td->copyDate;
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
}
afs_int32
-SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
- register struct volintInfo *astatus)
+SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
+ struct volintInfo *astatus)
{
afs_int32 code;
return code;
}
-afs_int32
-VolSetInfo(struct rx_call *acid, afs_int32 atrans,
- register struct volintInfo *astatus)
+static afs_int32
+VolSetInfo(struct rx_call *acid, afs_int32 atrans,
+ struct volintInfo *astatus)
{
- register struct Volume *tv;
- register struct VolumeDiskData *td;
+ struct Volume *tv;
+ struct VolumeDiskData *td;
struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
- afs_int32 error;
+ Error error;
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS; /*not a super user */
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolSetInfo: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetStatus");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "SetStatus");
tv = tt->volume;
if (!tv) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
return ENOENT;
}
- td = &tv->header->diskstuff;
+ td = &(V_disk(tv));
/*
* Add more fields as necessary
*/
td->maxquota = astatus->maxquota;
if (astatus->dayUse != -1)
td->dayUse = astatus->dayUse;
+ if (astatus->creationDate != -1)
+ td->creationDate = astatus->creationDate;
+ if (astatus->updateDate != -1)
+ td->updateDate = astatus->updateDate;
+ if (astatus->spare2 != -1)
+ td->volUpdateCounter = (unsigned int)astatus->spare2;
VUpdateVolume(&error, tv);
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
return 0;
return code;
}
-afs_int32
+static afs_int32
VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
{
- register struct Volume *tv;
- register struct VolumeDiskData *td;
+ struct Volume *tv;
+ struct VolumeDiskData *td;
struct volser_trans *tt;
- register int len;
+ int len;
- *aname = NULL;
+ /* We need to at least fill it in */
+ *aname = malloc(1);
+ if (!*aname)
+ return ENOMEM;
tt = FindTrans(atrans);
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolGetName: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "GetName");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "GetName");
tv = tt->volume;
if (!tv) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
return ENOENT;
}
- td = &tv->header->diskstuff;
+ td = &(V_disk(tv));
len = strlen(td->name) + 1; /* don't forget the null */
if (len >= SIZE) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
return E2BIG;
}
- *aname = (char *)malloc(len);
+ *aname = realloc(*aname, len);
strcpy(*aname, td->name);
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
/*this is a handshake to indicate that the next call will be SAFSVolRestore
* - a noop now !*/
afs_int32
-SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
- afs_int32 parentId, afs_int32 cloneId)
+SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
+ VolumeId parentId, VolumeId cloneId)
{
return 0;
}
return code;
}
-afs_int32
+static afs_int32
VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
{
char namehead[9];
- int code;
- char i;
+ int i;
strcpy(namehead, "/vicep"); /*7 including null terminator */
namehead[7] = '\0';
for (i = 0; i < 26; i++) {
namehead[6] = i + 'a';
- if (VGetPartition(namehead, 0))
- partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
+ partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
}
return 0;
return code;
}
-afs_int32
+static afs_int32
XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
{
- struct stat rbuf, pbuf;
char namehead[9];
struct partList partList;
- struct DiskPartition *dp;
- int i, j = 0, k;
+ struct DiskPartition64 *dp;
+ int i, j = 0;
strcpy(namehead, "/vicep"); /*7 including null terminator */
/* Only report attached partitions */
for (i = 0; i < VOLMAXPARTS; i++) {
+#ifdef AFS_DEMAND_ATTACH_FS
+ dp = VGetPartitionById(i, 0);
+#else
if (i < 26) {
namehead[6] = i + 'a';
namehead[7] = '\0';
} else {
+ int k;
+
k = i - 26;
namehead[6] = 'a' + (k / 26);
namehead[7] = 'a' + (k % 26);
namehead[8] = '\0';
}
dp = VGetPartition(namehead, 0);
+#endif
if (dp)
partList.partId[j++] = i;
}
- pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
- memcpy((char *)pEntries->partEntries_val, (char *)&partList,
- j * sizeof(int));
- pEntries->partEntries_len = j;
+ if (j > 0) {
+ pEntries->partEntries_val = malloc(j * sizeof(int));
+ if (!pEntries->partEntries_val)
+ return ENOMEM;
+ memcpy(pEntries->partEntries_val, partList.partId,
+ j * sizeof(int));
+ pEntries->partEntries_len = j;
+ } else {
+ pEntries->partEntries_val = NULL;
+ pEntries->partEntries_len = 0;
+ }
return 0;
}
-/*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
-afs_int32
-ExtractVolId(char vname[])
+/*
+ * Scan a directory for possible volume headers.
+ * in: DIR *dirp -- a directory handle from opendir()
+ * out: char *volname -- set to name of directory entry
+ * afs_uint32 *volid -- set to volume ID parsed from name
+ * returns:
+ * true if volname and volid have been set to valid values
+ * false if we got to the end of the directory
+ */
+static int
+GetNextVol(DIR *dirp, char *volname, VolumeId *volid)
{
- int i;
- char name[VOLSER_MAXVOLNAME + 1];
+ struct dirent *dp;
- strcpy(name, vname);
- i = 0;
- while (name[i] == 'V' || name[i] == '0')
- i++;
+ while ((dp = readdir(dirp)) != NULL) {
+ /* could be optimized on platforms with dp->d_namlen */
+ if (dp->d_name[0] == 'V' && strlen(dp->d_name) == VHDRNAMELEN
+ && strcmp(&(dp->d_name[VFORMATDIGITS + 1]), VHDREXT) == 0) {
+ *volid = VolumeNumber(dp->d_name);
+ strcpy(volname, dp->d_name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * volint vol info structure type.
+ */
+typedef enum {
+ VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
+ VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
+} volint_info_type_t;
+
+/**
+ * handle to various on-wire vol info types.
+ */
+typedef struct {
+ volint_info_type_t volinfo_type;
+ union {
+ void * opaque;
+ volintInfo * base;
+ volintXInfo * ext;
+ } volinfo_ptr;
+} volint_info_handle_t;
+
+/**
+ * store value to a field at the appropriate location in on-wire structure.
+ */
+#define VOLINT_INFO_STORE(handle, name, val) \
+ do { \
+ if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
+ (handle)->volinfo_ptr.base->name = (val); \
+ } else { \
+ (handle)->volinfo_ptr.ext->name = (val); \
+ } \
+ } while(0)
+
+/**
+ * get pointer to appropriate offset of field in on-wire structure.
+ */
+#define VOLINT_INFO_PTR(handle, name) \
+ (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
+ &((handle)->volinfo_ptr.base->name) : \
+ &((handle)->volinfo_ptr.ext->name))
+
+/**
+ * fill in appropriate type of on-wire volume metadata structure.
+ *
+ * @param vp pointer to volume object
+ * @param handle pointer to wire format handle object
+ *
+ * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
+ * @pre handle object must have a valid pointer and enumeration value
+ *
+ * @note passing a NULL value for vp means that the fileserver doesn't
+ * know about this particular volume, thus implying it is offline.
+ *
+ * @return operation status
+ * @retval 0 success
+ * @retval 1 failure
+ */
+static int
+FillVolInfo(Volume * vp, volint_info_handle_t * handle)
+{
+ unsigned int numStatBytes, now;
+ struct VolumeDiskData *hdr = &(V_disk(vp));
+
+ /*read in the relevant info */
+ strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
+ VOLINT_INFO_STORE(handle, status, VOK); /*its ok */
+ VOLINT_INFO_STORE(handle, volid, hdr->id);
+ VOLINT_INFO_STORE(handle, type, hdr->type); /*if ro volume */
+ VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId); /*if rw volume */
+ VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
+ VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
+ VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
+ VOLINT_INFO_STORE(handle, size, hdr->diskused);
+ VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
+ VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
+ now = FT_ApproxTime();
+ if ((now - hdr->dayUseDate) > OneDay) {
+ VOLINT_INFO_STORE(handle, dayUse, 0);
+ } else {
+ VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
+ }
+ VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
+ VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
+ VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
+ VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ /*
+ * for DAFS, we "lie" about volume state --
+ * instead of returning the raw state from the disk header,
+ * we compute state based upon the fileserver's internal
+ * in-core state enumeration value reported to us via fssync,
+ * along with the blessed and inService flags from the header.
+ * -- tkeiser 11/27/2007
+ */
+
+ /* Conditions that offline status is based on:
+ volume is unattached state
+ volume state is in (one of several error states)
+ volume not in service
+ volume is not marked as blessed (not on hold)
+ volume in salvage req. state
+ volume needsSalvaged
+ next op would set volume offline
+ next op would not leave volume online (based on several conditions)
+ */
+ if (!vp ||
+ (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+ VIsErrorState(V_attachState(vp)) ||
+ !hdr->inService ||
+ !hdr->blessed ||
+ (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
+ hdr->needsSalvaged ||
+ (vp->pending_vol_op &&
+ (vp->pending_vol_op->com.command == FSYNC_VOL_OFF ||
+ !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
+ )
+ ) {
+ VOLINT_INFO_STORE(handle, inUse, 0);
+ } else {
+ VOLINT_INFO_STORE(handle, inUse, 1);
+ }
+#else
+ /* offline status based on program type, where != fileServer enum (1) is offline */
+ if (hdr->inUse == fileServer) {
+ VOLINT_INFO_STORE(handle, inUse, 1);
+ } else {
+ VOLINT_INFO_STORE(handle, inUse, 0);
+ }
+#endif
+
+
+ switch(handle->volinfo_type) {
+ /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
+ case VOLINT_INFO_TYPE_BASE:
- name[11] = '\0'; /* smash the "." */
- return (atol(&name[i]));
+#ifdef AFS_DEMAND_ATTACH_FS
+ /* see comment above where we set inUse bit */
+ if (hdr->needsSalvaged ||
+ (vp && VIsErrorState(V_attachState(vp)))) {
+ handle->volinfo_ptr.base->needsSalvaged = 1;
+ } else {
+ handle->volinfo_ptr.base->needsSalvaged = 0;
+ }
+#else
+ handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
+#endif
+ handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
+ handle->volinfo_ptr.base->spare0 = hdr->minquota;
+ handle->volinfo_ptr.base->spare1 =
+ (long)hdr->weekUse[0] +
+ (long)hdr->weekUse[1] +
+ (long)hdr->weekUse[2] +
+ (long)hdr->weekUse[3] +
+ (long)hdr->weekUse[4] +
+ (long)hdr->weekUse[5] +
+ (long)hdr->weekUse[6];
+ handle->volinfo_ptr.base->flags = 0;
+ handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
+ handle->volinfo_ptr.base->spare3 = 0;
+ break;
+
+
+ case VOLINT_INFO_TYPE_EXT:
+ numStatBytes =
+ 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
+ (4 * VOLINT_STATS_NUM_TIME_FIELDS));
+
+ /*
+ * Copy out the stat fields in a single operation.
+ */
+ if ((now - hdr->dayUseDate) > OneDay) {
+ memset(&(handle->volinfo_ptr.ext->stat_reads[0]),
+ 0, numStatBytes);
+ } else {
+ memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
+ (char *)&(hdr->stat_reads[0]),
+ numStatBytes);
+ }
+ break;
+ }
+
+ return 0;
}
-/*return the name of the next volume header in the directory associated with dirp and dp.
-*the volume id is returned in volid, and volume header name is returned in volname*/
-int
-GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
+#ifdef AFS_DEMAND_ATTACH_FS
+
+/**
+ * get struct Volume out of the fileserver.
+ *
+ * @param[in] volumeId volumeId for which we want state information
+ * @param[in] pname partition name string
+ * @param[inout] vp pointer to pointer to Volume object which
+ * will be populated (see note)
+ *
+ * @return operation status
+ * @retval 0 success
+ * @retval non-zero failure
+ *
+ * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
+ *
+ * @internal
+ */
+static int
+GetVolObject(VolumeId volumeId, char * pname, Volume ** vp)
{
- struct dirent *dp;
+ int code;
+ SYNC_response res;
+
+ res.hdr.response_len = sizeof(res.hdr);
+ res.payload.buf = *vp;
+ res.payload.len = sizeof(Volume);
+
+ code = FSYNC_VolOp(volumeId,
+ pname,
+ FSYNC_VOL_QUERY,
+ 0,
+ &res);
+
+ if (code != SYNC_OK) {
+ switch (res.hdr.reason) {
+ case FSYNC_WRONG_PART:
+ case FSYNC_UNKNOWN_VOLID:
+ *vp = NULL;
+ code = SYNC_OK;
+ break;
+ }
+ }
- dp = readdir(dirp); /*read next entry in the directory */
- if (dp) {
- if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
- *volid = ExtractVolId(dp->d_name);
- strcpy(volname, dp->d_name);
- return 0; /*return the name of the file representing a volume */
- } else {
- strcpy(volname, "");
- return 0; /*volname doesnot represent a volume */
+ return code;
+}
+
+#endif
+
+/**
+ * mode of volume list operation.
+ */
+typedef enum {
+ VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
+ VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
+} vol_info_list_mode_t;
+
+/**
+ * abstract interface to populate wire-format volume metadata structures.
+ *
+ * @param[in] partId partition id
+ * @param[in] volumeId volume id
+ * @param[in] pname partition name
+ * @param[in] volname volume file name
+ * @param[in] handle handle to on-wire volume metadata object
+ * @param[in] mode listing mode
+ *
+ * @return operation status
+ * @retval 0 success
+ * @retval -2 DESTROY_ME flag is set
+ * @retval -1 general failure; some data filled in
+ * @retval -3 couldn't create vtrans; some data filled in
+ */
+static int
+GetVolInfo(afs_uint32 partId,
+ VolumeId volumeId,
+ char * pname,
+ char * volname,
+ volint_info_handle_t * handle,
+ vol_info_list_mode_t mode)
+{
+ int code = -1;
+ Error error;
+ struct volser_trans *ttc = NULL;
+ struct Volume *fill_tv, *tv = NULL;
+#ifdef AFS_DEMAND_ATTACH_FS
+ struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
+ SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
+ SYNC_response fs_res; /* Response handle for the pending_vol_op */
+ FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
+
+ /* Set up response handle for pending_vol_op */
+ fs_res.hdr.response_len = sizeof(fs_res.hdr);
+ fs_res.payload.buf = fs_res_buf;
+ fs_res.payload.len = SYNC_PROTO_MAX_LEN;
+#endif
+
+ ttc = NewTrans(volumeId, partId);
+ if (!ttc) {
+ code = -3;
+ VOLINT_INFO_STORE(handle, status, VBUSY);
+ VOLINT_INFO_STORE(handle, volid, volumeId);
+ goto drop;
+ }
+
+ /* Get volume from volserver */
+ if (mode == VOL_INFO_LIST_MULTIPLE)
+ tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
+ else {
+#ifdef AFS_DEMAND_ATTACH_FS
+ int mode = V_PEEK;
+#else
+ int mode = V_READONLY; /* informs the fileserver to update the volume headers. */
+#endif
+ tv = VAttachVolumeByName_retry(&error, pname, volname, mode);
+ }
+
+ if (error) {
+ Log("1 Volser: GetVolInfo: Could not attach volume %" AFS_VOLID_FMT " (%s:%s) error=%d\n",
+ afs_printable_VolumeId_lu(volumeId), pname, volname, error);
+ goto drop;
+ }
+
+ /*
+ * please note that destroyMe and needsSalvaged checks used to be ordered
+ * in the opposite manner for ListVolumes and XListVolumes. I think it's
+ * more correct to check destroyMe before needsSalvaged.
+ * -- tkeiser 11/28/2007
+ */
+
+ if (V_destroyMe(tv) == DESTROY_ME) {
+ switch (mode) {
+ case VOL_INFO_LIST_MULTIPLE:
+ code = -2;
+ goto drop;
+
+ case VOL_INFO_LIST_SINGLE:
+ Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT " (%s:%s) will be destroyed on next salvage\n",
+ afs_printable_VolumeId_lu(volumeId), pname, volname);
+
+ default:
+ goto drop;
}
+ }
+
+ if (V_needsSalvaged(tv)) {
+ /*this volume will be salvaged */
+ Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT " (%s:%s) needs to be salvaged\n",
+ afs_printable_VolumeId_lu(volumeId), pname, volname);
+ }
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ /* If using DAFS, get volume from fsserver */
+ if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK || fs_tv == NULL) {
+
+ goto drop;
+ }
+
+ /* fs_tv is a shallow copy, must populate certain structures before passing along */
+ if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) {
+ /* If we if the pending vol op */
+ memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
+ fs_tv->pending_vol_op=&pending_vol_op_res;
} else {
- strcpy(volname, "EOD");
- return 0; /*end of directory */
+ fs_tv->pending_vol_op=NULL;
}
+ /* populate the header from the volserver copy */
+ fs_tv->header=tv->header;
+
+ /* When using DAFS, use the fs volume info, populated with required structures */
+ fill_tv = fs_tv;
+#else
+ /* When not using DAFS, just use the local volume info */
+ fill_tv = tv;
+#endif
+
+ /* ok, we have all the data we need; fill in the on-wire struct */
+ code = FillVolInfo(fill_tv, handle);
+
+ drop:
+ if (code == -1) {
+ VOLINT_INFO_STORE(handle, status, 0);
+ strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
+ VOLINT_INFO_STORE(handle, volid, volumeId);
+ }
+ if (tv) {
+ VDetachVolume(&error, tv);
+ tv = NULL;
+ if (error) {
+ VOLINT_INFO_STORE(handle, status, 0);
+ strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
+ Log("1 Volser: GetVolInfo: Could not detach volume %" AFS_VOLID_FMT " (%s:%s)\n",
+ afs_printable_VolumeId_lu(volumeId), pname, volname);
+ }
+ }
+ if (ttc) {
+ DeleteTrans(ttc, 1);
+ ttc = NULL;
+ }
+ return code;
}
+
/*return the header information about the <volid> */
afs_int32
-SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
- volumeId, volEntries *volumeInfo)
+SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
+ VolumeId volumeId, volEntries *volumeInfo)
{
afs_int32 code;
return code;
}
-afs_int32
-VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
- volumeId, volEntries *volumeInfo)
+static afs_int32
+VolListOneVolume(struct rx_call *acid, afs_int32 partid,
+ VolumeId volumeId, volEntries *volumeInfo)
{
- volintInfo *pntr;
- register struct Volume *tv;
- struct DiskPartition *partP;
- struct volser_trans *ttc;
+ struct DiskPartition64 *partP;
char pname[9], volname[20];
- afs_int32 error = 0;
DIR *dirp;
- afs_int32 volid;
+ VolumeId volid;
int found = 0;
- unsigned int now;
+ volint_info_handle_t handle;
+
+ volumeInfo->volEntries_val = calloc(1, sizeof(volintInfo));
+ if (!volumeInfo->volEntries_val)
+ return ENOMEM;
- volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
- pntr = volumeInfo->volEntries_val;
volumeInfo->volEntries_len = 1;
if (GetPartName(partid, pname))
return VOLSERILLEGAL_PARTITION;
dirp = opendir(VPartitionPath(partP));
if (dirp == NULL)
return VOLSERILLEGAL_PARTITION;
- strcpy(volname, "");
- ttc = (struct volser_trans *)0;
- tv = (Volume *) 0; /* volume not attached */
-
- while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
-
- if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
- GetNextVol(dirp, volname, &volid);
- continue; /*back to while loop */
- }
+ while (GetNextVol(dirp, volname, &volid)) {
if (volid == volumeId) { /*copy other things too */
found = 1;
+ break;
+ }
+ }
+
+ if (found) {
#ifndef AFS_PTHREAD_ENV
- IOMGR_Poll(); /*make sure that the client doesnot time out */
+ IOMGR_Poll(); /*make sure that the client does not time out */
#endif
- ttc = NewTrans(volid, partid);
- if (!ttc) {
- pntr->status = VBUSY;
- pntr->volid = volid;
- goto drop;
- }
- tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
- if (error) {
- pntr->status = 0; /*things are messed up */
- strcpy(pntr->name, volname);
- pntr->volid = volid;
- Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
- goto drop;
- }
- if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
- /*this volume will be salvaged */
- pntr->status = 0;
- strcpy(pntr->name, volname);
- pntr->volid = volid;
- Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
- goto drop;
- }
- if (tv->header->diskstuff.needsSalvaged) {
- /*this volume will be salvaged */
- pntr->status = 0;
- strcpy(pntr->name, volname);
- pntr->volid = volid;
- Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
- goto drop;
- }
+ handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
+ handle.volinfo_ptr.base = volumeInfo->volEntries_val;
- /*read in the relevant info */
- pntr->status = VOK; /*its ok */
- pntr->volid = tv->header->diskstuff.id;
- strcpy(pntr->name, tv->header->diskstuff.name);
- pntr->type = tv->header->diskstuff.type; /*if ro volume */
- pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
- pntr->backupID = tv->header->diskstuff.backupId;
- pntr->parentID = tv->header->diskstuff.parentId;
- pntr->copyDate = tv->header->diskstuff.copyDate;
- pntr->inUse = tv->header->diskstuff.inUse;
- pntr->size = tv->header->diskstuff.diskused;
- pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
- pntr->destroyMe = tv->header->diskstuff.destroyMe;
- pntr->maxquota = tv->header->diskstuff.maxquota;
- pntr->filecount = tv->header->diskstuff.filecount;
- now = FT_ApproxTime();
- if (now - tv->header->diskstuff.dayUseDate > OneDay)
- pntr->dayUse = 0;
- else
- pntr->dayUse = tv->header->diskstuff.dayUse;
- pntr->creationDate = tv->header->diskstuff.creationDate;
- pntr->accessDate = tv->header->diskstuff.accessDate;
- pntr->updateDate = tv->header->diskstuff.updateDate;
- pntr->backupDate = tv->header->diskstuff.backupDate;
- pntr->spare0 = tv->header->diskstuff.minquota;
- pntr->spare1 =
- (long)tv->header->diskstuff.weekUse[0] +
- (long)tv->header->diskstuff.weekUse[1] +
- (long)tv->header->diskstuff.weekUse[2] +
- (long)tv->header->diskstuff.weekUse[3] +
- (long)tv->header->diskstuff.weekUse[4] +
- (long)tv->header->diskstuff.weekUse[5] +
- (long)tv->header->diskstuff.weekUse[6];
- pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
- VDetachVolume(&error, tv); /*free the volume */
- tv = (Volume *) 0;
- if (error) {
- pntr->status = 0; /*things are messed up */
- strcpy(pntr->name, volname);
- Log("1 Volser: ListVolumes: Could not detach volume %s\n",
- volname);
- goto drop;
- }
- }
- GetNextVol(dirp, volname, &volid);
- }
- drop:
- if (tv) {
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- }
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
+ /* The return code from GetVolInfo is ignored; there is no error from
+ * it that results in the whole call being aborted. Any volume
+ * attachment failures are reported in 'status' field in the
+ * volumeInfo payload. */
+ GetVolInfo(partid,
+ volid,
+ pname,
+ volname,
+ &handle,
+ VOL_INFO_LIST_SINGLE);
}
closedir(dirp);
- if (found)
- return 0;
- else
- return ENODEV;
+ return (found) ? 0 : ENODEV;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
afs_int32
-SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
- afs_int32 a_volID, volXEntries *a_volumeXInfoP)
+SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
+ VolumeId a_volID, volXEntries *a_volumeXInfoP)
{
afs_int32 code;
return code;
}
-afs_int32
-VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
- afs_int32 a_volID, volXEntries *a_volumeXInfoP)
+static afs_int32
+VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
+ VolumeId a_volID, volXEntries *a_volumeXInfoP)
{ /*SAFSVolXListOneVolume */
- volintXInfo *xInfoP; /*Ptr to the extended vol info */
- register struct Volume *tv; /*Volume ptr */
- struct volser_trans *ttc; /*Volume transaction ptr */
- struct DiskPartition *partP; /*Ptr to partition */
+ struct DiskPartition64 *partP; /*Ptr to partition */
char pname[9], volname[20]; /*Partition, volume names */
- afs_int32 error; /*Error code */
- afs_int32 code; /*Return code */
DIR *dirp; /*Partition directory ptr */
- afs_int32 currVolID; /*Current volume ID */
+ VolumeId currVolID; /*Current volume ID */
int found = 0; /*Did we find the volume we need? */
- struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
- int numStatBytes; /*Num stat bytes to copy per volume */
- unsigned int now;
+ volint_info_handle_t handle;
/*
* Set up our pointers for action, marking our structure to hold exactly
* one entry. Also, assume we'll fail in our quest.
*/
- a_volumeXInfoP->volXEntries_val =
- (volintXInfo *) malloc(sizeof(volintXInfo));
- xInfoP = a_volumeXInfoP->volXEntries_val;
+ a_volumeXInfoP->volXEntries_val = calloc(1, sizeof(volintXInfo));
+ if (!a_volumeXInfoP->volXEntries_val)
+ return ENOMEM;
+
a_volumeXInfoP->volXEntries_len = 1;
- code = ENODEV;
/*
* If the partition name we've been given is bad, bogue out.
if (dirp == NULL)
return (VOLSERILLEGAL_PARTITION);
+
/*
* Sweep through the partition directory, looking for the desired entry.
* First, of course, figure out how many stat bytes to copy out of each
* volume.
*/
- numStatBytes =
- 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
- (4 * VOLINT_STATS_NUM_TIME_FIELDS));
- strcpy(volname, "");
- ttc = (struct volser_trans *)0; /*No transaction yet */
- tv = (Volume *) 0; /*Volume not yet attached */
-
- while (strcmp(volname, "EOD") && !found) {
- /*
- * If this is not a volume, move on to the next entry in the
- * partition's directory.
- */
- if (!strcmp(volname, "")) {
- GetNextVol(dirp, volname, &currVolID);
- continue;
- }
-
+ while (GetNextVol(dirp, volname, &currVolID)) {
if (currVolID == a_volID) {
/*
* We found the volume entry we're interested. Pull out the
* doesn't time out) and to set up a transaction on the volume.
*/
found = 1;
+ break;
+ } /*Found desired volume */
+ }
+
+ if (found) {
#ifndef AFS_PTHREAD_ENV
- IOMGR_Poll();
+ IOMGR_Poll();
#endif
- ttc = NewTrans(currVolID, a_partID);
- if (!ttc) {
- /*
- * Couldn't get a transaction on this volume; let our caller
- * know it's busy.
- */
- xInfoP->status = VBUSY;
- xInfoP->volid = currVolID;
- goto drop;
- }
-
- /*
- * Attach the volume, give up on the volume if we can't.
- */
- tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
- if (error) {
- xInfoP->status = 0; /*things are messed up */
- strcpy(xInfoP->name, volname);
- xInfoP->volid = currVolID;
- Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
- currVolID);
- goto drop;
- }
- /*
- * Also bag out on this volume if it's been marked as needing a
- * salvage or to-be-destroyed.
- */
- volDiskDataP = &(tv->header->diskstuff);
- if (volDiskDataP->destroyMe == DESTROY_ME) {
- xInfoP->status = 0;
- strcpy(xInfoP->name, volname);
- xInfoP->volid = currVolID;
- Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
- goto drop;
- }
-
- if (volDiskDataP->needsSalvaged) {
- xInfoP->status = 0;
- strcpy(xInfoP->name, volname);
- xInfoP->volid = currVolID;
- Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
- goto drop;
- }
-
- /*
- * Pull out the desired info and stuff it into the area we'll be
- * returning to our caller.
- */
- strcpy(xInfoP->name, volDiskDataP->name);
- xInfoP->volid = volDiskDataP->id;
- xInfoP->type = volDiskDataP->type;
- xInfoP->backupID = volDiskDataP->backupId;
- xInfoP->parentID = volDiskDataP->parentId;
- xInfoP->cloneID = volDiskDataP->cloneId;
- xInfoP->status = VOK;
- xInfoP->copyDate = volDiskDataP->copyDate;
- xInfoP->inUse = volDiskDataP->inUse;
- xInfoP->creationDate = volDiskDataP->creationDate;
- xInfoP->accessDate = volDiskDataP->accessDate;
- xInfoP->updateDate = volDiskDataP->updateDate;
- xInfoP->backupDate = volDiskDataP->backupDate;
- now = FT_ApproxTime();
- if (now - volDiskDataP->dayUseDate > OneDay)
- xInfoP->dayUse = 0;
- else
- xInfoP->dayUse = volDiskDataP->dayUse;
- xInfoP->filecount = volDiskDataP->filecount;
- xInfoP->maxquota = volDiskDataP->maxquota;
- xInfoP->size = volDiskDataP->diskused;
-
- /*
- * Copy out the stat fields in a single operation.
- */
- memcpy((char *)&(xInfoP->stat_reads[0]),
- (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
-
- /*
- * We're done copying. Detach the volume and iterate (at this
- * point, since we found our volume, we'll then drop out of the
- * loop).
- */
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- if (error) {
- xInfoP->status = 0;
- strcpy(xInfoP->name, volname);
- Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
- volname);
- goto drop;
- }
+ handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
+ handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
- /*
- * At this point, we're golden.
- */
- code = 0;
- } /*Found desired volume */
- GetNextVol(dirp, volname, &currVolID);
- }
-
- /*
- * Drop the transaction we have for this volume.
- */
- drop:
- if (tv) {
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- }
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
+ /* The return code from GetVolInfo is ignored; there is no error from
+ * it that results in the whole call being aborted. Any volume
+ * attachment failures are reported in 'status' field in the
+ * volumeInfo payload. */
+ GetVolInfo(a_partID,
+ a_volID,
+ pname,
+ volname,
+ &handle,
+ VOL_INFO_LIST_SINGLE);
}
/*
* return the proper value.
*/
closedir(dirp);
- return (code);
-
+ return (found) ? 0 : ENODEV;
} /*SAFSVolXListOneVolume */
-/*returns all the volumes on partition partid. If flags = 1 then all the
+/*returns all the volumes on partition partid. If flags = 1 then all the
* relevant info about the volumes is also returned */
afs_int32
-SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
+SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
volEntries *volumeInfo)
{
afs_int32 code;
return code;
}
-afs_int32
-VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
+static afs_int32
+VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
volEntries *volumeInfo)
{
volintInfo *pntr;
- register struct Volume *tv;
- struct DiskPartition *partP;
- struct volser_trans *ttc;
+ struct DiskPartition64 *partP;
afs_int32 allocSize = 1000; /*to be changed to a larger figure */
char pname[9], volname[20];
- afs_int32 error = 0;
DIR *dirp;
- afs_int32 volid;
- unsigned int now;
+ VolumeId volid;
+ int code;
+ volint_info_handle_t handle;
+
+ volumeInfo->volEntries_val = calloc(allocSize, sizeof(volintInfo));
+ if (!volumeInfo->volEntries_val)
+ return ENOMEM;
- volumeInfo->volEntries_val =
- (volintInfo *) malloc(allocSize * sizeof(volintInfo));
pntr = volumeInfo->volEntries_val;
volumeInfo->volEntries_len = 0;
if (GetPartName(partid, pname))
dirp = opendir(VPartitionPath(partP));
if (dirp == NULL)
return VOLSERILLEGAL_PARTITION;
- strcpy(volname, "");
- while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
- ttc = (struct volser_trans *)0; /* new one for each pass */
- tv = (Volume *) 0; /* volume not attached */
-
- if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
- GetNextVol(dirp, volname, &volid);
- continue; /*back to while loop */
- }
+ while (GetNextVol(dirp, volname, &volid)) {
if (flags) { /*copy other things too */
#ifndef AFS_PTHREAD_ENV
- IOMGR_Poll(); /*make sure that the client doesnot time out */
+ IOMGR_Poll(); /*make sure that the client does not time out */
#endif
- ttc = NewTrans(volid, partid);
- if (!ttc) {
- pntr->status = VBUSY;
- pntr->volid = volid;
- goto drop;
- }
- tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
- if (error) {
- pntr->status = 0; /*things are messed up */
- strcpy(pntr->name, volname);
- pntr->volid = volid;
- Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
- goto drop;
- }
- if (tv->header->diskstuff.needsSalvaged) {
- /*this volume will be salvaged */
- pntr->status = 0;
- strcpy(pntr->name, volname);
- pntr->volid = volid;
- Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
- goto drop;
- }
- if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
- /*this volume will be salvaged */
- goto drop2;
- }
- /*read in the relevant info */
- pntr->status = VOK; /*its ok */
- pntr->volid = tv->header->diskstuff.id;
- strcpy(pntr->name, tv->header->diskstuff.name);
- pntr->type = tv->header->diskstuff.type; /*if ro volume */
- pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume */
- pntr->backupID = tv->header->diskstuff.backupId;
- pntr->parentID = tv->header->diskstuff.parentId;
- pntr->copyDate = tv->header->diskstuff.copyDate;
- pntr->inUse = tv->header->diskstuff.inUse;
- pntr->size = tv->header->diskstuff.diskused;
- pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
- pntr->maxquota = tv->header->diskstuff.maxquota;
- pntr->filecount = tv->header->diskstuff.filecount;
- now = FT_ApproxTime();
- if (now - tv->header->diskstuff.dayUseDate > OneDay)
- pntr->dayUse = 0;
- else
- pntr->dayUse = tv->header->diskstuff.dayUse;
- pntr->creationDate = tv->header->diskstuff.creationDate;
- pntr->accessDate = tv->header->diskstuff.accessDate;
- pntr->updateDate = tv->header->diskstuff.updateDate;
- pntr->backupDate = tv->header->diskstuff.backupDate;
- pntr->spare0 = tv->header->diskstuff.minquota;
- pntr->spare1 =
- (long)tv->header->diskstuff.weekUse[0] +
- (long)tv->header->diskstuff.weekUse[1] +
- (long)tv->header->diskstuff.weekUse[2] +
- (long)tv->header->diskstuff.weekUse[3] +
- (long)tv->header->diskstuff.weekUse[4] +
- (long)tv->header->diskstuff.weekUse[5] +
- (long)tv->header->diskstuff.weekUse[6];
- pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
- VDetachVolume(&error, tv); /*free the volume */
- tv = (Volume *) 0;
- if (error) {
- pntr->status = 0; /*things are messed up */
- strcpy(pntr->name, volname);
- Log("1 Volser: ListVolumes: Could not detach volume %s\n",
- volname);
- goto drop;
- }
+ handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
+ handle.volinfo_ptr.base = pntr;
+
+
+ code = GetVolInfo(partid,
+ volid,
+ pname,
+ volname,
+ &handle,
+ VOL_INFO_LIST_MULTIPLE);
+ if (code == -2) /* DESTROY_ME flag set */
+ continue;
} else {
pntr->volid = volid;
/*just volids are needed */
}
- drop:
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
- }
pntr++;
volumeInfo->volEntries_len += 1;
if ((allocSize - volumeInfo->volEntries_len) < 5) {
/*running out of space, allocate more space */
allocSize = (allocSize * 3) / 2;
- pntr =
- (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
- allocSize * sizeof(volintInfo));
+ pntr = realloc(volumeInfo->volEntries_val,
+ allocSize * sizeof(volintInfo));
if (pntr == NULL) {
- if (tv) {
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- }
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
- }
closedir(dirp);
return VOLSERNO_MEMORY;
}
volumeInfo->volEntries_val = pntr; /* point to new block */
/* set pntr to the right position */
pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
-
- }
-
- drop2:
- if (tv) {
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
}
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
- }
- GetNextVol(dirp, volname, &volid);
-
}
- closedir(dirp);
- if (ttc)
- DeleteTrans(ttc);
+ closedir(dirp);
return 0;
}
return code;
}
-afs_int32
+static afs_int32
VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
afs_int32 a_flags, volXEntries *a_volumeXInfoP)
{ /*SAFSVolXListVolumes */
volintXInfo *xInfoP; /*Ptr to the extended vol info */
- register struct Volume *tv; /*Volume ptr */
- struct DiskPartition *partP; /*Ptr to partition */
- struct volser_trans *ttc; /*Volume transaction ptr */
+ struct DiskPartition64 *partP; /*Ptr to partition */
afs_int32 allocSize = 1000; /*To be changed to a larger figure */
char pname[9], volname[20]; /*Partition, volume names */
- afs_int32 error = 0; /*Return code */
DIR *dirp; /*Partition directory ptr */
- afs_int32 volid; /*Current volume ID */
- struct VolumeDiskData *volDiskDataP; /*Ptr to on-disk volume data */
- int numStatBytes; /*Num stat bytes to copy per volume */
- unsigned int now;
+ VolumeId volid; /*Current volume ID */
+ int code;
+ volint_info_handle_t handle;
/*
* Allocate a large array of extended volume info structures, then
* set it up for action.
*/
- a_volumeXInfoP->volXEntries_val =
- (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
+ a_volumeXInfoP->volXEntries_val = calloc(allocSize, sizeof(volintXInfo));
+ if (!a_volumeXInfoP->volXEntries_val)
+ return ENOMEM;
+
xInfoP = a_volumeXInfoP->volXEntries_val;
a_volumeXInfoP->volXEntries_len = 0;
dirp = opendir(VPartitionPath(partP));
if (dirp == NULL)
return (VOLSERILLEGAL_PARTITION);
-
- /*
- * Sweep through the partition directory, acting on each entry. First,
- * of course, figure out how many stat bytes to copy out of each volume.
- */
- numStatBytes =
- 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
- (4 * VOLINT_STATS_NUM_TIME_FIELDS));
- strcpy(volname, "");
- while (strcmp(volname, "EOD")) {
- ttc = (struct volser_trans *)0; /*New one for each pass */
- tv = (Volume *) 0; /*Volume not yet attached */
-
- /*
- * If this is not a volume, move on to the next entry in the
- * partition's directory.
- */
- if (!strcmp(volname, "")) {
- GetNextVol(dirp, volname, &volid);
- continue;
- }
-
+ while (GetNextVol(dirp, volname, &volid)) {
if (a_flags) {
/*
* Full info about the volume desired. Poll to make sure the
#ifndef AFS_PTHREAD_ENV
IOMGR_Poll();
#endif
- ttc = NewTrans(volid, a_partID);
- if (!ttc) {
- /*
- * Couldn't get a transaction on this volume; let our caller
- * know it's busy.
- */
- xInfoP->status = VBUSY;
- xInfoP->volid = volid;
- goto drop;
- }
-
- /*
- * Attach the volume, give up on this volume if we can't.
- */
- tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
- if (error) {
- xInfoP->status = 0; /*things are messed up */
- strcpy(xInfoP->name, volname);
- xInfoP->volid = volid;
- Log("1 Volser: XListVolumes: Could not attach volume %u\n",
- volid);
- goto drop;
- }
-
- /*
- * Also bag out on this volume if it's been marked as needing a
- * salvage or to-be-destroyed.
- */
- volDiskDataP = &(tv->header->diskstuff);
- if (volDiskDataP->needsSalvaged) {
- xInfoP->status = 0;
- strcpy(xInfoP->name, volname);
- xInfoP->volid = volid;
- Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
- goto drop;
- }
-
- if (volDiskDataP->destroyMe == DESTROY_ME)
- goto drop2;
-
- /*
- * Pull out the desired info and stuff it into the area we'll be
- * returning to our caller.
- */
- strcpy(xInfoP->name, volDiskDataP->name);
- xInfoP->volid = volDiskDataP->id;
- xInfoP->type = volDiskDataP->type;
- xInfoP->backupID = volDiskDataP->backupId;
- xInfoP->parentID = volDiskDataP->parentId;
- xInfoP->cloneID = volDiskDataP->cloneId;
- xInfoP->status = VOK;
- xInfoP->copyDate = volDiskDataP->copyDate;
- xInfoP->inUse = volDiskDataP->inUse;
- xInfoP->creationDate = volDiskDataP->creationDate;
- xInfoP->accessDate = volDiskDataP->accessDate;
- xInfoP->updateDate = volDiskDataP->updateDate;
- xInfoP->backupDate = volDiskDataP->backupDate;
- now = FT_ApproxTime();
- if (now - volDiskDataP->dayUseDate > OneDay)
- xInfoP->dayUse = 0;
- else
- xInfoP->dayUse = volDiskDataP->dayUse;
- xInfoP->filecount = volDiskDataP->filecount;
- xInfoP->maxquota = volDiskDataP->maxquota;
- xInfoP->size = volDiskDataP->diskused;
-
- /*
- * Copy out the stat fields in a single operation.
- */
- memcpy((char *)&(xInfoP->stat_reads[0]),
- (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
- /*
- * We're done copying. Detach the volume and iterate.
- */
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- if (error) {
- xInfoP->status = 0;
- strcpy(xInfoP->name, volname);
- Log("1 Volser: XListVolumes: Could not detach volume %s\n",
- volname);
- goto drop;
- }
- } /*Full contents desired */
- else
+ handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
+ handle.volinfo_ptr.ext = xInfoP;
+
+ code = GetVolInfo(a_partID,
+ volid,
+ pname,
+ volname,
+ &handle,
+ VOL_INFO_LIST_MULTIPLE);
+ if (code == -2) /* DESTROY_ME flag set */
+ continue;
+ } else {
/*
* Just volume IDs are needed.
*/
xInfoP->volid = volid;
-
- drop:
- /*
- * Drop the transaction we have for this volume.
- */
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
}
/*
/*
* Bummer, no memory. Bag it, tell our caller what went wrong.
*/
- if (tv) {
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- }
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
- }
closedir(dirp);
return (VOLSERNO_MEMORY);
}
a_volumeXInfoP->volXEntries_val +
a_volumeXInfoP->volXEntries_len;
}
- /*Need more space */
- drop2:
- /*
- * Detach our current volume and the transaction on it, then move on
- * to the next volume in the partition directory.
- */
- if (tv) {
- VDetachVolume(&error, tv);
- tv = (Volume *) 0;
- }
- if (ttc) {
- DeleteTrans(ttc);
- ttc = (struct volser_trans *)0;
- }
- GetNextVol(dirp, volname, &volid);
- } /*Sweep through the partition directory */
+ }
/*
* We've examined all entries in the partition directory. Close it,
* delete our transaction (if any), and go home happy.
*/
closedir(dirp);
- if (ttc)
- DeleteTrans(ttc);
return (0);
} /*SAFSVolXListVolumes */
return code;
}
-afs_int32
+static afs_int32
VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
{
transDebugInfo *pntr;
afs_int32 allocSize = 50;
- struct volser_trans *tt, *allTrans;
+ struct volser_trans *tt, *nt, *allTrans;
transInfo->transDebugEntries_val =
- (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
+ malloc(allocSize * sizeof(transDebugInfo));
+ if (!transInfo->transDebugEntries_val)
+ return ENOMEM;
pntr = transInfo->transDebugEntries_val;
transInfo->transDebugEntries_len = 0;
+
+ VTRANS_LOCK;
allTrans = TransList();
if (allTrans == (struct volser_trans *)0)
- return 0; /*no active transactions */
- for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
+ goto done; /*no active transactions */
+ for (tt = allTrans; tt; tt = nt) { /*copy relevant info into pntr */
+ nt = tt->next;
+ VTRANS_OBJ_LOCK(tt);
pntr->tid = tt->tid;
pntr->time = tt->time;
pntr->creationTime = tt->creationTime;
pntr->callValid = 0;
if (tt->rxCallPtr) { /*record call related info */
pntr->callValid = 1;
+#if 0
pntr->readNext = tt->rxCallPtr->rnext;
pntr->transmitNext = tt->rxCallPtr->tnext;
pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
+#endif
}
+ VTRANS_OBJ_UNLOCK(tt);
pntr++;
transInfo->transDebugEntries_len += 1;
if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
allocSize = (allocSize * 3) / 2;
- pntr =
- (transDebugInfo *) realloc((char *)transInfo->
- transDebugEntries_val,
- allocSize *
- sizeof(transDebugInfo));
+ pntr = realloc(transInfo->transDebugEntries_val,
+ allocSize * sizeof(transDebugInfo));
transInfo->transDebugEntries_val = pntr;
pntr =
transInfo->transDebugEntries_val +
}
}
+done:
+ VTRANS_UNLOCK;
return 0;
}
afs_int32
-SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
+SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
+ afs_int32 type, afs_uint32 pId, VolumeId cloneId,
+ VolumeId backupId)
{
afs_int32 code;
code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
- AUD_STR, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
+ AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
backupId, AUD_END);
return code;
}
-afs_int32
-VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
+static afs_int32
+VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
+ afs_int32 type, VolumeId pId, VolumeId cloneId,
+ VolumeId backupId)
{
struct Volume *tv;
- afs_int32 error = 0;
- register struct volser_trans *tt;
+ Error error = 0;
+ struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
if (strlen(name) > 31)
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolSetIds: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetIdsTypes");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "SetIdsTypes");
tv = tt->volume;
V_type(tv) = type;
LogError(error);
goto fail;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt) && !error)
return VOLSERTRELE_ERROR;
return error;
fail:
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt) && !error)
return VOLSERTRELE_ERROR;
return error;
return code;
}
-afs_int32
+static afs_int32
VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
{
struct Volume *tv;
- afs_int32 error = 0;
- register struct volser_trans *tt;
+ Error error = 0;
+ struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
if (!tt)
return ENOENT;
if (tt->vflags & VTDeleted) {
- Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
+ Log("1 Volser: VolSetDate: volume %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetDate");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "SetDate");
tv = tt->volume;
V_creationDate(tv) = cdate;
LogError(error);
goto fail;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt) && !error)
return VOLSERTRELE_ERROR;
return error;
fail:
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt) && !error)
return VOLSERTRELE_ERROR;
return error;
}
-#ifdef AFS_NAMEI_ENV
-/*
- * Inode number format (from namei_ops.c):
- * low 26 bits - vnode number - all 1's if volume special file.
- * next 3 bits - tag
- * next 3 bits spare (0's)
- * high 32 bits - uniquifier (regular) or type if spare
- */
-#define NAMEI_VNODEMASK 0x003ffffff
-#define NAMEI_TAGMASK 0x7
-#define NAMEI_TAGSHIFT 26
-#define NAMEI_UNIQMASK 0xffffffff
-#define NAMEI_UNIQSHIFT 32
-#define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
-#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
-#endif /* AFS_NAMEI_ENV */
-
afs_int32
SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
- afs_int32 volumeId)
+ VolumeId volumeId)
{
-#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
- DIR *dirp;
- char pname[16];
- char volname[20];
- afs_int32 error = 0;
- afs_int32 volid;
- int found = 0;
+#ifdef AFS_NT40_ENV
+ return EXDEV;
+#else
char caller[MAXKTCNAMELEN];
- char headername[16];
- char opath[256];
- char npath[256];
- struct VolumeDiskHeader h;
- int fd;
- IHandle_t *ih;
- Inode ino;
- struct DiskPartition *dp;
+ DIR *dirp;
+ struct volser_trans *ttc;
+ char pname[16], volname[20];
+ struct DiskPartition64 *partP;
+ afs_int32 ret = ENODEV;
+ VolumeId volid;
if (!afsconf_SuperUser(tdir, acid, caller))
return VOLSERBAD_ACCESS; /*not a super user */
if (GetPartName(partId, pname))
- return VOLSERILLEGAL_PARTITION;
- dirp = opendir(pname);
+ return VOLSERILLEGAL_PARTITION;
+ if (!(partP = VGetPartition(pname, 0)))
+ return VOLSERILLEGAL_PARTITION;
+ dirp = opendir(VPartitionPath(partP));
if (dirp == NULL)
return VOLSERILLEGAL_PARTITION;
- strcpy(volname, "");
+ ttc = (struct volser_trans *)0;
- while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
- GetNextVol(dirp, volname, &volid);
- if (strcmp(volname, "")) { /* its a volume */
- if (volid == volumeId)
- found = 1;
+ while (GetNextVol(dirp, volname, &volid)) {
+ if (volid == volumeId) { /*copy other things too */
+#ifndef AFS_PTHREAD_ENV
+ IOMGR_Poll(); /*make sure that the client doesnot time out */
+#endif
+ ttc = NewTrans(volumeId, partId);
+ if (!ttc) {
+ return VOLSERVOLBUSY;
+ }
+#ifdef AFS_NAMEI_ENV
+ ret = namei_ConvertROtoRWvolume(pname, volumeId);
+#else
+ ret = inode_ConvertROtoRWvolume(pname, volumeId);
+#endif
+ break;
}
}
- if (!found)
- return ENOENT;
- (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
- (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
- fd = open(opath, O_RDONLY);
- if (fd < 0) {
- Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
- return ENOENT;
- }
- if (read(fd, &h, sizeof(h)) != sizeof(h)) {
- Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
- close(fd);
- return EIO;
- }
- close(fd);
- FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
- for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
- dp = dp->next);
- if (!dp) {
- Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
- return EIO;
- }
- ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
- IH_INIT(ih, dp->device, h.parent, ino);
+ if (ttc)
+ DeleteTrans(ttc, 1);
- error = namei_ConvertROtoRWvolume(ih, volumeId);
- if (error)
- return error;
- h.id = h.parent;
- h.volumeInfo_hi = h.id;
- h.smallVnodeIndex_hi = h.id;
- h.largeVnodeIndex_hi = h.id;
- h.linkTable_hi = h.id;
- (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
- (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
- fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
- if (fd < 0) {
- Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
- return EIO;
- }
- if (write(fd, &h, sizeof(h)) != sizeof(h)) {
- Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
- close(fd);
- return EIO;
- }
- close(fd);
- if (unlink(opath) < 0) {
- Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
- }
- FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
- FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
- return 0;
-#else /* AFS_NAMEI_ENV */
- return EINVAL;
-#endif /* AFS_NAMEI_ENV */
+ closedir(dirp);
+ return ret;
+#endif
}
afs_int32
SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
- register struct volintSize *size)
+ struct volintSize *size)
{
int code = 0;
- register struct volser_trans *tt;
+ struct volser_trans *tt;
char caller[MAXKTCNAMELEN];
if (!afsconf_SuperUser(tdir, acid, caller))
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "GetSize");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "GetSize");
code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt))
return VOLSERTRELE_ERROR;
return code;
}
+afs_int32
+SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
+ afs_uint32 where, afs_int32 verbose)
+{
+#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
+ Error code, code2;
+ Volume *vol=0, *newvol=0;
+ struct volser_trans *tt = 0, *tt2 = 0;
+ char caller[MAXKTCNAMELEN];
+ char line[128];
+
+ if (!afsconf_SuperUser(tdir, acall, caller))
+ return EPERM;
+
+ vol = VAttachVolume(&code, vid, V_VOLUPD);
+ if (!vol) {
+ if (!code)
+ code = ENOENT;
+ return code;
+ }
+ newvol = VAttachVolume(&code, new, V_VOLUPD);
+ if (!newvol) {
+ VDetachVolume(&code2, vol);
+ if (!code)
+ code = ENOENT;
+ return code;
+ }
+ if (V_device(vol) != V_device(newvol)
+ || V_uniquifier(newvol) != 2) {
+ if (V_device(vol) != V_device(newvol)) {
+ sprintf(line, "Volumes %u and %u are not in the same partition, aborted.\n",
+ vid, new);
+ rx_Write(acall, line, strlen(line));
+ }
+ if (V_uniquifier(newvol) != 2) {
+ sprintf(line, "Volume %u is not freshly created, aborted.\n", new);
+ rx_Write(acall, line, strlen(line));
+ }
+ line[0] = 0;
+ rx_Write(acall, line, 1);
+ VDetachVolume(&code2, vol);
+ VDetachVolume(&code2, newvol);
+ return EINVAL;
+ }
+ tt = NewTrans(vid, V_device(vol));
+ if (!tt) {
+ sprintf(line, "Couldn't create transaction for %u, aborted.\n", vid);
+ rx_Write(acall, line, strlen(line));
+ line[0] = 0;
+ rx_Write(acall, line, 1);
+ VDetachVolume(&code2, vol);
+ VDetachVolume(&code2, newvol);
+ return VOLSERVOLBUSY;
+ }
+ VTRANS_OBJ_LOCK(tt);
+ tt->iflags = ITBusy;
+ tt->vflags = 0;
+ TSetRxCall_r(tt, NULL, "SplitVolume");
+ VTRANS_OBJ_UNLOCK(tt);
+
+ tt2 = NewTrans(new, V_device(newvol));
+ if (!tt2) {
+ sprintf(line, "Couldn't create transaction for %u, aborted.\n", new);
+ rx_Write(acall, line, strlen(line));
+ line[0] = 0;
+ rx_Write(acall, line, 1);
+ DeleteTrans(tt, 1);
+ VDetachVolume(&code2, vol);
+ VDetachVolume(&code2, newvol);
+ return VOLSERVOLBUSY;
+ }
+ VTRANS_OBJ_LOCK(tt2);
+ tt2->iflags = ITBusy;
+ tt2->vflags = 0;
+ TSetRxCall_r(tt2, NULL, "SplitVolume");
+ VTRANS_OBJ_UNLOCK(tt2);
+
+ code = split_volume(acall, vol, newvol, where, verbose);
+
+ VDetachVolume(&code2, vol);
+ DeleteTrans(tt, 1);
+ VDetachVolume(&code2, newvol);
+ DeleteTrans(tt2, 1);
+ return code;
+#else
+ return VOLSERBADOP;
+#endif
+}
+
/* GetPartName - map partid (a decimal number) into pname (a string)
* Since for NT we actually want to return the drive name, we map through the
* partition struct.