/*
* 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
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
+#include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
+#include <roken.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#ifdef AFS_AIX_ENV
#include <sys/statfs.h>
#endif
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#include <winsock2.h>
-#else
-#include <sys/file.h>
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
#include <lock.h>
#include <afs/voldefs.h>
#include <rx/xdr.h>
#include <rx/rx.h>
+#include <rx/rx_queue.h>
#include <afs/vlserver.h>
#include <afs/nfs.h>
#include <afs/cellconfig.h>
#include <rx/rxkad.h>
#include <afs/kautils.h>
#include <afs/cmd.h>
-#include <errno.h>
+#include <afs/ihandle.h>
+#ifdef AFS_NT40_ENV
+#include <afs/ntops.h>
+#endif
+#include <afs/vnode.h>
+#include <afs/volume.h>
#define ERRCODE_RANGE 8 /* from error_table.h */
#define CLOCKSKEW 2 /* not really skew, but resolution */
#define CLOCKADJ(x) (((x) < CLOCKSKEW) ? 0 : (x) - CLOCKSKEW)
/* for UV_MoveVolume() recovery */
-#include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
#include <setjmp.h>
-#include <volser_prototypes.h>
+#include "volser_internal.h"
+#include "volser_prototypes.h"
+#include "vsutils_prototypes.h"
+#include "lockprocs_prototypes.h"
-struct ubik_client *cstruct;
-int verbose = 0;
+extern struct ubik_client *cstruct;
+int verbose = 0, noresolve = 0;
struct release {
- afs_int32 crtime;
- afs_int32 uptime;
+ afs_uint32 crtime;
+ afs_uint32 uptime;
afs_int32 vldbEntryIndex;
};
{ if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
#define VDONE \
{ if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
+#define VEPRINT(es) \
+ { if (verbose) { fprintf(STDERR, (es)); fflush(STDERR); } }
+#define VEPRINT1(es, p) \
+ { if (verbose) { fprintf(STDERR, (es), (p)); fflush(STDERR); } }
+#define VEPRINT2(es, p1, p2) \
+ { if (verbose) { fprintf(STDERR, (es), (p1), (p2)); fflush(STDERR); } }
+#define VEPRINT3(es, p1, p2, p3) \
+ { if (verbose) { fprintf(STDERR, (es), (p1), (p2), (p3)); fflush(STDERR); } }
+#define VEDONE \
+ { if (verbose) { fprintf(STDERR, " done\n"); fflush(STDERR); } }
/* getting rid of this */
-#define ERROR_EXIT(code) {error=(code); goto error_exit;}
+#define ERROR_EXIT(code) do { \
+ error = (code); \
+ goto error_exit; \
+} while (0)
/* Protos for static routines */
+#if 0
static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
- afs_int32 apart, afs_int32 okvol,
- afs_int32 delvol);
-static int DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
- afs_int32 flags);
+ afs_int32 apart, afs_uint32 okvol,
+ afs_uint32 delvol);
+#endif
static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
struct rx_connection **connPtr, afs_int32 * transPtr,
- afs_int32 * crtimePtr, afs_int32 * uptimePtr);
+ afs_uint32 * crtimePtr, afs_uint32 * uptimePtr,
+ afs_int32 *origflags, afs_uint32 tmpVolId);
static int SimulateForwardMultiple(struct rx_connection *fromconn,
afs_int32 fromtid, afs_int32 fromdate,
manyDests * tr, afs_int32 flags,
void *cookie, manyResults * results);
-static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
+static int DoVolOnline(struct nvldbentry *vldbEntryPtr, afs_uint32 avolid,
+ int index, char *vname, struct rx_connection *connPtr);
+static int DoVolClone(struct rx_connection *aconn, afs_uint32 avolid,
+ afs_int32 apart, int type, afs_uint32 cloneid,
+ char *typestring, char *pname, char *vname, char *suffix,
+ struct volser_status *volstatus, afs_int32 *transPtr);
+static int DoVolDelete(struct rx_connection *aconn, afs_uint32 avolid,
+ afs_int32 apart, char *typestring, afs_uint32 atoserver,
+ struct volser_status *volstatus, char *pprefix);
+static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_uint32 aserver,
afs_int32 apart, afs_int32 * modentry,
- afs_uint32 * maxvolid);
+ afs_uint32 * maxvolid, struct nvldbentry *aentry);
+static afs_int32 VolumeExists(afs_uint32 server, afs_int32 partition,
+ afs_uint32 volumeid);
+static afs_int32 CheckVldbRWBK(struct nvldbentry * entry,
+ afs_int32 * modified);
+static afs_int32 CheckVldbRO(struct nvldbentry *entry, afs_int32 * modified);
+static afs_int32 CheckVldb(struct nvldbentry *entry, afs_int32 * modified,
+ afs_int32 *deleted);
+static void dump_sig_handler(int x);
+static int sortVolumes(const void *a, const void *b);
/*map the partition <partId> into partition name <partName>*/
}
int
-yesprompt(char *str)
-{
- int response, c;
- int code;
-
- fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
- response = c = getchar();
- while (!(c == EOF || c == '\n'))
- c = getchar(); /*skip to end of line */
- code = (response == 'y' || response == 'Y');
- return code;
-}
-
-
-int
PrintError(char *msg, afs_int32 errcode)
{
- fprintf(STDERR, msg);
+ fprintf(STDERR, "%s", msg);
/*replace by a big switch statement */
switch (errcode) {
case 0:
break;
default:
{
-
- afs_int32 offset;
-
- initialize_KA_error_table();
initialize_RXK_error_table();
initialize_KTC_error_table();
initialize_ACFG_error_table();
- initialize_CMD_error_table();
initialize_VL_error_table();
- offset = errcode & ((1 << ERRCODE_RANGE) - 1);
fprintf(STDERR, "%s: %s\n", afs_error_table_name(errcode),
afs_error_message(errcode));
break;
static int uvindex = -1;
/* called by VLDBClient_Init to set the security module to be used in the RPC */
int
-UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
+UV_SetSecurity(struct rx_securityClass *as, afs_int32 aindex)
{
uvindex = aindex;
uvclass = as;
/* bind to volser on <port> <aserver> */
/* takes server address in network order, port in host order. dumb */
struct rx_connection *
-UV_Bind(afs_int32 aserver, afs_int32 port)
+UV_Bind(afs_uint32 aserver, afs_int32 port)
{
- register struct rx_connection *tc;
+ struct rx_connection *tc;
tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass,
uvindex);
return tc;
}
+static int
+AFSVolCreateVolume_retry(struct rx_connection *z_conn,
+ afs_int32 partition, char *name, afs_int32 type,
+ afs_int32 parent, afs_uint32 *volid, afs_int32 *trans)
+{
+ afs_int32 code;
+ int retries = 3;
+ while (retries) {
+ code = AFSVolCreateVolume(z_conn, partition, name, type, parent,
+ volid, trans);
+ if (code != VOLSERVOLBUSY)
+ break;
+ retries--;
+#ifdef AFS_PTHREAD_ENV
+ sleep(3-retries);
+#else
+ IOMGR_Sleep(3-retries);
+#endif
+ }
+ return code;
+}
+
+static int
+AFSVolTransCreate_retry(struct rx_connection *z_conn,
+ afs_int32 volume, afs_int32 partition,
+ afs_int32 flags, afs_int32 * trans)
+{
+ afs_int32 code;
+ int retries = 3;
+ while (retries) {
+ code = AFSVolTransCreate(z_conn, volume, partition, flags, trans);
+ if (code != VOLSERVOLBUSY)
+ break;
+ retries--;
+#ifdef AFS_PTHREAD_ENV
+ sleep(3-retries);
+#else
+ IOMGR_Sleep(3-retries);
+#endif
+ }
+ return code;
+}
+
+#if 0
/* if <okvol> is allright(indicated by beibg able to
* start a transaction, delete the <delvol> */
static afs_int32
CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
- afs_int32 okvol, afs_int32 delvol)
+ afs_uint32 okvol, afs_uint32 delvol)
{
afs_int32 error, code, tid, rcode;
-
error = 0;
code = 0;
if (okvol == 0) {
- code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
+ code = AFSVolTransCreate_retry(aconn, delvol, apart, ITOffline, &tid);
if (!error && code)
error = code;
code = AFSVolDeleteVolume(aconn, tid);
error = code;
return error;
} else {
- code = AFSVolTransCreate(aconn, okvol, apart, ITOffline, &tid);
+ code = AFSVolTransCreate_retry(aconn, okvol, apart, ITOffline, &tid);
if (!code) {
code = AFSVolEndTrans(aconn, tid, &rcode);
if (!code)
code = rcode;
if (!error && code)
error = code;
- code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
+ code = AFSVolTransCreate_retry(aconn, delvol, apart, ITOffline, &tid);
if (!error && code)
error = code;
code = AFSVolDeleteVolume(aconn, tid);
}
}
+#endif
+
/* called by EmuerateEntry, show vldb entry in a reasonable format */
void
SubEnumerateEntry(struct nvldbentry *entry)
int i;
char pname[10];
int isMixed = 0;
+ char hoststr[16];
#ifdef notdef
fprintf(STDOUT, " readWriteID %-10u ", entry->volumeId[RWVOL]);
for (i = 0; i < entry->nServers; i++) {
MapPartIdIntoName(entry->serverPartition[i], pname);
fprintf(STDOUT, " server %s partition %s ",
- hostutil_GetNameByINet(entry->serverNumber[i]), pname);
+ noresolve ? afs_inet_ntoa_r(entry->serverNumber[i], hoststr) :
+ hostutil_GetNameByINet(entry->serverNumber[i]), pname);
if (entry->serverFlags[i] & ITSRWVOL)
fprintf(STDOUT, "RW Site ");
else
/* forcibly remove a volume. Very dangerous call */
int
-UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
+UV_NukeVolume(afs_uint32 server, afs_int32 partid, afs_uint32 volid)
{
- register struct rx_connection *tconn;
- register afs_int32 code;
+ struct rx_connection *tconn;
+ afs_int32 code;
tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
if (tconn) {
/* like df. Return usage of <pname> on <server> in <partition> */
int
-UV_PartitionInfo(afs_int32 server, char *pname,
- struct diskPartition *partition)
+UV_PartitionInfo64(afs_uint32 server, char *pname,
+ struct diskPartition64 *partition)
{
- register struct rx_connection *aconn;
- afs_int32 code;
+ struct rx_connection *aconn;
+ afs_int32 code = 0;
- code = 0;
- aconn = (struct rx_connection *)0;
aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
- code = AFSVolPartitionInfo(aconn, pname, partition);
+ code = AFSVolPartitionInfo64(aconn, pname, partition);
+ if (code == RXGEN_OPCODE) {
+ struct diskPartition *dpp = malloc(sizeof(struct diskPartition));
+ code = AFSVolPartitionInfo(aconn, pname, dpp);
+ if (!code) {
+ strncpy(partition->name, dpp->name, 32);
+ strncpy(partition->devName, dpp->devName, 32);
+ partition->lock_fd = dpp->lock_fd;
+ partition->free = dpp->free;
+ partition->minFree = dpp->minFree;
+ }
+ free(dpp);
+ }
if (code) {
fprintf(STDERR, "Could not get information on partition %s\n", pname);
PrintError("", code);
return code;
}
-/* old interface to create volume */
+/* old interface to create volumes */
int
-UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname,
- afs_int32 * anewid)
+UV_CreateVolume(afs_uint32 aserver, afs_int32 apart, char *aname,
+ afs_uint32 * anewid)
{
afs_int32 code;
+ *anewid = 0;
code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
return code;
}
-/* create a volume, given a server, partition number, volume name --> sends
-* back new vol id in <anewid>*/
+/* less old interface to create volumes */
int
-UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname,
+UV_CreateVolume2(afs_uint32 aserver, afs_int32 apart, char *aname,
afs_int32 aquota, afs_int32 aspare1, afs_int32 aspare2,
- afs_int32 aspare3, afs_int32 aspare4, afs_int32 * anewid)
+ afs_int32 aspare3, afs_int32 aspare4, afs_uint32 * anewid)
{
+ afs_uint32 roid = 0, bkid = 0;
+ return UV_CreateVolume3(aserver, apart, aname, aquota, aspare1, aspare2,
+ aspare3, aspare4, anewid, &roid, &bkid);
+}
- register struct rx_connection *aconn;
+/**
+ * Create a volume on the given server and partition
+ *
+ * @param aserver server to create volume on
+ * @param spart partition to create volume on
+ * @param aname name of new volume
+ * @param aquota quota for new volume
+ * @param anewid contains the desired volume id for the new volume. If
+ * *anewid == 0, a new id will be chosen, and will be placed
+ * in *anewid when UV_CreateVolume3 returns.
+ * @param aroid contains the desired RO volume id. If NULL, the RO id entry
+ * will be unset. If *aroid == 0, an id will be chosen, and
+ * will be placed in *anewid when UV_CreateVolume3 returns.
+ * @param abkid same as aroid, except for the BK volume id instead of the
+ * RO volume id.
+ * @return 0 on success, error code otherwise.
+ */
+int
+UV_CreateVolume3(afs_uint32 aserver, afs_int32 apart, char *aname,
+ afs_int32 aquota, afs_int32 aspare1, afs_int32 aspare2,
+ afs_int32 aspare3, afs_int32 aspare4, afs_uint32 * anewid,
+ afs_uint32 * aroid, afs_uint32 * abkid)
+{
+ struct rx_connection *aconn;
afs_int32 tid;
- register afs_int32 code;
+ afs_int32 code;
afs_int32 error;
afs_int32 rcode, vcode;
+ afs_int32 lastid;
struct nvldbentry entry, storeEntry; /*the new vldb entry */
struct volintInfo tstatus;
tid = 0;
- aconn = (struct rx_connection *)0;
error = 0;
init_volintInfo(&tstatus);
tstatus.maxquota = aquota;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
- /* next the next 3 available ids from the VLDB */
- vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 3, anewid);
- EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n", aname);
+
+ if (aroid && *aroid) {
+ VPRINT1("Using RO volume ID %d.\n", *aroid);
+ }
+ if (abkid && *abkid) {
+ VPRINT1("Using BK volume ID %d.\n", *abkid);
+ }
+
+ if (*anewid) {
+ vcode = VLDB_GetEntryByID(*anewid, -1, &entry);
+ if (!vcode) {
+ fprintf(STDERR, "Volume ID %d already exists\n", *anewid);
+ return VVOLEXISTS;
+ }
+ VPRINT1("Using volume ID %d.\n", *anewid);
+ } else {
+ vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, anewid);
+ EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n", aname);
+
+ if (aroid && *aroid == 0) {
+ vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, aroid);
+ EGOTO1(cfail, vcode, "Could not get an RO Id for volume %s\n", aname);
+ }
+
+ if (abkid && *abkid == 0) {
+ vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, abkid);
+ EGOTO1(cfail, vcode, "Could not get a BK Id for volume %s\n", aname);
+ }
+ }
+
+ /* rw,ro, bk id are related in the default case */
+ /* If caller specified RW id, but not RO/BK ids, have them be RW+1 and RW+2 */
+ lastid = *anewid;
+ if (aroid && *aroid != 0) {
+ lastid = max(lastid, *aroid);
+ }
+ if (abkid && *abkid != 0) {
+ lastid = max(lastid, *abkid);
+ }
+ if (aroid && *aroid == 0) {
+ *aroid = ++lastid;
+ }
+ if (abkid && *abkid == 0) {
+ *abkid = ++lastid;
+ }
code =
- AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
- EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n", aname,
+ AFSVolCreateVolume_retry(aconn, apart, aname, volser_RW, 0, anewid, &tid);
+ EGOTO2(cfail, code, "Failed to create the volume %s %u \n", aname,
*anewid);
code = AFSVolSetInfo(aconn, tid, &tstatus);
if (code)
- EPRINT(code, "Could not change quota (error %d), continuing...\n");
+ EPRINT(code, "Could not change quota, continuing...\n");
code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
- EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n", aname,
+ EGOTO2(cfail, code, "Could not bring the volume %s %u online \n", aname,
*anewid);
VPRINT2("Volume %s %u created and brought online\n", aname, *anewid);
/* set up the vldb entry for this volume */
strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
entry.nServers = 1;
- entry.serverNumber[0] = aserver; /* this should have another
+ entry.serverNumber[0] = aserver; /* this should have another
* level of indirection later */
- entry.serverPartition[0] = apart; /* this should also have
+ entry.serverPartition[0] = apart; /* this should also have
* another indirection level */
entry.flags = RW_EXISTS; /* this records that rw volume exists */
entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
entry.volumeId[RWVOL] = *anewid;
- entry.volumeId[ROVOL] = *anewid + 1; /* rw,ro, bk id are related in the default case */
- entry.volumeId[BACKVOL] = *anewid + 2;
+ entry.volumeId[ROVOL] = aroid ? *aroid : 0;
+ entry.volumeId[BACKVOL] = abkid ? *abkid : 0;
entry.cloneId = 0;
/*map into right byte order, before passing to xdr, the stuff has to be in host
* byte order. Xdr converts it into network order */
rx_DestroyConnection(aconn);
PrintError("", error);
return error;
-
-
}
/* create a volume, given a server, partition number, volume name --> sends
* back new vol id in <anewid>*/
int
-UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname,
- afs_int32 aid)
+UV_AddVLDBEntry(afs_uint32 aserver, afs_int32 apart, char *aname,
+ afs_uint32 aid)
{
- register struct rx_connection *aconn;
+ struct rx_connection *aconn;
afs_int32 error;
afs_int32 vcode;
struct nvldbentry entry, storeEntry; /*the new vldb entry */
/* set up the vldb entry for this volume */
strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
entry.nServers = 1;
- entry.serverNumber[0] = aserver; /* this should have another
+ entry.serverNumber[0] = aserver; /* this should have another
* level of indirection later */
- entry.serverPartition[0] = apart; /* this should also have
+ entry.serverPartition[0] = apart; /* this should also have
* another indirection level */
entry.flags = RW_EXISTS; /* this records that rw volume exists */
entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
}
/* Delete the volume <volid>on <aserver> <apart>
- * the physical entry gets removed from the vldb only if the ref count
+ * the physical entry gets removed from the vldb only if the ref count
* becomes zero
*/
int
-UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
+UV_DeleteVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid)
{
struct rx_connection *aconn = (struct rx_connection *)0;
afs_int32 ttid = 0;
/* Whether volume is in the VLDB or not. Delete the volume on disk */
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
- code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
+
+ code = DoVolDelete(aconn, avolid, apart, "the", 0, NULL, NULL);
if (code) {
- if (code == VNOVOL) {
+ if (code == VNOVOL)
notondisk = 1;
- } else {
- EGOTO1(error_exit, code, "Transaction on volume %u failed\n",
- avolid);
+ else {
+ error = code;
+ goto error_exit;
}
- } else {
- VPRINT1("Trying to delete the volume %u ...", avolid);
-
- code = AFSVolDeleteVolume(aconn, ttid);
- EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
-
- code = AFSVolEndTrans(aconn, ttid, &rcode);
- code = (code ? code : rcode);
- ttid = 0;
- EGOTO1(error_exit, code,
- "Could not end the transaction for the volume %u \n", avolid);
- VDONE;
}
/* Now update the VLDB entry.
else if (avolid == entry.volumeId[ROVOL]) {
/* Its a read-only volume, modify the VLDB entry. Check that the
* readonly volume is on the server/partition we asked to delete.
- * If flags does not have RO_EIXSTS set, then this may mean the RO
+ * If flags does not have RO_EIXSTS set, then this may mean the RO
* hasn't been released (and could exist in VLDB).
*/
if (!Lp_ROMatch(aserver, apart, &entry)) {
ERROR_EXIT(0);
}
- /* Delete backup if it exists */
- code =
- AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart,
- ITOffline, &ttid);
- if (!code) {
- if (verbose) {
- fprintf(STDOUT, "Trying to delete the backup volume %u ...",
- entry.volumeId[BACKVOL]);
- fflush(STDOUT);
+ if (entry.volumeId[BACKVOL]) {
+ /* Delete backup if it exists */
+ code = DoVolDelete(aconn, entry.volumeId[BACKVOL], apart,
+ "the backup", 0, NULL, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto error_exit;
}
- code = AFSVolDeleteVolume(aconn, ttid);
- EGOTO1(error_exit, code, "Could not delete the volume %u \n",
- entry.volumeId[BACKVOL]);
-
- code = AFSVolEndTrans(aconn, ttid, &rcode);
- ttid = 0;
- code = (code ? code : rcode);
- EGOTO1(error_exit, code,
- "Could not end the transaction for the volume %u \n",
- entry.volumeId[BACKVOL]);
- if (verbose)
- fprintf(STDOUT, " done\n");
}
if (verbose)
if (islocked) {
code =
ubik_VL_ReleaseLock(cstruct, 0, avolid, -1,
- (LOCKREL_OPCODE | LOCKREL_AFSID |
+ (LOCKREL_OPCODE | LOCKREL_AFSID |
LOCKREL_TIMESTAMP));
if (code) {
EPRINT1(code,
jmp_buf env;
int interrupt = 0;
-void
-sigint_handler(int x)
+static void *
+do_interrupt(void * unused)
{
- if (interrupt)
+ if (interrupt) {
+#if !defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
+ /* Avoid UNIX LWP from getting confused that our stack has suddenly
+ * changed. This will avoid some sanity checks, but until a better way
+ * is found, the only alternative is always crashing and burning on at
+ * least the stack-overflow check. */
+ lwp_cpptr->stack = NULL;
+#endif
longjmp(env, 0);
+ }
fprintf(STDOUT, "\nSIGINT handler: vos move operation in progress\n");
fprintf(STDOUT,
fflush(STDOUT);
interrupt = 1;
+ return NULL;
+}
+
+static void
+sigint_handler(int x)
+{
+#ifdef AFS_PTHREAD_ENV
+ do_interrupt(NULL);
+#else
+ IOMGR_SoftSig(do_interrupt, 0);
+#endif
(void)signal(SIGINT, sigint_handler);
+}
- return;
+static int
+DoVolDelete(struct rx_connection *aconn, afs_uint32 avolid,
+ afs_int32 apart, char *ptypestring, afs_uint32 atoserver,
+ struct volser_status *volstatus, char *pprefix)
+{
+ afs_int32 ttid = 0, code, rcode, error = 0;
+ char *prefix, *typestring;
+ int beverbose = 0;
+
+ if (pprefix)
+ prefix = pprefix;
+ else
+ prefix = "";
+
+ if (ptypestring) {
+ typestring = ptypestring;
+ beverbose = 1;
+ } else
+ typestring = "the";
+
+ if (beverbose)
+ VPRINT3("%sDeleting %s volume %u ...", prefix, typestring, avolid);
+
+ code =
+ AFSVolTransCreate_retry(aconn, avolid, apart, ITOffline, &ttid);
+
+ /* return early and quietly for VNOVOL; don't continue the attempt to delete. */
+ if (code == VNOVOL) {
+ error = code;
+ goto dfail;
+ }
+
+ EGOTO2(dfail, code, "%sFailed to start transaction on %u\n",
+ prefix, avolid);
+
+ if (volstatus) {
+ code = AFSVolGetStatus(aconn, ttid, volstatus);
+ EGOTO2(dfail, code, "%sCould not get timestamp from volume %u\n",
+ prefix, avolid);
+ }
+
+ code =
+ AFSVolSetFlags(aconn, ttid,
+ VTDeleteOnSalvage | VTOutOfService);
+
+ EGOTO2(dfail, code, "%sCould not set flags on volume %u \n",
+ prefix, avolid);
+
+ if (atoserver) {
+ VPRINT1("%sSetting volume forwarding pointer ...", prefix);
+ AFSVolSetForwarding(aconn, ttid, atoserver);
+ VDONE;
+ }
+
+ code = AFSVolDeleteVolume(aconn, ttid);
+ EGOTO2(dfail, code, "%sCould not delete volume %u\n", prefix, avolid);
+
+dfail:
+ if (ttid) {
+ code = AFSVolEndTrans(aconn, ttid, &rcode);
+ ttid = 0;
+ if (!code)
+ code = rcode;
+ if (code) {
+ fprintf(STDERR, "%sCould not end transaction on %s volume %lu \n",
+ prefix, typestring, (unsigned long)avolid);
+ if (!error)
+ error = code;
+ }
+ }
+
+ if (beverbose && !error)
+ VDONE;
+ return error;
+}
+
+static int
+DoVolClone(struct rx_connection *aconn, afs_uint32 avolid,
+ afs_int32 apart, int type, afs_uint32 cloneid,
+ char *typestring, char *pname, char *vname, char *suffix,
+ struct volser_status *volstatus, afs_int32 *transPtr)
+{
+ char cname[64];
+ afs_int32 ttid = 0, btid = 0;
+ afs_int32 code = 0, rcode = 0;
+ afs_int32 error = 0;
+ int cloneexists = 1;
+
+ /* Test to see if the clone volume exists by trying to create
+ * a transaction on the clone volume. We've assumed the clone exists.
+ */
+ code = AFSVolTransCreate_retry(aconn, cloneid, apart, ITOffline, &btid);
+ if (code) {
+ if (code != VNOVOL) {
+ EPRINT2(code, "Could not reach the %s volume %lu\n",
+ typestring, (unsigned long)cloneid);
+ error = code;
+ goto cfail;
+ }
+ cloneexists = 0; /* clone volume does not exist */
+ }
+ if (btid) {
+ code = AFSVolEndTrans(aconn, btid, &rcode);
+ btid = 0;
+ if (code || rcode) {
+ fprintf(STDERR,
+ "Could not end transaction on the previous %s volume %lu\n",
+ typestring, (unsigned long)cloneid);
+ error = (code ? code : rcode);
+ goto cfail;
+ }
+ }
+
+ /* Now go ahead and try to clone the RW volume.
+ * First start a transaction on the RW volume
+ */
+ code = AFSVolTransCreate_retry(aconn, avolid, apart, ITBusy, &ttid);
+ if (code) {
+ fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
+ (unsigned long)avolid);
+ error = code;
+ goto cfail;
+ }
+
+ /* Clone or reclone the volume, depending on whether the clone
+ * volume exists or not
+ */
+ if (cloneexists) {
+ VPRINT2("Re-cloning %s volume %u ...", typestring, cloneid);
+
+ code = AFSVolReClone(aconn, ttid, cloneid);
+ if (code) {
+ EPRINT2(code, "Could not re-clone %s volume %lu\n",
+ typestring, (unsigned long)cloneid);
+ error = code;
+ goto cfail;
+ }
+ } else {
+ VPRINT2("Creating a new %s clone %u ...", typestring, cloneid);
+
+ if (!vname) {
+ strcpy(cname, pname);
+ strcat(cname, suffix);
+ }
+
+ code = AFSVolClone(aconn, ttid, 0, type, vname?vname:cname,
+ &cloneid);
+ if (code) {
+ fprintf(STDERR, "Failed to clone the volume %lu\n",
+ (unsigned long)avolid);
+ error = code;
+ goto cfail;
+ }
+ }
+
+ VDONE;
+
+ if (volstatus) {
+ VPRINT1("Getting status of parent volume %u...", avolid);
+ code = AFSVolGetStatus(aconn, ttid, volstatus);
+ if (code) {
+ fprintf(STDERR, "Failed to get the status of the parent volume %lu\n",
+ (unsigned long)avolid);
+ error = code;
+ goto cfail;
+ }
+ VDONE;
+ }
+
+cfail:
+ if (ttid) {
+ code = AFSVolEndTrans(aconn, ttid, &rcode);
+ if (code || rcode) {
+ fprintf(STDERR, "Could not end transaction on the volume %lu\n",
+ (unsigned long)avolid);
+ if (!error)
+ error = (code ? code : rcode);
+ }
+ }
+
+ if (btid) {
+ code = AFSVolEndTrans(aconn, btid, &rcode);
+ if (code || rcode) {
+ fprintf(STDERR,
+ "Could not end transaction on the %s volume %lu\n",
+ typestring, (unsigned long)cloneid);
+ if (!error)
+ error = (code ? code : rcode);
+ }
+ }
+ return error;
}
/* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
* <atopart>. The operation is almost idempotent. The following
* flags are recognized:
- *
+ *
* RV_NOCLONE - don't use a copy clone
*/
int
-UV_MoveVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
- afs_int32 atoserver, afs_int32 atopart, int flags)
+UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
+ afs_uint32 atoserver, afs_int32 atopart, int flags)
{
- struct rx_connection *toconn, *fromconn;
- afs_int32 fromtid, totid, clonetid;
+ /* declare stuff 'volatile' that may be used from setjmp/longjmp and may
+ * be changing during the move */
+ struct rx_connection * volatile toconn;
+ struct rx_connection * volatile fromconn;
+ afs_int32 volatile fromtid;
+ afs_int32 volatile totid;
+ afs_int32 volatile clonetid;
+ afs_uint32 volatile newVol;
+ afs_uint32 volatile volid;
+ afs_uint32 volatile backupId;
+ int volatile islocked;
+ int volatile pntg;
+
char vname[64];
char *volName = 0;
char tmpName[VOLSER_MAXVOLNAME + 1];
afs_int32 rcode;
afs_int32 fromDate;
+ afs_int32 tmp;
+ afs_uint32 tmpVol;
struct restoreCookie cookie;
- register afs_int32 vcode, code;
- afs_int32 newVol, volid, backupId;
+ afs_int32 vcode, code;
struct volser_status tstatus;
struct destServer destination;
struct nvldbentry entry, storeEntry;
- int i, islocked, pntg;
+ int i;
afs_int32 error;
char in, lf; /* for test code */
int same;
+ char hoststr[16];
#ifdef ENABLE_BUGFIX_1165
volEntries volumeInfo;
char pname[10];
MapPartIdIntoName(entry.serverPartition[i], pname);
fprintf(STDERR, " server %s partition %s \n",
- hostutil_GetNameByINet(entry.serverNumber[i]),
+ noresolve ? afs_inet_ntoa_r(entry.serverNumber[i], hoststr) :
+ hostutil_GetNameByINet(entry.serverNumber[i]),
pname);
}
}
* may still be existing physically on from fileserver
*/
fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
- fromtid = 0;
pntg = 1;
- code =
- AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline,
- &fromtid);
- if (!code) { /* volume exists - delete it */
- VPRINT1("Setting flags on leftover source volume %u ...",
- afromvol);
- code =
- AFSVolSetFlags(fromconn, fromtid,
- VTDeleteOnSalvage | VTOutOfService);
- EGOTO1(mfail, code,
- "Failed to set flags on the leftover source volume %u\n",
- afromvol);
- VDONE;
-
- VPRINT1("Deleting leftover source volume %u ...", afromvol);
- code = AFSVolDeleteVolume(fromconn, fromtid);
- EGOTO1(mfail, code,
- "Failed to delete the leftover source volume %u\n",
- afromvol);
- VDONE;
-
- VPRINT1("Ending transaction on leftover source volume %u ...",
- afromvol);
- code = AFSVolEndTrans(fromconn, fromtid, &rcode);
- fromtid = 0;
- if (!code)
- code = rcode;
- EGOTO1(mfail, code,
- "Could not end the transaction for the leftover source volume %u \n",
- afromvol);
- VDONE;
+ code = DoVolDelete(fromconn, afromvol, afrompart,
+ "leftover", 0, NULL, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto mfail;
}
- /*delete the backup volume now */
- fromtid = 0;
- code =
- AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
- &fromtid);
- if (!code) { /* backup volume exists - delete it */
- VPRINT1("Setting flags on leftover backup volume %u ...",
- backupId);
- code =
- AFSVolSetFlags(fromconn, fromtid,
- VTDeleteOnSalvage | VTOutOfService);
- EGOTO1(mfail, code,
- "Failed to set flags on the backup volume %u\n", backupId);
- VDONE;
-
- VPRINT1("Deleting leftover backup volume %u ...", backupId);
- code = AFSVolDeleteVolume(fromconn, fromtid);
- EGOTO1(mfail, code,
- "Could not delete the leftover backup volume %u\n",
- backupId);
- VDONE;
-
- VPRINT1("Ending transaction on leftover backup volume %u ...",
- backupId);
- code = AFSVolEndTrans(fromconn, fromtid, &rcode);
- fromtid = 0;
- if (!code)
- code = rcode;
- EGOTO1(mfail, code,
- "Could not end the transaction for the leftover backup volume %u\n",
- backupId);
- VDONE;
+ code = DoVolDelete(fromconn, backupId, afrompart,
+ "leftover backup", 0, NULL, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto mfail;
}
fromtid = 0;
}
/* From-info matches the vldb info about volid,
- * its ok start the move operation, the backup volume
- * on the old site is deleted in the process
+ * its ok start the move operation, the backup volume
+ * on the old site is deleted in the process
*/
if (afrompart == atopart) {
same = VLDB_IsSameAddrs(afromserver, atoserver, &error);
pntg = 1;
toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
- fromtid = totid = 0; /* initialize to uncreated */
+ totid = 0; /* initialize to uncreated */
/* ***
* clone the read/write volume locally.
* ***/
VPRINT1("Starting transaction on source volume %u ...", afromvol);
- code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
+ code = AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, &tmp);
+ fromtid = tmp;
EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
afromvol);
VDONE;
/* Get a clone id */
VPRINT1("Allocating new volume id for clone of volume %u ...",
afromvol);
- newVol = 0;
- vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &newVol);
+ tmpVol = 0;
+ vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &tmpVol);
+ newVol = tmpVol;
EGOTO1(mfail, vcode,
"Could not get an ID for the clone of volume %u from the VLDB\n",
afromvol);
VPRINT1("Cloning source volume %u ...", afromvol);
strcpy(vname, "move-clone-temp");
code =
- AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &newVol);
+ AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &tmpVol);
+ newVol = tmpVol;
EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
afromvol);
VDONE;
if (!(flags & RV_NOCLONE)) {
/* All of this is to get the fromDate */
VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
+ tmp = clonetid;
code =
- AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
- &clonetid);
+ AFSVolTransCreate_retry(fromconn, newVol, afrompart, ITOffline,
+ &tmp);
+ clonetid = tmp;
EGOTO1(mfail, code,
"Failed to start a transaction on the cloned volume%u\n",
newVol);
/* create a volume on the target machine */
volid = afromvol;
- code = AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
- if (!code) {
- /* Delete the existing volume.
- * While we are deleting the volume in these steps, the transaction
- * we started against the cloned volume (clonetid above) will be
- * sitting idle. It will get cleaned up after 600 seconds
- */
- VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
- code = AFSVolDeleteVolume(toconn, totid);
- EGOTO1(mfail, code,
- "Could not delete the pre-existing volume %u on destination\n",
- volid);
- VDONE;
-
- VPRINT1
- ("Ending transaction on pre-existing volume %u on destination ...",
- volid);
- code = AFSVolEndTrans(toconn, totid, &rcode);
- totid = 0;
- if (!code)
- code = rcode;
- EGOTO1(mfail, code,
- "Could not end the transaction on pre-existing volume %u on destination\n",
- volid);
- VDONE;
- }
+ code = DoVolDelete(toconn, volid, atopart,
+ "pre-existing destination", 0, NULL, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto mfail;
+ }
VPRINT1("Creating the destination volume %u ...", volid);
+ tmp = totid;
+ tmpVol = volid;
code =
- AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &volid,
- &totid);
+ AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &tmpVol,
+ &tmp);
+ totid = tmp;
+ volid = tmpVol;
EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
volid);
VDONE;
* ***/
VPRINT1("Starting transaction on source volume %u ...", afromvol);
- code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
+ tmp = fromtid;
+ code = AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, &tmp);
+ fromtid = tmp;
EGOTO1(mfail, code,
"Failed to create a transaction on the source volume %u\n",
afromvol);
afromvol);
VDONE;
- /* Delete the backup volume on the original site */
- VPRINT1("Creating transaction for backup volume %u on source ...",
- backupId);
- code =
- AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
- VDONE;
- if (!code) {
- VPRINT1("Setting flags on backup volume %u on source ...", backupId);
- code =
- AFSVolSetFlags(fromconn, fromtid,
- VTDeleteOnSalvage | VTOutOfService);
- EGOTO1(mfail, code,
- "Failed to set the flags on the backup volume %u on the source\n",
- backupId);
- VDONE;
-
- VPRINT1("Deleting the backup volume %u on the source ...", backupId);
- code = AFSVolDeleteVolume(fromconn, fromtid);
- EGOTO1(mfail, code,
- "Failed to delete the backup volume %u on the source\n",
- backupId);
- VDONE;
+ code = DoVolDelete(fromconn, backupId, afrompart,
+ "source backup", 0, NULL, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto mfail;
+ }
- VPRINT1("Ending transaction on backup volume %u on source ...",
- backupId);
- code = AFSVolEndTrans(fromconn, fromtid, &rcode);
- fromtid = 0;
- if (!code)
- code = rcode;
- EGOTO1(mfail, code,
- "Failed to end the transaction on the backup volume %u on the source\n",
- backupId);
- VDONE;
- } else
- code = 0; /* no backup volume? that's okay */
+ code = 0; /* no backup volume? that's okay */
fromtid = 0;
if (!(flags & RV_NOCLONE)) {
- VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
- code =
- AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
- &clonetid);
- EGOTO1(mfail, code,
- "Failed to start a transaction on the cloned volume%u\n",
- newVol);
- VDONE;
-
- /* now delete the clone */
- VPRINT1("Deleting the cloned volume %u ...", newVol);
- code = AFSVolDeleteVolume(fromconn, clonetid);
- EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
- newVol);
- VDONE;
-
- VPRINT1("Ending transaction on cloned volume %u ...", newVol);
- code = AFSVolEndTrans(fromconn, clonetid, &rcode);
- if (!code)
- code = rcode;
- clonetid = 0;
- EGOTO1(mfail, code,
- "Failed to end the transaction on the cloned volume %u\n",
- newVol);
- VDONE;
+ code = DoVolDelete(fromconn, newVol, afrompart,
+ "cloned", 0, NULL, NULL);
+ if (code) {
+ if (code == VNOVOL) {
+ EPRINT1(code, "Failed to start transaction on %u\n", newVol);
+ }
+ error = code;
+ goto mfail;
+ }
}
/* fall through */
ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
(LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
VDONE;
+ islocked = 0;
}
if (clonetid) {
}
MapHostToNetwork(&entry);
- /* Delete either the volume on the source location or the target location.
+ /* Delete either the volume on the source location or the target location.
* If the vldb entry still points to the source location, then we know the
- * volume move didn't finish so we remove the volume from the target
+ * volume move didn't finish so we remove the volume from the target
* location. Otherwise, we remove the volume from the source location.
*/
if (Lp_Match(afromserver, afrompart, &entry)) { /* didn't move - delete target volume */
}
if (volid && toconn) {
- VPRINT1
- ("Recovery: Creating transaction for destination volume %u ...",
- volid);
- code =
- AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
-
- if (!code) {
- VDONE;
-
- VPRINT1
- ("Recovery: Setting flags on destination volume %u ...",
- volid);
- AFSVolSetFlags(toconn, totid,
- VTDeleteOnSalvage | VTOutOfService);
- VDONE;
-
- VPRINT1("Recovery: Deleting destination volume %u ...",
- volid);
- AFSVolDeleteVolume(toconn, totid);
- VDONE;
-
- VPRINT1
- ("Recovery: Ending transaction on destination volume %u ...",
- volid);
- AFSVolEndTrans(toconn, totid, &rcode);
- VDONE;
- } else {
- VPRINT1
- ("\nRecovery: Unable to start transaction on destination volume %u.\n",
- afromvol);
+ code = DoVolDelete(toconn, volid, atopart,
+ "destination", 0, NULL, "Recovery:");
+ if (code == VNOVOL) {
+ EPRINT1(code, "Recovery: Failed to start transaction on %u\n", volid);
}
- }
+ }
/* put source volume on-line */
if (fromconn) {
VPRINT1("Recovery: Creating transaction on source volume %u ...",
afromvol);
+ tmp = fromtid;
code =
- AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
- &fromtid);
+ AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy,
+ &tmp);
+ fromtid = tmp;
if (!code) {
VDONE;
/* delete backup volume */
if (fromconn) {
- VPRINT1("Recovery: Creating transaction on backup volume %u ...",
- backupId);
- code =
- AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
- &fromtid);
- if (!code) {
- VDONE;
-
- VPRINT1("Recovery: Setting flags on backup volume %u ...",
- backupId);
- AFSVolSetFlags(fromconn, fromtid,
- VTDeleteOnSalvage | VTOutOfService);
- VDONE;
-
- VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
- AFSVolDeleteVolume(fromconn, fromtid);
- VDONE;
-
- VPRINT1
- ("Recovery: Ending transaction on backup volume %u ...",
- backupId);
- AFSVolEndTrans(fromconn, fromtid, &rcode);
- VDONE;
- } else {
- VPRINT1
- ("\nRecovery: Unable to start transaction on backup volume %u.\n",
- backupId);
+ code = DoVolDelete(fromconn, backupId, afrompart,
+ "backup", 0, NULL, "Recovery:");
+ if (code == VNOVOL) {
+ EPRINT1(code, "Recovery: Failed to start transaction on %u\n", backupId);
}
- /* delete source volume */
- VPRINT1("Recovery: Creating transaction on source volume %u ...",
- afromvol);
- code =
- AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
- &fromtid);
- if (!code) {
- VDONE;
-
- VPRINT1("Recovery: Setting flags on backup volume %u ...",
- afromvol);
- AFSVolSetFlags(fromconn, fromtid,
- VTDeleteOnSalvage | VTOutOfService);
- VDONE;
-
- if (atoserver != afromserver) {
- VPRINT("Recovery: Setting volume forwarding pointer ...");
- AFSVolSetForwarding(fromconn, fromtid, atoserver);
- VDONE;
- }
-
- VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
- AFSVolDeleteVolume(fromconn, fromtid);
- VDONE;
-
- VPRINT1
- ("Recovery: Ending transaction on source volume %u ...",
- afromvol);
- AFSVolEndTrans(fromconn, fromtid, &rcode);
- VDONE;
- } else {
- VPRINT1
- ("\nRecovery: Unable to start transaction on source volume %u.\n",
- afromvol);
+ code = DoVolDelete(fromconn, afromvol, afrompart, "source",
+ (atoserver != afromserver)?atoserver:0,
+ NULL, NULL);
+ if (code == VNOVOL) {
+ EPRINT1(code, "Failed to start transaction on %u\n", afromvol);
}
}
}
/* common cleanup - delete local clone */
if (newVol) {
- VPRINT1("Recovery: Creating transaction on clone volume %u ...",
- newVol);
- code =
- AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
- &clonetid);
- if (!code) {
- VDONE;
-
- VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
- AFSVolDeleteVolume(fromconn, clonetid);
- VDONE;
-
- VPRINT1("Recovery: Ending transaction on clone volume %u ...",
- newVol);
- AFSVolEndTrans(fromconn, clonetid, &rcode);
- VDONE;
- } else {
- VPRINT1
- ("\nRecovery: Unable to start transaction on source volume %u.\n",
- afromvol);
+ code = DoVolDelete(fromconn, newVol, afrompart,
+ "clone", 0, NULL, "Recovery:");
+ if (code == VNOVOL) {
+ EPRINT1(code, "Recovery: Failed to start transaction on %u\n", newVol);
}
}
/* unlock VLDB entry */
- VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...",
- afromvol);
- ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
- (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
- VDONE;
-
+ if (islocked) {
+ VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...",
+ afromvol);
+ ubik_VL_ReleaseLock(cstruct, 0, afromvol, -1,
+ (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
+ VDONE;
+ }
done: /* routine cleanup */
if (volName)
free(volName);
int
-UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
- afs_int32 atoserver, afs_int32 atopart)
+UV_MoveVolume(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
+ afs_uint32 atoserver, afs_int32 atopart)
{
return UV_MoveVolume2(afromvol, afromserver, afrompart,
atoserver, atopart, 0);
* <atopart>. The new volume is named by <atovolname>. The new volume
* has ID <atovolid> if that is nonzero; otherwise a new ID is allocated
* from the VLDB. the following flags are supported:
- *
+ *
* RV_RDONLY - target volume is RO
* RV_OFFLINE - leave target volume offline
* RV_CPINCR - do incremental dump if target exists
* RV_NOCLONE - don't use a copy clone
*/
int
-UV_CopyVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
- char *atovolname, afs_int32 atoserver, afs_int32 atopart,
- afs_int32 atovolid, int flags)
+UV_CopyVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
+ char *atovolname, afs_uint32 atoserver, afs_int32 atopart,
+ afs_uint32 atovolid, int flags)
{
- struct rx_connection *toconn, *fromconn;
- afs_int32 fromtid, totid, clonetid;
+ /* declare stuff 'volatile' that may be used from setjmp/longjmp and may
+ * be changing during the copy */
+ int volatile pntg;
+ afs_int32 volatile clonetid;
+ afs_int32 volatile totid;
+ afs_int32 volatile fromtid;
+ struct rx_connection * volatile fromconn;
+ struct rx_connection * volatile toconn;
+ afs_uint32 volatile cloneVol;
+
char vname[64];
afs_int32 rcode;
afs_int32 fromDate, cloneFromDate;
struct restoreCookie cookie;
- register afs_int32 vcode, code;
- afs_int32 cloneVol, newVol, volflag;
+ afs_int32 vcode, code;
+ afs_uint32 newVol;
+ afs_int32 volflag;
struct volser_status tstatus;
struct destServer destination;
-
struct nvldbentry entry, newentry, storeEntry;
- int islocked, pntg;
afs_int32 error;
- int justclone = 0;
+ afs_int32 tmp;
+ afs_uint32 tmpVol;
- islocked = 0;
fromconn = (struct rx_connection *)0;
toconn = (struct rx_connection *)0;
fromtid = 0;
fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
fromtid = totid = 0; /* initialize to uncreated */
-
- /* check if we can shortcut and use a local clone instead of a full copy */
- if (afromserver == atoserver && afrompart == atopart) {
- justclone = 1;
- }
-
/* ***
* clone the read/write volume locally.
* ***/
cloneVol = 0;
if (!(flags & RV_NOCLONE)) {
VPRINT1("Starting transaction on source volume %u ...", afromvol);
- code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
- &fromtid);
+ tmp = fromtid;
+ code = AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy,
+ &tmp);
+ fromtid = tmp;
EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
afromvol);
VDONE;
VPRINT1("Allocating new volume id for clone of volume %u ...",
afromvol);
cloneVol = 0;
- vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &cloneVol);
+ tmpVol = cloneVol;
+ vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &tmpVol);
+ cloneVol = tmpVol;
EGOTO1(mfail, vcode,
"Could not get an ID for the clone of volume %u from the VLDB\n",
afromvol);
/* Do the clone. Default flags on clone are set to delete on salvage and out of service */
VPRINT1("Cloning source volume %u ...", afromvol);
strcpy(vname, "copy-clone-temp");
+ tmpVol = cloneVol;
code =
AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname,
- &cloneVol);
+ &tmpVol);
+ cloneVol = tmpVol;
EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
afromvol);
VDONE;
if (!(flags & RV_NOCLONE)) {
VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
+ tmp = clonetid;
code =
- AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
- &clonetid);
+ AFSVolTransCreate_retry(fromconn, cloneVol, afrompart, ITOffline,
+ &tmp);
+ clonetid = tmp;
EGOTO1(mfail, code,
"Failed to start a transaction on the cloned volume%u\n",
cloneVol);
/* create a volume on the target machine */
cloneFromDate = 0;
- code = AFSVolTransCreate(toconn, newVol, atopart, ITOffline, &totid);
+ tmp = totid;
+ code = AFSVolTransCreate_retry(toconn, newVol, atopart, ITOffline, &tmp);
+ totid = tmp;
if (!code) {
if ((flags & RV_CPINCR)) {
VPRINT1("Getting status of pre-existing volume %u ...", newVol);
}
VPRINT1("Creating the destination volume %u ...", newVol);
+ tmp = totid;
code =
AFSVolCreateVolume(toconn, atopart, atovolname,
(flags & RV_RDONLY) ? volser_RO : volser_RW,
- newVol, &newVol, &totid);
+ newVol, &newVol, &tmp);
+ totid = tmp;
EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
newVol);
VDONE;
* ***/
VPRINT1("Starting transaction on source volume %u ...", afromvol);
- code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
+ tmp = fromtid;
+ code = AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, &tmp);
+ fromtid = tmp;
EGOTO1(mfail, code,
"Failed to create a transaction on the source volume %u\n",
afromvol);
&cookie);
EGOTO1(mfail, code,
"Failed to do the%s dump from old site to new site\n",
- afromvol);
+ (flags & RV_NOCLONE) ? "" : " incremental");
VDONE;
VPRINT1("Setting volume flags on destination volume %u ...", newVol);
fromtid = 0;
if (!(flags & RV_NOCLONE)) {
- VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
- code =
- AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
- &clonetid);
- EGOTO1(mfail, code,
- "Failed to start a transaction on the cloned volume%u\n",
- cloneVol);
- VDONE;
-
- /* now delete the clone */
- VPRINT1("Deleting the cloned volume %u ...", cloneVol);
- code = AFSVolDeleteVolume(fromconn, clonetid);
- EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
- cloneVol);
- VDONE;
-
- VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
- code = AFSVolEndTrans(fromconn, clonetid, &rcode);
- if (!code)
- code = rcode;
- clonetid = 0;
- EGOTO1(mfail, code,
- "Failed to end the transaction on the cloned volume %u\n",
- cloneVol);
- VDONE;
+ code = DoVolDelete(fromconn, cloneVol, afrompart,
+ "cloned", 0, NULL, NULL);
+ if (code) {
+ if (code == VNOVOL) {
+ EPRINT1(code, "Failed to start transaction on %u\n", cloneVol);
+ }
+ error = code;
+ goto mfail;
+ }
}
if (!(flags & RV_NOVLDB)) {
/* common cleanup - delete local clone */
if (cloneVol) {
- VPRINT1("Recovery: Creating transaction on clone volume %u ...",
- cloneVol);
- code =
- AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
- &clonetid);
- if (!code) {
- VDONE;
-
- VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
- AFSVolDeleteVolume(fromconn, clonetid);
- VDONE;
-
- VPRINT1("Recovery: Ending transaction on clone volume %u ...",
- cloneVol);
- AFSVolEndTrans(fromconn, clonetid, &rcode);
- VDONE;
- } else {
- VPRINT1
- ("\nRecovery: Unable to start transaction on clone volume %u.\n",
- cloneVol);
+ code = DoVolDelete(fromconn, cloneVol, afrompart,
+ "clone", 0, NULL, "Recovery:");
+ if (code == VNOVOL) {
+ EPRINT1(code, "Recovery: Failed to start transaction on %u\n", cloneVol);
}
}
int
-UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
- char *atovolname, afs_int32 atoserver, afs_int32 atopart)
+UV_CopyVolume(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
+ char *atovolname, afs_uint32 atoserver, afs_int32 atopart)
{
return UV_CopyVolume2(afromvol, afromserver, afrompart,
atovolname, atoserver, atopart, 0, 0);
-/* Make a new backup of volume <avolid> on <aserver> and <apart>
- * if one already exists, update it
+/* Make a new backup of volume <avolid> on <aserver> and <apart>
+ * if one already exists, update it
*/
int
-UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
+UV_BackupVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid)
{
struct rx_connection *aconn = (struct rx_connection *)0;
afs_int32 ttid = 0, btid = 0;
- afs_int32 backupID;
+ afs_uint32 backupID;
afs_int32 code = 0, rcode = 0;
- char vname[VOLSER_MAXVOLNAME + 1];
struct nvldbentry entry, storeEntry;
afs_int32 error = 0;
- int vldblocked = 0, vldbmod = 0, backexists = 1;
+ int vldblocked = 0, vldbmod = 0;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
backupID = entry.volumeId[BACKVOL];
if (backupID == INVALID_BID) {
/* Get a backup volume id from the VLDB and update the vldb
- * entry with it.
+ * entry with it.
*/
code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &backupID);
if (code) {
vldbmod = 1;
}
- /* Test to see if the backup volume exists by trying to create
- * a transaction on the backup volume. We've assumed the backup exists.
- */
- code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
- if (code) {
- if (code != VNOVOL) {
- fprintf(STDERR, "Could not reach the backup volume %lu\n",
- (unsigned long)backupID);
- error = code;
- goto bfail;
- }
- backexists = 0; /* backup volume does not exist */
- }
- if (btid) {
- code = AFSVolEndTrans(aconn, btid, &rcode);
- btid = 0;
- if (code || rcode) {
- fprintf(STDERR,
- "Could not end transaction on the previous backup volume %lu\n",
- (unsigned long)backupID);
- error = (code ? code : rcode);
- goto bfail;
- }
- }
-
- /* Now go ahead and try to clone the RW volume.
- * First start a transaction on the RW volume
- */
- code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
+ code = DoVolClone(aconn, avolid, apart, backupVolume, backupID, "backup",
+ entry.name, NULL, ".backup", NULL, NULL);
if (code) {
- fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
- (unsigned long)avolid);
error = code;
goto bfail;
}
- /* Clone or reclone the volume, depending on whether the backup
- * volume exists or not
- */
- if (backexists) {
- VPRINT1("Re-cloning backup volume %u ...", backupID);
-
- code = AFSVolReClone(aconn, ttid, backupID);
- if (code) {
- fprintf(STDERR, "Could not re-clone backup volume %lu\n",
- (unsigned long)backupID);
- error = code;
- goto bfail;
- }
- } else {
- VPRINT1("Creating a new backup clone %u ...", backupID);
-
- strcpy(vname, entry.name);
- strcat(vname, ".backup");
-
- code = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID);
- if (code) {
- fprintf(STDERR, "Failed to clone the volume %lu\n",
- (unsigned long)avolid);
- error = code;
- goto bfail;
- }
- }
-
- /* End the transaction on the RW volume */
- code = AFSVolEndTrans(aconn, ttid, &rcode);
- ttid = 0;
- if (code || rcode) {
- fprintf(STDERR,
- "Failed to end the transaction on the rw volume %lu\n",
- (unsigned long)avolid);
- error = (code ? code : rcode);
- goto bfail;
- }
-
- /* Mork vldb as backup exists */
+ /* Mark vldb as backup exists */
if (!(entry.flags & BACK_EXISTS)) {
entry.flags |= BACK_EXISTS;
vldbmod = 1;
}
/* Now go back to the backup volume and bring it on line */
- code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
+ code = AFSVolTransCreate_retry(aconn, backupID, apart, ITOffline, &btid);
if (code) {
fprintf(STDERR,
"Failed to start a transaction on the backup volume %lu\n",
return error;
}
-/* Make a new clone of volume <avolid> on <aserver> and <apart>
+/* Make a new clone of volume <avolid> on <aserver> and <apart>
* using volume ID <acloneid>, or a new ID allocated from the VLDB.
* The new volume is named by <aname>, or by appending ".clone" to
* the existing name if <aname> is NULL. The following flags are
* supported:
- *
+ *
* RV_RDONLY - target volume is RO
* RV_OFFLINE - leave target volume offline
*/
int
-UV_CloneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid,
- afs_int32 acloneid, char *aname, int flags)
+UV_CloneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid,
+ afs_uint32 acloneid, char *aname, int flags)
{
struct rx_connection *aconn = (struct rx_connection *)0;
afs_int32 ttid = 0, btid = 0;
afs_int32 code = 0, rcode = 0;
char vname[VOLSER_MAXVOLNAME + 1];
afs_int32 error = 0;
- int backexists = 1;
volEntries volumeInfo;
+ int type = 0;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
VDONE;
}
- /* Test to see if the clone volume exists by trying to create
- * a transaction on the clone volume. We've assumed the clone exists.
- */
- /* XXX I wonder what happens if the clone has some other parent... */
- code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
- if (code) {
- if (code != VNOVOL) {
- fprintf(STDERR, "Could not reach the clone volume %lu\n",
- (unsigned long)acloneid);
- error = code;
- goto bfail;
- }
- backexists = 0; /* backup volume does not exist */
- }
- if (btid) {
- code = AFSVolEndTrans(aconn, btid, &rcode);
- btid = 0;
- if (code || rcode) {
- fprintf(STDERR,
- "Could not end transaction on the previous clone volume %lu\n",
- (unsigned long)acloneid);
- error = (code ? code : rcode);
- goto bfail;
- }
- }
+ if (flags & RV_RWONLY)
+ type = readwriteVolume;
+ else if (flags & RV_RDONLY)
+ type = readonlyVolume;
+ else
+ type = backupVolume;
- /* Now go ahead and try to clone the RW volume.
- * First start a transaction on the RW volume
- */
- code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
+ code = DoVolClone(aconn, avolid, apart, type, acloneid, "clone",
+ NULL, ".clone", NULL, NULL, NULL);
if (code) {
- fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
- (unsigned long)avolid);
error = code;
goto bfail;
}
- /* Clone or reclone the volume, depending on whether the backup
- * volume exists or not
- */
- if (backexists) {
- VPRINT1("Re-cloning clone volume %u ...", acloneid);
-
- code = AFSVolReClone(aconn, ttid, acloneid);
- if (code) {
- fprintf(STDERR, "Could not re-clone backup volume %lu\n",
- (unsigned long)acloneid);
- error = code;
- goto bfail;
- }
- } else {
- VPRINT1("Creating a new clone %u ...", acloneid);
-
- code = AFSVolClone(aconn, ttid, 0,
- (flags & RV_RDONLY) ? readonlyVolume : backupVolume,
- aname, &acloneid);
- if (code) {
- fprintf(STDERR, "Failed to clone the volume %lu\n",
- (unsigned long)avolid);
- error = code;
- goto bfail;
- }
- }
-
- /* End the transaction on the RW volume */
- code = AFSVolEndTrans(aconn, ttid, &rcode);
- ttid = 0;
- if (code || rcode) {
- fprintf(STDERR,
- "Failed to end the transaction on the rw volume %lu\n",
- (unsigned long)avolid);
- error = (code ? code : rcode);
- goto bfail;
- }
-
/* Now go back to the backup volume and bring it on line */
if (!(flags & RV_OFFLINE)) {
- code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
+ code = AFSVolTransCreate_retry(aconn, acloneid, apart, ITOffline, &btid);
if (code) {
fprintf(STDERR,
"Failed to start a transaction on the clone volume %lu\n",
return error;
}
-static int
-DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
- afs_int32 flags)
-{
- afs_int32 acode, ccode, rcode, tid;
- ccode = rcode = tid = 0;
-
- acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
- if (!acode) { /* It really was there */
- acode = AFSVolDeleteVolume(conn, tid);
- if (acode) {
- fprintf(STDERR, "Failed to delete volume %lu.\n",
- (unsigned long)vid);
- PrintError("", acode);
- }
- ccode = AFSVolEndTrans(conn, tid, &rcode);
- if (!ccode)
- ccode = rcode;
- if (ccode) {
- fprintf(STDERR, "Failed to end transaction on volume %lu.\n",
- (unsigned long)vid);
- PrintError("", ccode);
- }
- }
-
- return acode;
-}
-
-#define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
-#define ERROREXIT(ec) { error = (ec); goto rfail; }
+#define ONERROR(ec, ep, es) do { \
+ if (ec) { \
+ fprintf(STDERR, (es), (ep)); \
+ error = (ec); \
+ goto rfail; \
+ } \
+} while (0)
+#define ONERROR0(ec, es) do { \
+ if (ec) { \
+ fprintf(STDERR, (es)); \
+ error = (ec); \
+ goto rfail; \
+ } \
+} while (0)
+#define ERROREXIT(ec) do { \
+ error = (ec); \
+ goto rfail; \
+} while (0)
-/* Get a "transaction" on this replica. Create the volume
+/* Get a "transaction" on this replica. Create the volume
* if necessary. Return the time from which a dump should
* be made (0 if it's a new volume)
*/
static int
GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
struct rx_connection **connPtr, afs_int32 * transPtr,
- afs_int32 * crtimePtr, afs_int32 * uptimePtr)
+ afs_uint32 * crtimePtr, afs_uint32 * uptimePtr,
+ afs_int32 *origflags, afs_uint32 tmpVolId)
{
- afs_int32 volid;
+ afs_uint32 volid;
struct volser_status tstatus;
- int code, rcode, tcode;
+ int code = 0;
+ int rcode, tcode;
+ char hoststr[16];
*connPtr = (struct rx_connection *)0;
*transPtr = 0;
goto fail; /* server is down */
volid = vldbEntryPtr->volumeId[ROVOL];
- if (volid)
+
+ if (volid) {
code =
- AFSVolTransCreate(*connPtr, volid,
+ AFSVolTransCreate_retry(*connPtr, volid,
vldbEntryPtr->serverPartition[index], ITOffline,
transPtr);
+ if (!code && (origflags[index] & RO_DONTUSE)) {
+ /* If RO_DONTUSE is set, this is supposed to be an entirely new
+ * site. Don't trust any data on it, since it is possible we
+ * have encountered some temporary volume from some other
+ * incomplete volume operation. It is difficult to detect if
+ * that has happened vs if this is a legit volume, so just
+ * delete it to be safe. */
+
+ VPRINT1("Deleting extant RO_DONTUSE site on %s...",
+ noresolve ? afs_inet_ntoa_r(vldbEntryPtr->
+ serverNumber[index], hoststr) :
+ hostutil_GetNameByINet(vldbEntryPtr->
+ serverNumber[index]));
+
+ code = AFSVolDeleteVolume(*connPtr, *transPtr);
+ if (code) {
+ PrintError("Failed to delete RO_DONTUSE site: ", code);
+ goto fail;
+ }
+
+ tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
+ *transPtr = 0;
+ if (!tcode) {
+ tcode = rcode;
+ }
+ if (tcode) {
+ PrintError("Failed to end transaction on RO_DONTUSE site: ",
+ tcode);
+ goto fail;
+ }
+
+ VDONE;
+
+ /* emulate what TransCreate would have returned, so we try to
+ * create the volume below */
+ code = VNOVOL;
+ }
+ }
+
/* If the volume does not exist, create it */
if (!volid || code) {
- char volname[64];
+ char volname[VL_MAXNAMELEN];
+ char hoststr[16];
if (volid && (code != VNOVOL)) {
PrintError("Failed to start a transaction on the RO volume.\n",
goto fail;
}
- strcpy(volname, vldbEntryPtr->name);
- strcat(volname, ".readonly");
+ strlcpy(volname, vldbEntryPtr->name, sizeof(volname));
+
+ if (strlcat(volname,
+ tmpVolId?".roclone":".readonly",
+ sizeof(volname)) >= sizeof(volname)) {
+ code = ENOMEM;
+ PrintError("Volume name is too long\n", code);
+ goto fail;
+ }
+
+ if (tmpVolId)
+ strcat(volname, ".roclone");
+ else
+ strcat(volname, ".readonly");
if (verbose) {
fprintf(STDOUT,
"Creating new volume %lu on replication site %s: ",
- (unsigned long)volid,
- hostutil_GetNameByINet(vldbEntryPtr->
+ tmpVolId?(unsigned long)tmpVolId:(unsigned long)volid,
+ noresolve ? afs_inet_ntoa_r(vldbEntryPtr->
+ serverNumber[index], hoststr) :
+ hostutil_GetNameByINet(vldbEntryPtr->
serverNumber[index]));
fflush(STDOUT);
}
code =
- AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
- volname, volser_RO,
- vldbEntryPtr->volumeId[RWVOL], &volid,
- transPtr);
+ AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
+ volname, volser_RO,
+ vldbEntryPtr->volumeId[RWVOL],
+ tmpVolId?&tmpVolId:&volid,
+ transPtr);
if (code) {
PrintError("Failed to create the ro volume: ", code);
goto fail;
}
/* Otherwise, the transaction did succeed, so get the creation date of the
- * latest RO volume on the replication site
+ * latest RO volume on the replication site
*/
else {
VPRINT2("Updating existing ro volume %u on %s ...\n", volid,
- hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
+ noresolve ? afs_inet_ntoa_r(vldbEntryPtr->
+ serverNumber[index], hoststr) :
+ hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
if (code) {
code);
goto fail;
}
+ if (tmpVolId) {
+ code = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
+ *transPtr = 0;
+ if (!code)
+ code = rcode;
+ if (!code)
+ code = DoVolClone(*connPtr, volid,
+ vldbEntryPtr->serverPartition[index],
+ readonlyVolume, tmpVolId, "temporary",
+ vldbEntryPtr->name, NULL, ".roclone", NULL,
+ transPtr);
+ if (code)
+ goto fail;
+ }
*crtimePtr = CLOCKADJ(tstatus.creationDate);
*uptimePtr = CLOCKADJ(tstatus.updateDate);
}
*transPtr = 0;
if (!tcode)
tcode = rcode;
- if (tcode)
+ if (tcode && tcode != ENOENT)
PrintError("Could not end transaction on a ro volume: ", tcode);
}
afs_int32 fromdate, manyDests * tr, afs_int32 flags,
void *cookie, manyResults * results)
{
- int i;
+ unsigned int i;
for (i = 0; i < tr->manyDests_len; i++) {
results->manyResults_val[i] =
return 0;
}
+/**
+ * Check if a trans has timed out, and recreate it if necessary.
+ *
+ * @param[in] aconn RX connection to the relevant server
+ * @param[inout] atid Transaction ID to check; if we recreated the trans,
+ * contains the new trans ID on success
+ * @param[in] apart Partition for the transaction
+ * @param[in] astat The status of the original transaction
+ *
+ * @return operation status
+ * @retval 0 existing transaction is still valid, or we managed to recreate
+ * the trans successfully
+ * @retval nonzero Fatal error; bail out
+ */
+static int
+CheckTrans(struct rx_connection *aconn, afs_int32 *atid, afs_int32 apart,
+ struct volser_status *astat)
+{
+ struct volser_status new_status;
+ afs_int32 code;
+
+ memset(&new_status, 0, sizeof(new_status));
+ code = AFSVolGetStatus(aconn, *atid, &new_status);
+ if (code) {
+ if (code == ENOENT) {
+ *atid = 0;
+ VPRINT1("Old transaction on cloned volume %lu timed out, "
+ "restarting transaction\n", (long unsigned) astat->volID);
+ code = AFSVolTransCreate_retry(aconn, astat->volID, apart,
+ ITBusy, atid);
+ if (code) {
+ PrintError("Failed to recreate cloned RO volume transaction\n",
+ code);
+ return 1;
+ }
+
+ memset(&new_status, 0, sizeof(new_status));
+ code = AFSVolGetStatus(aconn, *atid, &new_status);
+ if (code) {
+ PrintError("Failed to get status on recreated transaction\n",
+ code);
+ return 1;
+ }
+
+ if (memcmp(&new_status, astat, sizeof(new_status)) != 0) {
+ PrintError("Recreated transaction on cloned RO volume, but "
+ "the volume has changed!\n", 0);
+ return 1;
+ }
+ } else {
+ PrintError("Unable to get status of current cloned RO transaction\n",
+ code);
+ return 1;
+ }
+ } else {
+ if (memcmp(&new_status, astat, sizeof(new_status)) != 0) {
+ /* sanity check */
+ PrintError("Internal error: current GetStatus does not match "
+ "original GetStatus?\n", 0);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+PutTrans(afs_int32 *vldbindex, struct replica *replicas,
+ struct rx_connection **toconns, struct release *times,
+ afs_int32 volcount)
+{
+ afs_int32 s, code = 0, rcode = 0;
+ /* End the transactions and destroy the connections */
+ for (s = 0; s < volcount; s++) {
+ if (replicas[s].trans) {
+ code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
+
+ replicas[s].trans = 0;
+ if (!code)
+ code = rcode;
+ if (code) {
+ if ((s == 0) || (code != ENOENT)) {
+ PrintError("Could not end transaction on a ro volume: ",
+ code);
+ } else {
+ PrintError
+ ("Transaction timed out on a ro volume. Will retry.\n",
+ 0);
+ if (times[s].vldbEntryIndex < *vldbindex)
+ *vldbindex = times[s].vldbEntryIndex;
+ }
+ }
+ }
+ if (toconns[s])
+ rx_DestroyConnection(toconns[s]);
+ toconns[s] = 0;
+ }
+}
+
+static int
+DoVolOnline(struct nvldbentry *vldbEntryPtr, afs_uint32 avolid, int index,
+ char *vname, struct rx_connection *connPtr)
+{
+ afs_int32 code = 0, rcode = 0, onlinetid = 0;
+
+ code =
+ AFSVolTransCreate_retry(connPtr, avolid,
+ vldbEntryPtr->serverPartition[index],
+ ITOffline,
+ &onlinetid);
+ if (code)
+ EPRINT(code, "Could not create transaction on readonly...\n");
+
+ else {
+ code = AFSVolSetFlags(connPtr, onlinetid, 0);
+ if (code)
+ EPRINT(code, "Could not set flags on readonly...\n");
+ }
+
+ if (!code) {
+ code =
+ AFSVolSetIdsTypes(connPtr, onlinetid, vname,
+ ROVOL, vldbEntryPtr->volumeId[RWVOL],
+ 0, 0);
+ if (code)
+ EPRINT(code, "Could not set ids on readonly...\n");
+ }
+ if (!code)
+ code = AFSVolEndTrans(connPtr, onlinetid, &rcode);
+ if (!code)
+ code = rcode;
+ return code;
+}
/* UV_ReleaseVolume()
* Release volume <afromvol> on <afromserver> <afrompart> to all
* successfully.
* forceflag: Performs a full release.
*
- * Will create a clone from the RW, then dump the clone out to
+ * Will create a clone from the RW, then dump the clone out to
* the remaining replicas. If there is more than 1 RO sites,
* ensure that the VLDB says at least one RO is available all
* the time: Influences when we write back the VLDB entry.
*/
int
-UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
- afs_int32 afrompart, int forceflag)
+UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
+ afs_int32 afrompart, int forceflag, int stayUp)
{
char vname[64];
- afs_int32 code, vcode, rcode, tcode;
- afs_int32 cloneVolId, roVolId;
+ afs_int32 code = 0;
+ afs_int32 vcode, rcode, tcode;
+ afs_uint32 cloneVolId = 0, roVolId;
struct replica *replicas = 0;
struct nvldbentry entry, storeEntry;
- int i, volcount, m, fullrelease, vldbindex;
+ int i, volcount = 0, m, fullrelease, vldbindex;
int failure;
struct restoreCookie cookie;
struct rx_connection **toconns = 0;
int islocked = 0;
afs_int32 clonetid = 0, onlinetid;
afs_int32 fromtid = 0;
- afs_uint32 fromdate, thisdate;
+ afs_uint32 fromdate = 0;
+ afs_uint32 thisdate;
time_t tmv;
int s;
manyDests tr;
manyResults results;
int rwindex, roindex, roclone, roexists;
- afs_int32 rwcrdate, rwupdate, clcrdate;
+ afs_uint32 rwcrdate = 0, rwupdate = 0;
+ afs_uint32 clcrdate;
struct rtime {
int validtime;
afs_uint32 uptime;
} remembertime[NMAXNSERVERS];
int releasecount = 0;
struct volser_status volstatus;
+ char hoststr[16];
+ afs_int32 origflags[NMAXNSERVERS];
+ struct volser_status orig_status;
+ int notreleased = 0;
+ int tried_justnewsites = 0;
+ int justnewsites = 0; /* are we just trying to release to new RO sites? */
- memset((char *)remembertime, 0, sizeof(remembertime));
- memset((char *)&results, 0, sizeof(results));
+ memset(remembertime, 0, sizeof(remembertime));
+ memset(&results, 0, sizeof(results));
+ memset(origflags, 0, sizeof(origflags));
vcode = ubik_VL_SetLock(cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
if (vcode != VL_RERELEASE)
roclone = ((roindex == -1) ? 0 : 1);
rwindex = Lp_GetRwIndex(&entry);
if (rwindex < 0)
- ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
+ ONERROR0(VOLSERNOVOL, "There is no RW volume \n");
/* Make sure we have a RO volume id to work with */
if (entry.volumeId[ROVOL] == INVALID_BID) {
if (entry.serverFlags[i] & ITSROVOL) {
m++;
if (entry.serverFlags[i] & NEW_REPSITE) s++;
+ if (entry.serverFlags[i] & RO_DONTUSE) notreleased++;
}
+ origflags[i] = entry.serverFlags[i];
}
if ((forceflag && !fullrelease) || (s == m) || (s == 0))
fullrelease = 1;
+ if (!forceflag && (s == m || s == 0)) {
+ if (notreleased && notreleased != m) {
+ /* we have some new unreleased sites. try to just release to those,
+ * if the RW has not changed */
+ justnewsites = 1;
+ }
+ }
+
/* Determine which volume id to use and see if it exists */
cloneVolId =
((fullrelease
code = VolumeExists(afromserver, afrompart, cloneVolId);
roexists = ((code == ENODEV) ? 0 : 1);
+ /* For stayUp case, if roclone is the only site, bypass special handling */
+ if (stayUp && roclone) {
+ int e;
+ error = 0;
+
+ for (e = 0; (e < entry.nServers) && !error; e++) {
+ if ((entry.serverFlags[e] & ITSROVOL)) {
+ if (!(VLDB_IsSameAddrs(entry.serverNumber[e], afromserver,
+ &error)))
+ break;
+ }
+ }
+ if (e >= entry.nServers)
+ stayUp = 0;
+ }
+
+ /* If we had a previous release to complete, do so, else: */
+ if (stayUp && (cloneVolId == entry.volumeId[ROVOL])) {
+ code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &cloneVolId);
+ ONERROR(code, afromvol,
+ "Cannot get temporary clone id for volume %u\n");
+ }
+
fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
if (!fromconn)
ONERROR(-1, afromserver,
fullrelease = 1; /* Do a full release if RO clone does not exist */
else {
/* Begin transaction on RW and mark it busy while we query it */
- code = AFSVolTransCreate(
+ code = AFSVolTransCreate_retry(
fromconn, afromvol, afrompart, ITBusy, &fromtid
);
ONERROR(code, afromvol,
ONERROR(code, afromvol,
"Failed to get the status of RW volume %u\n");
rwcrdate = volstatus.creationDate;
- rwupdate = volstatus.updateDate;
/* End transaction on RW */
code = AFSVolEndTrans(fromconn, fromtid, &rcode);
"Failed to end transaction on RW volume %u\n");
/* Begin transaction on clone and mark it busy while we query it */
- code = AFSVolTransCreate(
+ code = AFSVolTransCreate_retry(
fromconn, cloneVolId, afrompart, ITBusy, &clonetid
);
ONERROR(code, cloneVolId,
}
}
+ if (fullrelease != 1) {
+ /* in case the RW has changed, and just to be safe */
+ justnewsites = 0;
+ }
+
if (verbose) {
switch (fullrelease) {
case 2:
case 1:
fprintf(STDOUT, "This is a complete release of volume %lu\n",
(unsigned long)afromvol);
+ if (justnewsites) {
+ tried_justnewsites = 1;
+ fprintf(STDOUT, "There are new RO sites; we will try to "
+ "only release to new sites\n");
+ }
break;
case 0:
fprintf(STDOUT, "This is a completion of a previous release\n");
}
if (fullrelease) {
+ afs_int32 oldest = 0;
/* If the RO clone exists, then if the clone is a temporary
* clone, delete it. Or if the RO clone is marked RO_DONTUSE
* (it was recently added), then also delete it. We do not
* want to "reclone" a temporary RO clone.
*/
+ if (stayUp) {
+ code = VolumeExists(afromserver, afrompart, cloneVolId);
+ if (!code) {
+ code = DoVolDelete(fromconn, cloneVolId, afrompart, "previous clone", 0,
+ NULL, NULL);
+ if (code && (code != VNOVOL))
+ ERROREXIT(code);
+ VDONE;
+ }
+ }
+ /* clean up any previous tmp clone before starting if staying up */
if (roexists
&& (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
- code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
+ code = DoVolDelete(fromconn,
+ stayUp ? entry.volumeId[ROVOL] : cloneVolId,
+ afrompart, "the", 0, NULL, NULL);
if (code && (code != VNOVOL))
ERROREXIT(code);
roexists = 0;
}
+ if (justnewsites) {
+ VPRINT("Querying old RO sites for update times...");
+ for (vldbindex = 0; vldbindex < entry.nServers; vldbindex++) {
+ volEntries volumeInfo;
+ struct rx_connection *conn;
+ afs_int32 crdate;
+
+ if (!(entry.serverFlags[vldbindex] & ITSROVOL)) {
+ continue;
+ }
+ if ((entry.serverFlags[vldbindex] & RO_DONTUSE)) {
+ continue;
+ }
+ conn = UV_Bind(entry.serverNumber[vldbindex], AFSCONF_VOLUMEPORT);
+ if (!conn) {
+ fprintf(STDERR, "Cannot establish connection to server %s\n",
+ hostutil_GetNameByINet(entry.serverNumber[vldbindex]));
+ justnewsites = 0;
+ break;
+ }
+ volumeInfo.volEntries_val = NULL;
+ volumeInfo.volEntries_len = 0;
+ code = AFSVolListOneVolume(conn, entry.serverPartition[vldbindex],
+ entry.volumeId[ROVOL],
+ &volumeInfo);
+ if (code) {
+ fprintf(STDERR, "Could not fetch information about RO vol %lu from server %s\n",
+ (unsigned long)entry.volumeId[ROVOL],
+ hostutil_GetNameByINet(entry.serverNumber[vldbindex]));
+ PrintError("", code);
+ justnewsites = 0;
+ rx_DestroyConnection(conn);
+ break;
+ }
+
+ crdate = CLOCKADJ(volumeInfo.volEntries_val[0].creationDate);
+
+ if (oldest == 0 || crdate < oldest) {
+ oldest = crdate;
+ }
+
+ rx_DestroyConnection(conn);
+ free(volumeInfo.volEntries_val);
+ volumeInfo.volEntries_val = NULL;
+ volumeInfo.volEntries_len = 0;
+ }
+ VDONE;
+ }
+ if (justnewsites) {
+ volEntries volumeInfo;
+ volumeInfo.volEntries_val = NULL;
+ volumeInfo.volEntries_len = 0;
+ code = AFSVolListOneVolume(fromconn, afrompart, afromvol,
+ &volumeInfo);
+ if (code) {
+ fprintf(STDERR, "Could not fetch information about RW vol %lu from server %s\n",
+ (unsigned long)afromvol,
+ hostutil_GetNameByINet(afromserver));
+ PrintError("", code);
+ justnewsites = 0;
+ } else {
+ rwupdate = volumeInfo.volEntries_val[0].updateDate;
+
+ free(volumeInfo.volEntries_val);
+ volumeInfo.volEntries_val = NULL;
+ volumeInfo.volEntries_len = 0;
+ }
+ }
+ if (justnewsites && oldest <= rwupdate) {
+ /* RW has changed */
+ justnewsites = 0;
+ }
+
/* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
* write this entry out to the vlserver until after the first
* RO volume is released (temp RO clones don't count).
+ *
+ * If 'justnewsites' is set, we're only updating sites that have
+ * RO_DONTUSE set, so set NEW_REPSITE for all of the others.
*/
for (i = 0; i < entry.nServers; i++) {
- entry.serverFlags[i] &= ~NEW_REPSITE;
- entry.serverFlags[i] |= RO_DONTUSE;
+ if (justnewsites) {
+ if ((entry.serverFlags[i] & RO_DONTUSE)) {
+ entry.serverFlags[i] &= ~NEW_REPSITE;
+ } else {
+ entry.serverFlags[i] |= NEW_REPSITE;
+ }
+ } else {
+ entry.serverFlags[i] &= ~NEW_REPSITE;
+ entry.serverFlags[i] |= RO_DONTUSE;
+ }
}
entry.serverFlags[rwindex] |= NEW_REPSITE;
entry.serverFlags[rwindex] &= ~RO_DONTUSE;
+ }
- /* Begin transaction on RW and mark it busy while we clone it */
- code =
- AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
- &clonetid);
- ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
-
- /* Clone or reclone the volume */
- if (roexists) {
- VPRINT1("Recloning RW volume %u...", cloneVolId);
- code = AFSVolReClone(fromconn, clonetid, cloneVolId);
- ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
- VDONE;
- } else {
- if (roclone) {
- strcpy(vname, entry.name);
+ if (justnewsites && roexists) {
+ /* if 'justnewsites' and 'roexists' are set, we don't need to do
+ * anything with the RO clone, so skip the reclone */
+ /* noop */
+
+ } else if (fullrelease) {
+
+ if (roclone) {
+ strcpy(vname, entry.name);
+ if (stayUp)
+ strcat(vname, ".roclone");
+ else
strcat(vname, ".readonly");
- VPRINT1("Cloning RW volume %u to permanent RO...", afromvol);
- } else {
- strcpy(vname, "readonly-clone-temp");
- VPRINT1("Cloning RW volume %u to temporary RO...", afromvol);
+ } else {
+ strcpy(vname, "readonly-clone-temp");
+ }
+
+ code = DoVolClone(fromconn, afromvol, afrompart, readonlyVolume,
+ cloneVolId, (roclone && !stayUp)?"permanent RO":
+ "temporary RO", NULL, vname, NULL, &volstatus, NULL);
+ if (code) {
+ error = code;
+ goto rfail;
+ }
+
+ if (justnewsites && rwupdate != volstatus.updateDate) {
+ justnewsites = 0;
+ /* reset the serverFlags as if 'justnewsites' had never been set */
+ for (i = 0; i < entry.nServers; i++) {
+ entry.serverFlags[i] &= ~NEW_REPSITE;
+ entry.serverFlags[i] |= RO_DONTUSE;
}
- code =
- AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
- &cloneVolId);
- ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
- VDONE;
+ entry.serverFlags[rwindex] |= NEW_REPSITE;
+ entry.serverFlags[rwindex] &= ~RO_DONTUSE;
}
- /* Get the time the RW was created for future information */
- VPRINT1("Getting status of RW volume %u...", afromvol);
- code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
- ONERROR(code, afromvol,
- "Failed to get the status of the RW volume %u\n");
- VDONE;
rwcrdate = volstatus.creationDate;
- rwupdate = volstatus.updateDate;
-
- /* End the transaction on the RW volume */
- VPRINT1("Ending cloning transaction on RW volume %u...", afromvol);
- code = AFSVolEndTrans(fromconn, clonetid, &rcode);
- clonetid = 0;
- ONERROR((code ? code : rcode), afromvol,
- "Failed to end cloning transaction on RW %u\n");
- VDONE;
/* Remember clone volume ID in case we fail or are interrupted */
entry.cloneId = cloneVolId;
- if (roclone) {
+ if (roclone && !stayUp) {
/* Bring the RO clone online - though not if it's a temporary clone */
VPRINT1("Starting transaction on RO clone volume %u...",
cloneVolId);
code =
- AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
+ AFSVolTransCreate_retry(fromconn, cloneVolId, afrompart, ITOffline,
&onlinetid);
ONERROR(code, cloneVolId,
"Failed to start transaction on volume %u\n");
ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
/* Sleep so that a client searching for an online volume won't
- * find the clone offline and then the next RO offline while the
+ * find the clone offline and then the next RO offline while the
* release brings the clone online and the next RO offline (race).
* There is a fix in the 3.4 client that does not need this sleep
* anymore, but we don't know what clients we have.
*/
- if (entry.nServers > 2)
+ if (entry.nServers > 2 && !justnewsites)
sleep(5);
/* Mark the RO clone in the VLDB as a good site (already released) */
}
}
+ if (justnewsites) {
+ VPRINT("RW vol has not changed; only releasing to new RO sites\n");
+ /* act like this is a completion of a previous release */
+ fullrelease = 0;
+ } else if (tried_justnewsites) {
+ VPRINT("RW vol has changed; releasing to all sites\n");
+ }
+
/* Now we will release from the clone to the remaining RO replicas.
* The first 2 ROs (counting the non-temporary RO clone) are released
* individually: releasecount. This is to reduce the race condition
*/
strcpy(vname, entry.name);
- strcat(vname, ".readonly");
+ if (stayUp)
+ strcat(vname, ".roclone");
+ else
+ strcat(vname, ".readonly");
memset(&cookie, 0, sizeof(cookie));
strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
cookie.type = ROVOL;
cookie.parent = entry.volumeId[RWVOL];
cookie.clone = 0;
- nservers = entry.nServers / 2; /* how many to do at once, excluding clone */
- replicas =
- (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
- times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
- toconns =
- (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
- nservers + 1);
- results.manyResults_val =
- (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
- if (!replicas || !times || !!!results.manyResults_val || !toconns)
- ONERROR(ENOMEM, 0,
+ /* how many to do at once, excluding clone */
+ if (stayUp || justnewsites)
+ nservers = entry.nServers; /* can do all, none offline */
+ else
+ nservers = entry.nServers / 2;
+ replicas = calloc(nservers + 1, sizeof(struct replica));
+ times = calloc(nservers + 1, sizeof(struct release));
+ toconns = calloc(nservers + 1, sizeof(struct rx_connection *));
+ results.manyResults_val = calloc(nservers + 1, sizeof(afs_int32));
+ if (!replicas || !times || !results.manyResults_val || !toconns)
+ ONERROR0(ENOMEM,
"Failed to create transaction on the release clone\n");
- memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
- memset(times, 0, (sizeof(struct release) * nservers + 1));
- memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
- memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
-
/* Create a transaction on the cloned volume */
VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
code =
- AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
+ AFSVolTransCreate_retry(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
+ if (!code) {
+ memset(&orig_status, 0, sizeof(orig_status));
+ code = AFSVolGetStatus(fromconn, fromtid, &orig_status);
+ }
if (!fullrelease && code)
ONERROR(VOLSERNOVOL, afromvol,
"Old clone is inaccessible. Try vos release -f %u.\n");
- ONERROR(code, 0, "Failed to create transaction on the release clone\n");
+ ONERROR0(code, "Failed to create transaction on the release clone\n");
VDONE;
+ /* if we have a clone, treat this as done, for now */
+ if (stayUp && !fullrelease) {
+ entry.serverFlags[roindex] |= NEW_REPSITE;
+ entry.serverFlags[roindex] &= ~RO_DONTUSE;
+ entry.flags |= RO_EXISTS;
+
+ releasecount++;
+ }
+
/* For each index in the VLDB */
for (vldbindex = 0; vldbindex < entry.nServers;) {
-
- /* Get a transaction on the replicas. Pick replacas which have an old release. */
+ /* Get a transaction on the replicas. Pick replicas which have an old release. */
for (volcount = 0;
((volcount < nservers) && (vldbindex < entry.nServers));
vldbindex++) {
- /* The first two RO volumes will be released individually.
- * The rest are then released in parallel. This is a hack
- * for clients not recognizing right away when a RO volume
- * comes back on-line.
- */
- if ((volcount == 1) && (releasecount < 2))
- break;
+ if (!stayUp && !justnewsites) {
+ /* The first two RO volumes will be released individually.
+ * The rest are then released in parallel. This is a hack
+ * for clients not recognizing right away when a RO volume
+ * comes back on-line.
+ */
+ if ((volcount == 1) && (releasecount < 2))
+ break;
+ }
if (vldbindex == roindex)
continue; /* the clone */
/* Get a Transaction on this replica. Get a new connection if
* necessary. Create the volume if necessary. Return the
* time from which the dump should be made (0 if it's a new
- * volume). Each volume might have a different time.
+ * volume). Each volume might have a different time.
*/
replicas[volcount].server.destHost =
ntohl(entry.serverNumber[vldbindex]);
GetTrans(&entry, vldbindex, &(toconns[volcount]),
&(replicas[volcount].trans),
&(times[volcount].crtime),
- &(times[volcount].uptime));
+ &(times[volcount].uptime),
+ origflags, stayUp?cloneVolId:0);
if (code)
continue;
if (!volcount)
continue;
+ code = CheckTrans(fromconn, &fromtid, afrompart, &orig_status);
+ if (code) {
+ code = ENOENT;
+ goto rfail;
+ }
+
if (verbose) {
fprintf(STDOUT, "Starting ForwardMulti from %lu to %u on %s",
- (unsigned long)cloneVolId, entry.volumeId[ROVOL],
- hostutil_GetNameByINet(entry.
+ (unsigned long)cloneVolId, stayUp?
+ cloneVolId:entry.volumeId[ROVOL],
+ noresolve ? afs_inet_ntoa_r(entry.serverNumber[times[0].
+ vldbEntryIndex], hoststr) :
+ hostutil_GetNameByINet(entry.
serverNumber[times[0].
vldbEntryIndex]));
for (s = 1; s < volcount; s++) {
fprintf(STDOUT, " and %s",
- hostutil_GetNameByINet(entry.
+ noresolve ? afs_inet_ntoa_r(entry.serverNumber[times[s].
+ vldbEntryIndex], hoststr) :
+ hostutil_GetNameByINet(entry.
serverNumber[times[s].
vldbEntryIndex]));
}
continue;
}
- code =
- AFSVolSetIdsTypes(toconns[m], replicas[m].trans, vname,
- ROVOL, entry.volumeId[RWVOL], 0, 0);
- if (code) {
- if ((m == 0) || (code != ENOENT)) {
- PrintError("Failed to set correct names and ids: ",
- code);
+ code =
+ AFSVolSetIdsTypes(toconns[m], replicas[m].trans, vname,
+ ROVOL, entry.volumeId[RWVOL], 0, 0);
+ if (code) {
+ if ((m == 0) || (code != ENOENT)) {
+ PrintError("Failed to set correct names and ids: ",
+ code);
+ }
+ continue;
+ }
+
+ /* have to clear dest. flags to ensure new vol goes online:
+ * because the restore (forwarded) operation copied
+ * the V_inService(=0) flag over to the destination.
+ */
+ code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
+ if (code) {
+ if ((m == 0) || (code != ENOENT)) {
+ PrintError("Failed to set flags on ro volume: ",
+ code);
+ }
+ continue;
+ }
+
+ entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
+ entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
+ entry.flags |= RO_EXISTS;
+ releasecount++;
+ }
+ }
+
+ if (!stayUp) {
+ PutTrans(&vldbindex, replicas, toconns, times, volcount);
+ MapNetworkToHost(&entry, &storeEntry);
+ vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
+ ONERROR(vcode, afromvol,
+ " Could not update VLDB entry for volume %u\n");
+ }
+ } /* for each index in the vldb */
+
+ /* for the stayup case, put back at the end */
+ if (stayUp) {
+ afs_uint32 tmpVol = entry.volumeId[ROVOL];
+ strcpy(vname, entry.name);
+ strcat(vname, ".readonly");
+
+ if (roclone) {
+ /* have to clear flags to ensure new vol goes online
+ */
+ code = AFSVolSetFlags(fromconn, fromtid, 0);
+ if (code && (code != ENOENT)) {
+ PrintError("Failed to set flags on ro volume: ",
+ code);
+ }
+
+ VPRINT3("%sloning to permanent RO %u on %s...", roexists?"Re-c":"C", tmpVol,
+ noresolve ?
+ afs_inet_ntoa_r(entry.serverNumber[roindex],
+ hoststr) :
+ hostutil_GetNameByINet(entry.serverNumber[roindex]));
+
+ code = AFSVolClone(fromconn, fromtid, roexists?tmpVol:0,
+ readonlyVolume, vname, &tmpVol);
+
+ if (!code) {
+ VDONE;
+ VPRINT("Bringing readonly online...");
+ code = DoVolOnline(&entry, tmpVol, roindex, vname,
+ fromconn);
+ }
+ if (code) {
+ EPRINT(code, "Failed: ");
+ entry.serverFlags[roindex] &= ~NEW_REPSITE;
+ entry.serverFlags[roindex] |= RO_DONTUSE;
+ } else {
+ entry.serverFlags[roindex] |= NEW_REPSITE;
+ entry.serverFlags[roindex] &= ~RO_DONTUSE;
+ entry.flags |= RO_EXISTS;
+ VDONE;
+ }
+
+ }
+ for (s = 0; s < volcount; s++) {
+ if (replicas[s].trans) {
+ vldbindex = times[s].vldbEntryIndex;
+
+ /* ok, so now we have to end the previous transaction */
+ code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
+ if (!code)
+ code = rcode;
+
+ if (!code) {
+ code = AFSVolTransCreate_retry(toconns[s],
+ cloneVolId,
+ entry.serverPartition[vldbindex],
+ ITBusy,
+ &(replicas[s].trans));
+ if (code) {
+ PrintError("Unable to begin transaction on temporary clone: ", code);
}
- continue;
+ } else {
+ PrintError("Unable to end transaction on temporary clone: ", code);
}
- /* have to clear dest. flags to ensure new vol goes online:
- * because the restore (forwarded) operation copied
- * the V_inService(=0) flag over to the destination.
- */
- code = AFSVolSetFlags(toconns[m], replicas[m].trans, 0);
+ VPRINT3("%sloning to permanent RO %u on %s...", times[s].crtime?"Re-c":"C",
+ tmpVol, noresolve ?
+ afs_inet_ntoa_r(htonl(replicas[s].server.destHost),
+ hoststr) :
+ hostutil_GetNameByINet(htonl(replicas[s].server.destHost)));
+ if (times[s].crtime)
+ code = AFSVolClone(toconns[s], replicas[s].trans, tmpVol,
+ readonlyVolume, vname, &tmpVol);
+ else
+ code = AFSVolClone(toconns[s], replicas[s].trans, 0,
+ readonlyVolume, vname, &tmpVol);
+
if (code) {
- if ((m == 0) || (code != ENOENT)) {
- PrintError("Failed to set flags on ro volume: ",
- code);
+ if (!times[s].crtime) {
+ entry.serverFlags[vldbindex] |= RO_DONTUSE;
}
- continue;
+ entry.serverFlags[vldbindex] &= ~NEW_REPSITE;
+ PrintError("Failed: ",
+ code);
+ } else
+ VDONE;
+
+ if (entry.serverFlags[vldbindex] != RO_DONTUSE) {
+ /* bring it online (mark it InService) */
+ VPRINT1("Bringing readonly online on %s...",
+ noresolve ?
+ afs_inet_ntoa_r(
+ htonl(replicas[s].server.destHost),
+ hoststr) :
+ hostutil_GetNameByINet(
+ htonl(replicas[s].server.destHost)));
+
+ code = DoVolOnline(&entry, tmpVol, vldbindex, vname,
+ toconns[s]);
+ /* needed to come online for cloning */
+ if (code) {
+ /* technically it's still new, just not online */
+ entry.serverFlags[s] &= ~NEW_REPSITE;
+ entry.serverFlags[s] |= RO_DONTUSE;
+ if (code != ENOENT) {
+ PrintError("Failed to set correct names and ids: ",
+ code);
+ }
+ } else
+ VDONE;
}
- entry.serverFlags[times[m].vldbEntryIndex] |= NEW_REPSITE;
- entry.serverFlags[times[m].vldbEntryIndex] &= ~RO_DONTUSE;
- entry.flags |= RO_EXISTS;
- releasecount++;
- }
- }
+ VPRINT("Marking temporary clone for deletion...\n");
+ code = AFSVolSetFlags(toconns[s],
+ replicas[s].trans,
+ VTDeleteOnSalvage |
+ VTOutOfService);
+ if (code)
+ EPRINT(code, "Failed: ");
+ else
+ VDONE;
- /* End the transactions and destroy the connections */
- for (s = 0; s < volcount; s++) {
- if (replicas[s].trans)
+ VPRINT("Ending transaction on temporary clone...\n");
code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
- replicas[s].trans = 0;
- if (!code)
- code = rcode;
- if (code) {
- if ((s == 0) || (code != ENOENT)) {
- PrintError("Could not end transaction on a ro volume: ",
- code);
- } else {
- PrintError
- ("Transaction timed out on a ro volume. Will retry.\n",
- 0);
- if (times[s].vldbEntryIndex < vldbindex)
- vldbindex = times[s].vldbEntryIndex;
+ if (!code)
+ rcode = code;
+ if (code)
+ PrintError("Failed: ", code);
+ else {
+ VDONE;
+ /* ended successfully */
+ replicas[s].trans = 0;
+
+ VPRINT2("Deleting temporary clone %u on %s...", cloneVolId,
+ noresolve ?
+ afs_inet_ntoa_r(htonl(replicas[s].server.destHost),
+ hoststr) :
+ hostutil_GetNameByINet(htonl(replicas[s].server.destHost)));
+ code = DoVolDelete(toconns[s], cloneVolId,
+ entry.serverPartition[vldbindex],
+ NULL, 0, NULL, NULL);
+ if (code) {
+ EPRINT(code, "Failed: ");
+ } else
+ VDONE;
}
}
-
- if (toconns[s])
- rx_DestroyConnection(toconns[s]);
- toconns[s] = 0;
}
- MapNetworkToHost(&entry, &storeEntry);
- vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
- ONERROR(vcode, afromvol,
- " Could not update VLDB entry for volume %u\n");
- } /* for each index in the vldb */
+ /* done. put the vldb entry in the success tail case*/
+ PutTrans(&vldbindex, replicas, toconns, times, volcount);
+ }
/* End the transaction on the cloned volume */
code = AFSVolEndTrans(fromconn, fromtid, &rcode);
if (!(entry.serverFlags[i] & NEW_REPSITE)) {
MapPartIdIntoName(entry.serverPartition[i], pname);
fprintf(STDERR, "\t%35s %s\n",
- hostutil_GetNameByINet(entry.serverNumber[i]), pname);
+ noresolve ? afs_inet_ntoa_r(entry.serverNumber[i], hoststr) :
+ hostutil_GetNameByINet(entry.serverNumber[i]), pname);
}
}
-
MapNetworkToHost(&entry, &storeEntry);
vcode =
VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry,
ERROREXIT(VOLSERBADRELEASE);
}
+ entry.cloneId = 0;
/* All the ROs were release successfully. Remove the temporary clone */
- if (!roclone) {
+ if (!roclone || stayUp) {
if (verbose) {
fprintf(STDOUT, "Deleting the releaseClone %lu ...",
(unsigned long)cloneVolId);
fflush(STDOUT);
}
- code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
+ code = DoVolDelete(fromconn, cloneVolId, afrompart, NULL, 0, NULL,
+ NULL);
ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
VDONE;
}
- entry.cloneId = 0;
for (i = 0; i < entry.nServers; i++)
entry.serverFlags[i] &= ~NEW_REPSITE;
fprintf(STDERR,
"Failed to end transaction on ro volume %u at server %s\n",
entry.volumeId[ROVOL],
- hostutil_GetNameByINet(htonl
- (replicas[i].server.
- destHost)));
+ noresolve ? afs_inet_ntoa_r(htonl(replicas[i].server.
+ destHost), hoststr) :
+ hostutil_GetNameByINet(htonl
+ (replicas[i].server.destHost)));
if (!error)
error = code;
}
}
-void
+static void
dump_sig_handler(int x)
{
fprintf(STDERR, "\nSignal handler: vos dump operation\n");
/* Dump the volume <afromvol> on <afromserver> and
* <afrompart> to <afilename> starting from <fromdate>.
* DumpFunction does the real work behind the scenes after
- * extracting parameters from the rock
+ * extracting parameters from the rock
*/
int
-UV_DumpVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
- afs_int32 fromdate, afs_int32(*DumpFunction) (), char *rock,
+UV_DumpVolume(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
+ afs_int32 fromdate,
+ afs_int32(*DumpFunction) (struct rx_call *, void *), void *rock,
afs_int32 flags)
{
- struct rx_connection *fromconn = (struct rx_connection *)0;
- struct rx_call *fromcall = (struct rx_call *)0;
- afs_int32 fromtid = 0, rxError = 0, rcode = 0;
- afs_int32 code, error = 0, retry = 0;
+ /* declare stuff 'volatile' that may be used from setjmp/longjmp and may
+ * be changing during the dump */
+ struct rx_call * volatile fromcall = NULL;
+ struct rx_connection * volatile fromconn = NULL;
+ afs_int32 volatile fromtid = 0;
+
+ afs_int32 rxError = 0, rcode = 0;
+ afs_int32 code, error = 0;
+ afs_int32 tmp;
time_t tmv = fromdate;
if (setjmp(env))
(void)signal(SIGINT, dump_sig_handler);
if (!fromdate) {
- VPRINT("Full Dump ...\n");
+ VEPRINT("Full Dump ...\n");
} else {
- VPRINT1("Incremental Dump (as of %.24s)...\n",
+ VEPRINT1("Incremental Dump (as of %.24s)...\n",
ctime(&tmv));
}
/* get connections to the servers */
fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
- VPRINT1("Starting transaction on volume %u...", afromvol);
- code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
+ VEPRINT1("Starting transaction on volume %u...", afromvol);
+ tmp = fromtid;
+ code = AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, &tmp);
+ fromtid = tmp;
EGOTO1(error_exit, code,
"Could not start transaction on the volume %u to be dumped\n",
afromvol);
- VDONE;
+ VEDONE;
fromcall = rx_NewCall(fromconn);
- VPRINT1("Starting volume dump on volume %u...", afromvol);
- if (flags & VOLDUMPV2_OMITDIRS)
+ VEPRINT1("Starting volume dump on volume %u...", afromvol);
+ if (flags & VOLDUMPV2_OMITDIRS)
code = StartAFSVolDumpV2(fromcall, fromtid, fromdate, flags);
else
- retryold:
code = StartAFSVolDump(fromcall, fromtid, fromdate);
EGOTO(error_exit, code, "Could not start the dump process \n");
- VDONE;
+ VEDONE;
- VPRINT1("Dumping volume %u...", afromvol);
+ VEPRINT1("Dumping volume %u...", afromvol);
code = DumpFunction(fromcall, rock);
- if (code == RXGEN_OPCODE)
+ if (code == RXGEN_OPCODE)
goto error_exit;
EGOTO(error_exit, code, "Error while dumping volume \n");
- VDONE;
+ VEDONE;
error_exit:
if (fromcall) {
code = rx_EndCall(fromcall, rxError);
- if (code && code != RXGEN_OPCODE)
+ if (code && code != RXGEN_OPCODE)
fprintf(STDERR, "Error in rx_EndCall\n");
if (code && !error)
error = code;
}
if (fromtid) {
- VPRINT1("Ending transaction on volume %u...", afromvol);
+ VEPRINT1("Ending transaction on volume %u...", afromvol);
code = AFSVolEndTrans(fromconn, fromtid, &rcode);
if (code || rcode) {
fprintf(STDERR, "Could not end transaction on the volume %lu\n",
if (!error)
error = (code ? code : rcode);
}
- VDONE;
+ VEDONE;
}
if (fromconn)
rx_DestroyConnection(fromconn);
- if (retry)
- goto retryold;
if (error != RXGEN_OPCODE)
PrintError("", error);
return (error);
}
/* Clone the volume <afromvol> on <afromserver> and
- * <afrompart>, and then dump the clone volume to
+ * <afrompart>, and then dump the clone volume to
* <afilename> starting from <fromdate>.
* DumpFunction does the real work behind the scenes after
- * extracting parameters from the rock
+ * extracting parameters from the rock
*/
int
-UV_DumpClonedVolume(afs_int32 afromvol, afs_int32 afromserver,
+UV_DumpClonedVolume(afs_uint32 afromvol, afs_uint32 afromserver,
afs_int32 afrompart, afs_int32 fromdate,
- afs_int32(*DumpFunction) (), char *rock, afs_int32 flags)
+ afs_int32(*DumpFunction) (struct rx_call *, void *),
+ void *rock, afs_int32 flags)
{
- struct rx_connection *fromconn = (struct rx_connection *)0;
- struct rx_call *fromcall = (struct rx_call *)0;
+ /* declare stuff 'volatile' that may be used from setjmp/longjmp and may
+ * be changing during the dump */
+ struct rx_connection * volatile fromconn = NULL;
+ struct rx_call * volatile fromcall = NULL;
+ afs_int32 volatile clonetid = 0;
+ afs_uint32 volatile clonevol = 0;
+
+ afs_int32 tmp;
afs_int32 fromtid = 0, rxError = 0, rcode = 0;
- afs_int32 clonetid = 0;
- afs_int32 code = 0, vcode = 0, error = 0;
- afs_int32 clonevol = 0;
+ afs_int32 code = 0, error = 0;
+ afs_uint32 tmpVol;
char vname[64];
time_t tmv = fromdate;
(void)signal(SIGINT, dump_sig_handler);
if (!fromdate) {
- VPRINT("Full Dump ...\n");
+ VEPRINT("Full Dump ...\n");
} else {
- VPRINT1("Incremental Dump (as of %.24s)...\n",
+ VEPRINT1("Incremental Dump (as of %.24s)...\n",
ctime(&tmv));
}
/* get connections to the servers */
fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
- VPRINT1("Starting transaction on volume %u...", afromvol);
- code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
+ VEPRINT1("Starting transaction on volume %u...", afromvol);
+ code = AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, &fromtid);
EGOTO1(error_exit, code,
"Could not start transaction on the volume %u to be dumped\n",
afromvol);
- VDONE;
+ VEDONE;
/* Get a clone id */
- VPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
- code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &clonevol);
+ VEPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
+ tmpVol = clonevol;
+ code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &tmpVol);
+ clonevol = tmpVol;
EGOTO1(error_exit, code,
"Could not get an ID for the clone of volume %u from the VLDB\n",
afromvol);
- VDONE;
+ VEDONE;
/* Do the clone. Default flags on clone are set to delete on salvage and out of service */
- VPRINT2("Cloning source volume %u to clone volume %u...", afromvol,
+ VEPRINT2("Cloning source volume %u to clone volume %u...", afromvol,
clonevol);
strcpy(vname, "dump-clone-temp");
+ tmpVol = clonevol;
code =
- AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &clonevol);
+ AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &tmpVol);
+ clonevol = tmpVol;
EGOTO1(error_exit, code, "Failed to clone the source volume %u\n",
afromvol);
- VDONE;
+ VEDONE;
- VPRINT1("Ending the transaction on the volume %u ...", afromvol);
+ VEPRINT1("Ending the transaction on the volume %u ...", afromvol);
rcode = 0;
code = AFSVolEndTrans(fromconn, fromtid, &rcode);
fromtid = 0;
code = rcode;
EGOTO1(error_exit, code,
"Failed to end the transaction on the volume %u\n", afromvol);
- VDONE;
+ VEDONE;
- VPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
+ VEPRINT1("Starting transaction on the cloned volume %u ...", clonevol);
+ tmp = clonetid;
code =
- AFSVolTransCreate(fromconn, clonevol, afrompart, ITOffline,
- &clonetid);
+ AFSVolTransCreate_retry(fromconn, clonevol, afrompart, ITOffline,
+ &tmp);
+ clonetid = tmp;
EGOTO1(error_exit, code,
"Failed to start a transaction on the cloned volume%u\n",
clonevol);
- VDONE;
+ VEDONE;
- VPRINT1("Setting flags on cloned volume %u ...", clonevol);
+ VEPRINT1("Setting flags on cloned volume %u ...", clonevol);
code = AFSVolSetFlags(fromconn, clonetid, VTDeleteOnSalvage | VTOutOfService); /*redundant */
EGOTO1(error_exit, code, "Could not set falgs on the cloned volume %u\n",
clonevol);
- VDONE;
+ VEDONE;
fromcall = rx_NewCall(fromconn);
- VPRINT1("Starting volume dump from cloned volume %u...", clonevol);
- if (flags & VOLDUMPV2_OMITDIRS)
+ VEPRINT1("Starting volume dump from cloned volume %u...", clonevol);
+ if (flags & VOLDUMPV2_OMITDIRS)
code = StartAFSVolDumpV2(fromcall, clonetid, fromdate, flags);
else
code = StartAFSVolDump(fromcall, clonetid, fromdate);
EGOTO(error_exit, code, "Could not start the dump process \n");
- VDONE;
+ VEDONE;
- VPRINT1("Dumping volume %u...", afromvol);
+ VEPRINT1("Dumping volume %u...", afromvol);
code = DumpFunction(fromcall, rock);
EGOTO(error_exit, code, "Error while dumping volume \n");
- VDONE;
+ VEDONE;
error_exit:
/* now delete the clone */
- VPRINT1("Deleting the cloned volume %u ...", clonevol);
+ VEPRINT1("Deleting the cloned volume %u ...", clonevol);
code = AFSVolDeleteVolume(fromconn, clonetid);
if (code) {
fprintf(STDERR, "Failed to delete the cloned volume %lu\n",
(unsigned long)clonevol);
} else {
- VDONE;
+ VEDONE;
}
if (fromcall) {
}
}
if (clonetid) {
- VPRINT1("Ending transaction on cloned volume %u...", clonevol);
+ VEPRINT1("Ending transaction on cloned volume %u...", clonevol);
code = AFSVolEndTrans(fromconn, clonetid, &rcode);
if (code || rcode) {
fprintf(STDERR,
if (!error)
error = (code ? code : rcode);
}
- VDONE;
+ VEDONE;
}
if (fromconn)
rx_DestroyConnection(fromconn);
/*
* Restore a volume <tovolid> <tovolname> on <toserver> <topart> from
* the dump file <afilename>. WriteData does all the real work
- * after extracting params from the rock
+ * after extracting params from the rock
*/
int
-UV_RestoreVolume2(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
- afs_int32 toparentid, char tovolname[], int flags,
- afs_int32(*WriteData) (), char *rock)
+UV_RestoreVolume2(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid,
+ afs_uint32 toparentid, char tovolname[], int flags,
+ afs_int32(*WriteData) (struct rx_call *, void *),
+ void *rock)
{
struct rx_connection *toconn, *tempconn;
struct rx_call *tocall;
struct volser_status tstatus;
struct volintInfo vinfo;
char partName[10];
- afs_int32 pvolid, pparentid;
- afs_int32 temptid;
- int success;
+ char tovolreal[VOLSER_OLDMAXVOLNAME];
+ afs_uint32 pvolid;
+ afs_int32 temptid, pparentid;
struct nvldbentry entry, storeEntry;
afs_int32 error;
int islocked;
afs_int32 oldCreateDate, oldUpdateDate, newCreateDate, newUpdateDate;
int index, same, errcode;
char apartName[10];
-
+ char hoststr[16];
memset(&cookie, 0, sizeof(cookie));
islocked = 0;
- success = 0;
error = 0;
reuseID = 1;
tocall = (struct rx_call *)0;
- toconn = (struct rx_connection *)0;
tempconn = (struct rx_connection *)0;
totid = 0;
temptid = 0;
}
if (!pparentid) pparentid = pvolid;
/* at this point we have a volume id to use/reuse for the volume to be restored */
+ strncpy(tovolreal, tovolname, VOLSER_OLDMAXVOLNAME);
+
if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 1)) {
EGOTO1(refail, VOLSERBADOP,
"The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n",
tovolname);
+ } else {
+ if ((pparentid != pvolid) && (flags & RV_RDONLY)) {
+ if (strlen(tovolname) > (VOLSER_OLDMAXVOLNAME - 10)) {
+ EGOTO1(refail, VOLSERBADOP,
+ "The volume name %s exceeds the maximum limit of (VOLSER_OLDMAXVOLNAME -1 ) bytes\n", tovolname);
+ }
+ snprintf(tovolreal, VOLSER_OLDMAXVOLNAME, "%s.readonly", tovolname);
+ }
}
MapPartIdIntoName(topart, partName);
fprintf(STDOUT, "Restoring volume %s Id %lu on server %s partition %s ..",
- tovolname, (unsigned long)pvolid,
+ tovolreal, (unsigned long)pvolid,
+ noresolve ? afs_inet_ntoa_r(toserver, hoststr) :
hostutil_GetNameByINet(toserver), partName);
fflush(STDOUT);
code =
- AFSVolCreateVolume(toconn, topart, tovolname, volsertype, pparentid, &pvolid,
+ AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid, &pvolid,
&totid);
if (code) {
if (flags & RV_FULLRST) { /* full restore: delete then create anew */
- VPRINT1("Deleting the previous volume %u ...", pvolid);
-
- code =
- AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
- EGOTO1(refail, code, "Failed to start transaction on %u\n",
- pvolid);
-
- code = AFSVolGetStatus(toconn, totid, &tstatus);
- EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
- pvolid);
-
- oldCreateDate = tstatus.creationDate;
- oldUpdateDate = tstatus.updateDate;
-
- code =
- AFSVolSetFlags(toconn, totid,
- VTDeleteOnSalvage | VTOutOfService);
- EGOTO1(refail, code, "Could not set flags on volume %u \n",
- pvolid);
-
- code = AFSVolDeleteVolume(toconn, totid);
- EGOTO1(refail, code, "Could not delete volume %u\n", pvolid);
-
- code = AFSVolEndTrans(toconn, totid, &rcode);
- totid = 0;
- if (!code)
- code = rcode;
- EGOTO1(refail, code, "Could not end transaction on %u\n", pvolid);
-
- VDONE;
+ code = DoVolDelete(toconn, pvolid, topart, "the previous", 0,
+ &tstatus, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto refail;
+ }
code =
- AFSVolCreateVolume(toconn, topart, tovolname, volsertype, pparentid,
+ AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid,
&pvolid, &totid);
EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
} else {
code =
- AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
+ AFSVolTransCreate_retry(toconn, pvolid, topart, ITOffline, &totid);
EGOTO1(refail, code, "Failed to start transaction on %u\n",
pvolid);
EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
pvolid);
- oldCreateDate = tstatus.creationDate;
- oldUpdateDate = tstatus.updateDate;
}
+ oldCreateDate = tstatus.creationDate;
+ oldUpdateDate = tstatus.updateDate;
} else {
oldCreateDate = 0;
oldUpdateDate = 0;
cookie.parent = pparentid;
cookie.type = voltype;
cookie.clone = 0;
- strncpy(cookie.name, tovolname, VOLSER_OLDMAXVOLNAME);
+ strncpy(cookie.name, tovolreal, VOLSER_OLDMAXVOLNAME);
tocall = rx_NewCall(toconn);
terror = StartAFSVolRestore(tocall, totid, 1, &cookie);
error = code;
goto refail;
}
- code = AFSVolSetIdsTypes(toconn, totid, tovolname, voltype, pparentid, 0, 0);
+ code = AFSVolSetIdsTypes(toconn, totid, tovolreal, voltype, pparentid, 0, 0);
if (code) {
fprintf(STDERR, "Could not set the right type and ID on %lu\n",
(unsigned long)pvolid);
goto refail;
}
- success = 1;
fprintf(STDOUT, " done\n");
fflush(STDOUT);
- if (success && (!reuseID || (flags & RV_FULLRST))) {
- /* Volume was restored on the file server, update the
+ if (!reuseID || (flags & RV_FULLRST)) {
+ /* Volume was restored on the file server, update the
* VLDB to reflect the change.
*/
vcode = VLDB_GetEntryByID(pvolid, voltype, &entry);
toserver, errcode);
if ((!errcode && !same)
|| (entry.serverPartition[index] != topart)) {
- tempconn =
- UV_Bind(entry.serverNumber[index],
- AFSCONF_VOLUMEPORT);
-
- MapPartIdIntoName(entry.serverPartition[index],
- apartName);
- VPRINT3
- ("Deleting the previous volume %u on server %s, partition %s ...",
- pvolid,
- hostutil_GetNameByINet(entry.serverNumber[index]),
- apartName);
- code =
- AFSVolTransCreate(tempconn, pvolid,
- entry.serverPartition[index],
- ITOffline, &temptid);
- if (!code) {
- code =
- AFSVolSetFlags(tempconn, temptid,
- VTDeleteOnSalvage |
- VTOutOfService);
- if (code) {
- fprintf(STDERR,
- "Could not set flags on volume %lu on the older site\n",
- (unsigned long)pvolid);
- error = code;
- goto refail;
- }
- code = AFSVolDeleteVolume(tempconn, temptid);
- if (code) {
- fprintf(STDERR,
- "Could not delete volume %lu on the older site\n",
- (unsigned long)pvolid);
- error = code;
- goto refail;
- }
- code = AFSVolEndTrans(tempconn, temptid, &rcode);
- temptid = 0;
- if (!code)
- code = rcode;
- if (code) {
- fprintf(STDERR,
- "Could not end transaction on volume %lu on the older site\n",
- (unsigned long)pvolid);
+ if (flags & RV_NODEL) {
+ VPRINT2
+ ("Not deleting the previous volume %u on server %s, ...",
+ pvolid,
+ noresolve ? afs_inet_ntoa_r(entry.serverNumber[index], hoststr) :
+ hostutil_GetNameByINet(entry.serverNumber[index]));
+ } else {
+ tempconn =
+ UV_Bind(entry.serverNumber[index],
+ AFSCONF_VOLUMEPORT);
+
+ MapPartIdIntoName(entry.serverPartition[index],
+ apartName);
+ VPRINT3
+ ("Deleting the previous volume %u on server %s, partition %s ...",
+ pvolid,
+ noresolve ? afs_inet_ntoa_r(entry.serverNumber[index], hoststr) :
+ hostutil_GetNameByINet(entry.serverNumber[index]),
+ apartName);
+ code = DoVolDelete(tempconn, pvolid,
+ entry.serverPartition[index],
+ "the", 0, NULL, NULL);
+ if (code && code != VNOVOL) {
error = code;
goto refail;
}
- VDONE;
MapPartIdIntoName(entry.serverPartition[index],
partName);
}
}
int
-UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
- char tovolname[], int flags, afs_int32(*WriteData) (),
- char *rock)
+UV_RestoreVolume(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid,
+ char tovolname[], int flags,
+ afs_int32(*WriteData) (struct rx_call *, void *),
+ void *rock)
{
return UV_RestoreVolume2(toserver, topart, tovolid, 0, tovolname, flags,
WriteData, rock);
/*unlocks the vldb entry associated with <volid> */
int
-UV_LockRelease(afs_int32 volid)
+UV_LockRelease(afs_uint32 volid)
{
-
-
afs_int32 vcode;
VPRINT("Binding to the VLDB server\n");
}
+/* old interface to add rosites */
+int
+UV_AddSite(afs_uint32 server, afs_int32 part, afs_uint32 volid,
+ afs_int32 valid)
+{
+ return UV_AddSite2(server, part, volid, 0, valid);
+}
+
/*adds <server> and <part> as a readonly replication site for <volid>
*in vldb */
int
-UV_AddSite(afs_int32 server, afs_int32 part, afs_int32 volid)
+UV_AddSite2(afs_uint32 server, afs_int32 part, afs_uint32 volid,
+ afs_uint32 rovolid, afs_int32 valid)
{
int j, nro = 0, islocked = 0;
- struct nvldbentry entry, storeEntry;
+ struct nvldbentry entry, storeEntry, entry2;
afs_int32 vcode, error = 0;
char apartName[10];
goto asfail;
}
+ /* if rovolid == 0, we leave the RO volume id alone. If the volume doesn't
+ * have an RO volid at this point (i.e. entry.volumeId[ROVOL] ==
+ * INVALID_BID) and we leave it alone, it gets an RO volid at release-time.
+ */
+ if (rovolid) {
+ if (entry.volumeId[ROVOL] == INVALID_BID) {
+ vcode = VLDB_GetEntryByID(rovolid, -1, &entry2);
+ if (!vcode) {
+ fprintf(STDERR, "Volume ID %d already exists\n", rovolid);
+ return VVOLEXISTS;
+ }
+ VPRINT1("Using RO volume id %d.\n", rovolid);
+ entry.volumeId[ROVOL] = rovolid;
+ } else {
+ fprintf(STDERR, "Ignoring given RO id %d, since volume already has RO id %d\n",
+ rovolid, entry.volumeId[ROVOL]);
+ }
+ }
+
VPRINT("Adding a new site ...");
entry.serverNumber[entry.nServers] = server;
entry.serverPartition[entry.nServers] = part;
- entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
+ if (!valid) {
+ entry.serverFlags[entry.nServers] = (ITSROVOL | RO_DONTUSE);
+ } else {
+ entry.serverFlags[entry.nServers] = (ITSROVOL);
+ }
entry.nServers++;
MapNetworkToHost(&entry, &storeEntry);
/*removes <server> <part> as read only site for <volid> from the vldb */
int
-UV_RemoveSite(afs_int32 server, afs_int32 part, afs_int32 volid)
+UV_RemoveSite(afs_uint32 server, afs_int32 part, afs_uint32 volid)
{
afs_int32 vcode;
struct nvldbentry entry, storeEntry;
- int islocked;
vcode = ubik_VL_SetLock(cstruct, 0, volid, RWVOL, VLOP_ADDSITE);
if (vcode) {
PrintError("", vcode);
return (vcode);
}
- islocked = 1;
vcode = VLDB_GetEntryByID(volid, RWVOL, &entry);
if (vcode) {
fprintf(STDERR,
/*sets <server> <part> as read/write site for <volid> in the vldb */
int
-UV_ChangeLocation(afs_int32 server, afs_int32 part, afs_int32 volid)
+UV_ChangeLocation(afs_uint32 server, afs_int32 part, afs_uint32 volid)
{
afs_int32 vcode;
struct nvldbentry entry, storeEntry;
/*list all the partitions on <aserver> */
int
-UV_ListPartitions(afs_int32 aserver, struct partList *ptrPartList,
+UV_ListPartitions(afs_uint32 aserver, struct partList *ptrPartList,
afs_int32 * cntp)
{
struct rx_connection *aconn;
struct pIDs partIds;
struct partEntries partEnts;
- register int i, j = 0, code;
+ int i, j = 0, code;
*cntp = 0;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
/*zap the list of volumes specified by volPtrArray (the volCloneId field).
This is used by the backup system */
int
-UV_ZapVolumeClones(afs_int32 aserver, afs_int32 apart,
+UV_ZapVolumeClones(afs_uint32 aserver, afs_int32 apart,
struct volDescription *volPtr, afs_int32 arraySize)
{
struct rx_connection *aconn;
struct volDescription *curPtr;
int curPos;
afs_int32 code = 0;
- afs_int32 rcode = 0;
afs_int32 success = 1;
- afs_int32 tid;
- aconn = (struct rx_connection *)0;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
curPos = 0;
for (curPtr = volPtr; curPos < arraySize; curPtr++) {
if (curPtr->volFlags & CLONEVALID) {
curPtr->volFlags &= ~CLONEZAPPED;
success = 1;
- code =
- AFSVolTransCreate(aconn, curPtr->volCloneId, apart, ITOffline,
- &tid);
+
+ code = DoVolDelete(aconn, curPtr->volCloneId, apart,
+ "clone", 0, NULL, NULL);
if (code)
success = 0;
- else {
- code = AFSVolDeleteVolume(aconn, tid);
- if (code)
- success = 0;
- code = AFSVolEndTrans(aconn, tid, &rcode);
- if (code || rcode)
- success = 0;
- }
+
if (success)
curPtr->volFlags |= CLONEZAPPED;
if (!success)
VPRINT2("Clone of %s %u deleted\n", curPtr->volName,
curPtr->volCloneId);
curPos++;
- tid = 0;
}
}
if (aconn)
return 0;
}
-/*return a list of clones of the volumes specified by volPtrArray. Used by the
+/*return a list of clones of the volumes specified by volPtrArray. Used by the
backup system */
int
-UV_GenerateVolumeClones(afs_int32 aserver, afs_int32 apart,
+UV_GenerateVolumeClones(afs_uint32 aserver, afs_int32 apart,
struct volDescription *volPtr, afs_int32 arraySize)
{
struct rx_connection *aconn;
afs_int32 rcode = 0;
afs_int32 tid;
int reuseCloneId = 0;
- afs_int32 curCloneId = 0;
+ afs_uint32 curCloneId = 0;
char cloneName[256]; /*max vol name */
- aconn = (struct rx_connection *)0;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
curPos = 0;
if ((volPtr->volFlags & REUSECLONEID) && (volPtr->volFlags & ENTRYVALID))
curPtr->volFlags |= CLONEVALID;
/*make a clone of curParentId and record as curPtr->volCloneId */
code =
- AFSVolTransCreate(aconn, curPtr->volId, apart, ITOffline,
+ AFSVolTransCreate_retry(aconn, curPtr->volId, apart, ITOffline,
&tid);
if (code)
VPRINT2("Clone for volume %s %u failed \n", curPtr->volName,
/*list all the volumes on <aserver> and <apart>. If all = 1, then all the
* relevant fields of the volume are also returned. This is a heavy weight operation.*/
int
-UV_ListVolumes(afs_int32 aserver, afs_int32 apart, int all,
+UV_ListVolumes(afs_uint32 aserver, afs_int32 apart, int all,
struct volintInfo **resultPtr, afs_int32 * size)
{
struct rx_connection *aconn;
*------------------------------------------------------------------------*/
int
-UV_XListVolumes(afs_int32 a_serverID, afs_int32 a_partID, int a_all,
+UV_XListVolumes(afs_uint32 a_serverID, afs_int32 a_partID, int a_all,
struct volintXInfo **a_resultPP,
afs_int32 * a_numEntsInResultP)
{
* We set the val field to a null pointer as a hint for the stub to
* allocate space.
*/
- code = 0;
*a_numEntsInResultP = 0;
*a_resultPP = (volintXInfo *) 0;
volumeXInfo.volXEntries_val = (volintXInfo *) 0;
/* get all the information about volume <volid> on <aserver> and <apart> */
int
-UV_ListOneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 volid,
+UV_ListOneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 volid,
struct volintInfo **resultPtr)
{
struct rx_connection *aconn;
afs_int32 code = 0;
volEntries volumeInfo;
- code = 0;
-
*resultPtr = (volintInfo *) 0;
volumeInfo.volEntries_val = (volintInfo *) 0; /*this hints the stub to allocate space */
volumeInfo.volEntries_len = 0;
*------------------------------------------------------------------------*/
int
-UV_XListOneVolume(afs_int32 a_serverID, afs_int32 a_partID, afs_int32 a_volID,
+UV_XListOneVolume(afs_uint32 a_serverID, afs_int32 a_partID, afs_uint32 a_volID,
struct volintXInfo **a_resultPP)
{
struct rx_connection *rxConnP; /*Rx connection to Volume Server */
* the info. Setting the val field to a null pointer tells the stub
* to allocate space for us.
*/
- code = 0;
*a_resultPP = (volintXInfo *) 0;
volumeXInfo.volXEntries_val = (volintXInfo *) 0;
volumeXInfo.volXEntries_len = 0;
}
/* CheckVolume()
- * Given a volume we read from a partition, check if it is
+ * Given a volume we read from a partition, check if it is
* represented in the VLDB correctly.
- *
+ *
* The VLDB is looked up by the RW volume id (not its name).
* The RW contains the true name of the volume (BK and RO set
* the name in the VLDB only on creation of the VLDB entry).
* We want rules strict enough that when we check all volumes
* on one partition, it does not need to be done again. IE:
- * two volumes on different partitions won't constantly
+ * two volumes on different partitions won't constantly
* change a VLDB entry away from what the other set.
- * For RW and BK volumes, we will always check the VLDB to see
+ * For RW and BK volumes, we will always check the VLDB to see
* if the two exist on the server/partition. May seem redundant,
* but this is an easy check of the VLDB. IE: if the VLDB entry
* says the BK exists but no BK volume is there, we will detect
* Output changed to look a lot like the "vos syncserv" otuput.
*/
static afs_int32
-CheckVolume(volintInfo * volumeinfo, afs_int32 aserver, afs_int32 apart,
- afs_int32 * modentry, afs_uint32 * maxvolid)
+CheckVolume(volintInfo * volumeinfo, afs_uint32 aserver, afs_int32 apart,
+ afs_int32 * modentry, afs_uint32 * maxvolid,
+ struct nvldbentry *aentry)
{
- int idx, j;
+ int idx = 0;
+ int j;
afs_int32 code, error = 0;
struct nvldbentry entry, storeEntry;
char pname[10];
- int pass = 0, islocked = 0, createentry, addvolume, modified, mod;
- afs_int32 rwvolid;
+ int pass = 0, createentry, addvolume, modified, mod, doit = 1;
+ afs_uint32 rwvolid;
+ char hoststr[16];
- if (modentry)
+ if (modentry) {
+ if (*modentry == 1)
+ doit = 0;
*modentry = 0;
+ }
rwvolid =
((volumeinfo->type ==
RWVOL) ? volumeinfo->volid : volumeinfo->parentID);
(unsigned long)rwvolid);
ERROR_EXIT(code);
}
- islocked = 1;
}
createentry = 0; /* Do we need to create a VLDB entry */
addvolume = 0; /* Add this volume to the VLDB entry */
modified = 0; /* The VLDB entry was modified */
- /* Read the entry from VLDB by its RW volume id */
- code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
- if (code) {
- if (code != VL_NOENT) {
- fprintf(STDOUT,
- "Could not retreive the VLDB entry for volume %lu \n",
- (unsigned long)rwvolid);
- ERROR_EXIT(code);
- }
+ if (aentry) {
+ memcpy(&entry, aentry, sizeof(entry));
+ } else {
+ /* Read the entry from VLDB by its RW volume id */
+ code = VLDB_GetEntryByID(rwvolid, RWVOL, &entry);
+ if (code) {
+ if (code != VL_NOENT) {
+ fprintf(STDOUT,
+ "Could not retrieve the VLDB entry for volume %lu \n",
+ (unsigned long)rwvolid);
+ ERROR_EXIT(code);
+ }
- memset(&entry, 0, sizeof(entry));
- vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
+ memset(&entry, 0, sizeof(entry));
+ vsu_ExtractName(entry.name, volumeinfo->name); /* Store name of RW */
- createentry = 1;
- } else {
- MapHostToNetwork(&entry);
+ createentry = 1;
+ } else {
+ MapHostToNetwork(&entry);
+ }
}
if (verbose && (pass == 1)) {
fprintf(STDERR,
"*** Warning: Orphaned RW volume %lu exists on %s %s\n",
(unsigned long)rwvolid,
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
hostutil_GetNameByINet(aserver), pname);
MapPartIdIntoName(entry.serverPartition[idx],
pname);
fprintf(STDERR,
" VLDB reports RW volume %lu exists on %s %s\n",
(unsigned long)rwvolid,
+ noresolve ?
+ afs_inet_ntoa_r(entry.serverNumber[idx], hoststr) :
hostutil_GetNameByINet(entry.
serverNumber[idx]),
pname);
fprintf(STDERR,
"*** Warning: Orphaned BK volume %u exists on %s %s\n",
entry.volumeId[BACKVOL],
+ noresolve ?
+ afs_inet_ntoa_r(entry.serverNumber[idx], hoststr) :
hostutil_GetNameByINet(entry.
serverNumber
[idx]), pname);
fprintf(STDERR,
" VLDB reports its RW volume %lu exists on %s %s\n",
(unsigned long)rwvolid,
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
hostutil_GetNameByINet(aserver),
pname);
}
fprintf(STDERR,
"*** Warning: Orphaned BK volume %lu exists on %s %s\n",
(unsigned long)volumeinfo->volid,
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
hostutil_GetNameByINet(aserver), pname);
MapPartIdIntoName(entry.serverPartition[idx], pname);
fprintf(STDERR,
" VLDB reports its RW/BK volume %lu exists on %s %s\n",
(unsigned long)rwvolid,
+ noresolve ?
+ afs_inet_ntoa_r(entry.serverNumber[idx], hoststr) :
hostutil_GetNameByINet(entry.
serverNumber[idx]),
pname);
fprintf(STDERR,
"*** Warning: Orphaned BK volume %u exists on %s %s\n",
entry.volumeId[BACKVOL],
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
hostutil_GetNameByINet(aserver),
pname);
fprintf(STDERR,
pname);
fprintf(STDERR,
"*** Warning: Orphaned BK volume %lu exists on %s %s\n",
- (unsigned long)volumeinfo->volid,
- hostutil_GetNameByINet(aserver),
+ (unsigned long)volumeinfo->volid,
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
+ hostutil_GetNameByINet(aserver),
pname);
fprintf(STDERR,
" VLDB reports its BK volume ID is %u\n",
entry.serverNumber[idx] = aserver;
entry.serverPartition[idx] = apart;
- entry.serverFlags[idx] = ITSRWVOL;
+ entry.serverFlags[idx] = ITSBACKVOL;
modified++;
}
else if (volumeinfo->type == ROVOL) { /* A RO volume */
if (volumeinfo->volid == entry.volumeId[ROVOL]) {
- /* This is a quick check to see if the RO entry exists in the
+ /* This is a quick check to see if the RO entry exists in the
* VLDB so we avoid the CheckVldbRO() call (which checks if each
* RO volume listed in the VLDB exists).
*/
fprintf(STDERR,
"*** Warning: Orphaned RO volume %u exists on %s %s\n",
entry.volumeId[ROVOL],
- hostutil_GetNameByINet(entry.
+ noresolve ?
+ afs_inet_ntoa_r(entry.serverNumber[j], hoststr) :
+ hostutil_GetNameByINet(entry.
serverNumber[j]),
pname);
fprintf(STDERR,
(unsigned long)volumeinfo->volid);
}
- Lp_SetRWValue(entry, entry.serverNumber[idx],
+ Lp_SetRWValue(&entry, entry.serverNumber[idx],
entry.serverPartition[idx], 0L, 0L);
entry.nServers--;
modified++;
MapPartIdIntoName(apart, pname);
fprintf(STDERR,
"*** Warning: Orphaned RO volume %lu exists on %s %s\n",
- (unsigned long)volumeinfo->volid,
- hostutil_GetNameByINet(aserver), pname);
+ (unsigned long)volumeinfo->volid,
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
+ hostutil_GetNameByINet(aserver), pname);
fprintf(STDERR,
" VLDB reports its RO volume ID is %u\n",
entry.volumeId[ROVOL]);
if (entry.volumeId[RWVOL] > *maxvolid)
*maxvolid = entry.volumeId[RWVOL];
- if (modified) {
+ if (modified && doit) {
MapNetworkToHost(&entry, &storeEntry);
if (createentry) {
ERROR_EXIT(code);
}
}
- if (modentry)
- *modentry = modified;
} else if (pass == 2) {
code =
ubik_VL_ReleaseLock(cstruct, 0, rwvolid, RWVOL,
}
}
+ if (modified && modentry) {
+ *modentry = 1;
+ }
+
+ if (aentry) {
+ memcpy(aentry, &entry, sizeof(entry));
+ }
+
if (verbose) {
fprintf(STDOUT, "-- status after --\n");
if (modified)
return (error);
}
-int
+static int
sortVolumes(const void *a, const void *b)
{
volintInfo *v1 = (volintInfo *) a;
volintInfo *v2 = (volintInfo *) b;
- afs_int32 rwvolid1, rwvolid2;
+ afs_uint32 rwvolid1, rwvolid2;
rwvolid1 = ((v1->type == RWVOL) ? v1->volid : v1->parentID);
rwvolid2 = ((v2->type == RWVOL) ? v2->volid : v2->parentID);
* if the volume exists on specified servers (similar to syncvldb).
*/
int
-UV_SyncVolume(afs_int32 aserver, afs_int32 apart, char *avolname, int flags)
+UV_SyncVolume(afs_uint32 aserver, afs_int32 apart, char *avolname, int flags)
{
struct rx_connection *aconn = 0;
afs_int32 j, k, code, vcode, error = 0;
- afs_int32 tverbose, mod, modified = 0;
+ afs_int32 tverbose;
+ afs_int32 mod, modified = 0, deleted = 0;
struct nvldbentry vldbentry;
- afs_int32 volumeid = 0;
+ afs_uint32 volumeid = 0;
volEntries volumeInfo;
struct partList PartList;
- afs_int32 pcnt, rv;
- afs_int32 maxvolid = 0;
+ afs_int32 pcnt;
+ afs_uint32 maxvolid = 0;
volumeInfo.volEntries_val = (volintInfo *) 0;
volumeInfo.volEntries_len = 0;
- if (!aserver && flags) {
- /* fprintf(STDERR,"Partition option requires a server option\n"); */
- ERROR_EXIT(EINVAL);
- }
-
/* Turn verbose logging off and do our own verbose logging */
+ /* tverbose must be set before we call ERROR_EXIT() */
+
tverbose = verbose;
+ if (flags & 2)
+ tverbose = 1;
verbose = 0;
+ if (!aserver && (flags & 1)) {
+ /* fprintf(STDERR,"Partition option requires a server option\n"); */
+ ERROR_EXIT(EINVAL);
+ }
+
/* Read the VLDB entry */
vcode = VLDB_GetEntryByName(avolname, &vldbentry);
if (vcode && (vcode != VL_NOENT)) {
fprintf(STDOUT, "\n");
}
- /* Verify that all of the VLDB entries exist on the repective servers
+ /* Verify that all of the VLDB entries exist on the repective servers
* and partitions (this does not require that avolname be a volume ID).
* Equivalent to a syncserv.
*/
if (!vcode) {
- code = CheckVldb(&vldbentry, &mod);
+ /* Tell CheckVldb not to update if appropriate */
+ if (flags & 2)
+ mod = 1;
+ else
+ mod = 0;
+ code = CheckVldb(&vldbentry, &mod, &deleted);
if (code) {
fprintf(STDERR, "Could not process VLDB entry for volume %s\n",
vldbentry.name);
/* If aserver is given, we will search for the desired volume on it */
if (aserver) {
/* Generate array of partitions on the server that we will check */
- if (!flags) {
+ if (!(flags & 1)) {
code = UV_ListPartitions(aserver, &PartList, &pcnt);
if (code) {
fprintf(STDERR,
ERROR_EXIT(code);
}
} else {
+ if (flags & 2)
+ mod = 1;
+ else
+ mod = 0;
/* Found one, sync it with VLDB entry */
code =
CheckVolume(volumeInfo.volEntries_val, aserver,
- PartList.partId[j], &mod, &maxvolid);
+ PartList.partId[j], &mod, &maxvolid, &vldbentry);
if (code)
ERROR_EXIT(code);
if (mod)
/* Check to see if the RW, BK, and RO IDs exist on any
* partitions. We get the volume IDs from the VLDB.
*/
- rv = 1; /* Read the VLDB entry ? */
for (j = 0; j < MAXTYPES; j++) { /* for RW, RO, and BK IDs */
- if (rv) {
- vcode = VLDB_GetEntryByName(avolname, &vldbentry);
- if (vcode) {
- if (vcode == VL_NOENT)
- break;
- fprintf(STDERR,
- "Could not access the VLDB for volume %s\n",
- avolname);
- ERROR_EXIT(vcode);
- }
- rv = 0;
- }
-
if (vldbentry.volumeId[j] == 0)
continue;
ERROR_EXIT(code);
}
} else {
+ if (flags & 2)
+ mod = 1;
+ else
+ mod = 0;
/* Found one, sync it with VLDB entry */
code =
CheckVolume(volumeInfo.volEntries_val, aserver,
- PartList.partId[k], &mod, &maxvolid);
+ PartList.partId[k], &mod, &maxvolid, &vldbentry);
if (code)
ERROR_EXIT(code);
if (mod)
- modified++, rv++;
+ modified++;
}
if (volumeInfo.volEntries_val)
/* If verbose output, print a summary of what changed */
if (tverbose) {
fprintf(STDOUT, "-- status after --\n");
- code = VLDB_GetEntryByName(avolname, &vldbentry);
- if (code && (code != VL_NOENT)) {
- fprintf(STDERR, "Could not access the VLDB for volume %s\n",
- avolname);
- ERROR_EXIT(code);
- }
- if (modified && (code == VL_NOENT)) {
+ if (deleted) {
fprintf(STDOUT, "\n**entry deleted**\n");
} else if (modified) {
EnumerateEntry(&vldbentry);
error_exit:
/* Now check if the maxvolid is larger than that stored in the VLDB */
if (maxvolid) {
- afs_int32 maxvldbid = 0;
+ afs_uint32 maxvldbid = 0;
code = ubik_VL_GetNewVolumeId(cstruct, 0, 0, &maxvldbid);
if (code) {
fprintf(STDERR,
if (!error)
error = code;
} else if (maxvolid > maxvldbid) {
- afs_int32 id, nid;
+ afs_uint32 id, nid;
id = maxvolid - maxvldbid + 1;
code = ubik_VL_GetNewVolumeId(cstruct, 0, id, &nid);
if (code) {
* optionally, <apart>.
*/
int
-UV_SyncVldb(afs_int32 aserver, afs_int32 apart, int flags, int force)
+UV_SyncVldb(afs_uint32 aserver, afs_int32 apart, int flags, int force)
{
struct rx_connection *aconn;
afs_int32 code, error = 0;
- int i, j, pfail;
+ int i, pfail;
+ unsigned int j;
volEntries volumeInfo;
struct partList PartList;
afs_int32 pcnt;
afs_int32 failures = 0, modifications = 0, tentries = 0;
afs_int32 modified;
afs_uint32 maxvolid = 0;
+ char hoststr[16];
volumeInfo.volEntries_val = (volintInfo *) 0;
volumeInfo.volEntries_len = 0;
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
/* Generate array of partitions to check */
- if (!flags) {
+ if (!(flags & 1)) {
code = UV_ListPartitions(aserver, &PartList, &pcnt);
if (code) {
fprintf(STDERR,
fprintf(STDOUT,
"Processing volume entry %d: %s (%lu) on server %s %s...\n",
j + 1, vi->name, (unsigned long)vi->volid,
- hostutil_GetNameByINet(aserver), pname);
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
+ hostutil_GetNameByINet(aserver), pname);
fflush(STDOUT);
}
- code = CheckVolume(vi, aserver, apart, &modified, &maxvolid);
+ if (flags & 2)
+ modified = 1;
+ else
+ modified = 0;
+ code = CheckVolume(vi, aserver, apart, &modified, &maxvolid, NULL);
if (code) {
PrintError("", code);
failures++;
if (pfail) {
fprintf(STDERR,
"Could not process entries on server %s partition %s\n",
- hostutil_GetNameByINet(aserver), pname);
+ noresolve ?
+ afs_inet_ntoa_r(aserver, hoststr) :
+ hostutil_GetNameByINet(aserver), pname);
}
if (volumeInfo.volEntries_val) {
free(volumeInfo.volEntries_val);
} /* thru all partitions */
- VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n", tentries,
- failures, modifications);
+ if (flags & 2) {
+ VPRINT3("Total entries: %u, Failed to process %d, Would change %d\n",
+ tentries, failures, modifications);
+ } else {
+ VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n",
+ tentries, failures, modifications);
+ }
error_exit:
/* Now check if the maxvolid is larger than that stored in the VLDB */
if (maxvolid) {
- afs_int32 maxvldbid = 0;
+ afs_uint32 maxvldbid = 0;
code = ubik_VL_GetNewVolumeId(cstruct, 0, 0, &maxvldbid);
if (code) {
fprintf(STDERR,
if (!error)
error = code;
} else if (maxvolid > maxvldbid) {
- afs_int32 id, nid;
+ afs_uint32 id, nid;
id = maxvolid - maxvldbid + 1;
code = ubik_VL_GetNewVolumeId(cstruct, 0, id, &nid);
if (code) {
* Some error codes mean the volume is unavailable but
* still exists - so we catch these error codes.
*/
-afs_int32
-VolumeExists(afs_int32 server, afs_int32 partition, afs_int32 volumeid)
+static afs_int32
+VolumeExists(afs_uint32 server, afs_int32 partition, afs_uint32 volumeid)
{
struct rx_connection *conn = (struct rx_connection *)0;
afs_int32 code = -1;
/* CheckVldbRWBK()
*
*/
-afs_int32
+static afs_int32
CheckVldbRWBK(struct nvldbentry * entry, afs_int32 * modified)
{
int modentry = 0;
int idx;
afs_int32 code, error = 0;
char pname[10];
+ char hoststr[16];
if (modified)
*modified = 0;
fprintf(STDERR,
"Transaction call failed for RW volume %u on server %s %s\n",
entry->volumeId[RWVOL],
- hostutil_GetNameByINet(entry->serverNumber[idx]),
+ noresolve ?
+ afs_inet_ntoa_r(entry->serverNumber[idx], hoststr) :
+ hostutil_GetNameByINet(entry->serverNumber[idx]),
pname);
ERROR_EXIT(code);
}
fprintf(STDERR,
"Transaction call failed for BK volume %u on server %s %s\n",
entry->volumeId[BACKVOL],
- hostutil_GetNameByINet(entry->serverNumber[idx]),
+ noresolve ?
+ afs_inet_ntoa_r(entry->serverNumber[idx], hoststr) :
+ hostutil_GetNameByINet(entry->serverNumber[idx]),
pname);
ERROR_EXIT(code);
}
return (error);
}
-int
+static afs_int32
CheckVldbRO(struct nvldbentry *entry, afs_int32 * modified)
{
int idx;
int foundro = 0, modentry = 0;
afs_int32 code, error = 0;
char pname[10];
+ char hoststr[16];
if (modified)
*modified = 0;
/* Check to see if the RO volumes exist and set the RO_EXISTS
- * flag accordingly.
+ * flag accordingly.
*/
for (idx = 0; idx < entry->nServers; idx++) {
if (!(entry->serverFlags[idx] & ITSROVOL)) {
fprintf(STDERR,
"Transaction call failed for RO %u on server %s %s\n",
entry->volumeId[ROVOL],
- hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
+ noresolve ?
+ afs_inet_ntoa_r(entry->serverNumber[idx], hoststr) :
+ hostutil_GetNameByINet(entry->serverNumber[idx]), pname);
ERROR_EXIT(code);
}
}
/* CheckVldb()
* Ensure that <entry> matches with the info on file servers
*/
-afs_int32
-CheckVldb(struct nvldbentry * entry, afs_int32 * modified)
+static afs_int32
+CheckVldb(struct nvldbentry * entry, afs_int32 * modified, afs_int32 * deleted)
{
afs_int32 code, error = 0;
struct nvldbentry storeEntry;
int islocked = 0, mod, modentry, delentry = 0;
- int pass = 0;
+ int pass = 0, doit=1;
- if (modified)
+ if (modified) {
+ if (*modified == 1)
+ doit = 0;
*modified = 0;
+ }
if (verbose) {
fprintf(STDOUT, "_______________________________\n");
fprintf(STDOUT, "\n-- status before -- \n");
code = CheckVldbRWBK(entry, &mod);
if (code)
ERROR_EXIT(code);
- if (mod && (pass == 1))
+ if (mod && (pass == 1) && doit)
goto retry;
if (mod)
modentry++;
code = CheckVldbRO(entry, &mod);
if (code)
ERROR_EXIT(code);
- if (mod && (pass == 1))
+ if (mod && (pass == 1) && doit)
goto retry;
if (mod)
modentry++;
- /* The VLDB entry has been updated. If it as been modified, then
+ /* The VLDB entry has been updated. If it as been modified, then
* write the entry back out the the VLDB.
*/
- if (modentry) {
+ if (modentry && doit) {
if (pass == 1)
goto retry;
if (!(entry->flags & RW_EXISTS) && !(entry->flags & BACK_EXISTS)
- && !(entry->flags & RO_EXISTS)) {
+ && !(entry->flags & RO_EXISTS) && doit) {
/* The RW, BK, nor RO volumes do not exist. Delete the VLDB entry */
code =
ubik_VL_DeleteEntry(cstruct, 0, entry->volumeId[RWVOL],
ERROR_EXIT(code);
}
}
- if (modified)
- *modified = 1;
islocked = 0;
}
+ if (modified && modentry) {
+ *modified = 1;
+ }
+ if (deleted && delentry) {
+ *deleted = 1;
+ }
+
if (verbose) {
fprintf(STDOUT, "-- status after --\n");
if (delentry)
* Synchronise <aserver> <apart>(if flags = 1) with the VLDB.
*/
int
-UV_SyncServer(afs_int32 aserver, afs_int32 apart, int flags, int force)
+UV_SyncServer(afs_uint32 aserver, afs_int32 apart, int flags, int force)
{
struct rx_connection *aconn;
afs_int32 code, error = 0;
struct nvldbentry *vlentry;
afs_int32 si, nsi, j;
+ if (flags & 2)
+ verbose = 1;
+
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
/* Set up attributes to search VLDB */
attributes.server = ntohl(aserver);
attributes.Mask = VLLIST_SERVER;
- if (flags) {
+ if ((flags & 1)) {
attributes.partition = apart;
attributes.Mask |= VLLIST_PARTITION;
}
VPRINT1("Processing VLDB entry %d ...\n", j + 1);
- code = CheckVldb(vlentry, &modified);
+ /* Tell CheckVldb not to update if appropriate */
+ if (flags & 2)
+ modified = 1;
+ else
+ modified = 0;
+ code = CheckVldb(vlentry, &modified, NULL);
if (code) {
PrintError("", code);
fprintf(STDERR,
}
}
- VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n", tentries,
- failures, modifications);
+ if (flags & 2) {
+ VPRINT3("Total entries: %u, Failed to process %d, Would change %d\n",
+ tentries, failures, modifications);
+ } else {
+ VPRINT3("Total entries: %u, Failed to process %d, Changed %d\n",
+ tentries, failures, modifications);
+ }
error_exit:
if (aconn)
return error;
}
-/*rename volume <oldname> to <newname>, changing the names of the related
+/*rename volume <oldname> to <newname>, changing the names of the related
*readonly and backup volumes. This operation is also idempotent.
*salvager is capable of recovering from rename operation stopping halfway.
*to recover run syncserver on the affected machines,it will force renaming to completion. name clashes should have been detected before calling this proc */
afs_int32 tid;
struct rx_connection *aconn;
int islocked;
+ char hoststr[16];
error = 0;
aconn = (struct rx_connection *)0;
goto rvfail;
}
VPRINT1("Recorded the new name %s in VLDB\n", newname);
- /*at this stage the intent to rename is recorded in the vldb, as far as the vldb
+ /*at this stage the intent to rename is recorded in the vldb, as far as the vldb
* is concerned, oldname is lost */
if (entry->flags & RW_EXISTS) {
index = Lp_GetRwIndex(entry);
}
aconn = UV_Bind(entry->serverNumber[index], AFSCONF_VOLUMEPORT);
code =
- AFSVolTransCreate(aconn, entry->volumeId[RWVOL],
+ AFSVolTransCreate_retry(aconn, entry->volumeId[RWVOL],
entry->serverPartition[index], ITOffline, &tid);
if (code) { /*volume doesnot exist */
fprintf(STDERR,
}
aconn = UV_Bind(entry->serverNumber[index], AFSCONF_VOLUMEPORT);
code =
- AFSVolTransCreate(aconn, entry->volumeId[BACKVOL],
+ AFSVolTransCreate_retry(aconn, entry->volumeId[BACKVOL],
entry->serverPartition[index], ITOffline, &tid);
if (code) { /*volume doesnot exist */
fprintf(STDERR,
if (entry->serverFlags[i] & ITSROVOL) {
aconn = UV_Bind(entry->serverNumber[i], AFSCONF_VOLUMEPORT);
code =
- AFSVolTransCreate(aconn, entry->volumeId[ROVOL],
+ AFSVolTransCreate_retry(aconn, entry->volumeId[ROVOL],
entry->serverPartition[i], ITOffline,
&tid);
if (code) { /*volume doesnot exist */
if (!code) {
VPRINT2("Renamed RO volume %s on host %s\n",
nameBuffer,
- hostutil_GetNameByINet(entry->
+ noresolve ?
+ afs_inet_ntoa_r(entry->serverNumber[i], hoststr) :
+ hostutil_GetNameByINet(entry->
serverNumber[i]));
code = AFSVolEndTrans(aconn, tid, &rcode);
tid = 0;
/*report on all the active transactions on volser */
int
-UV_VolserStatus(afs_int32 server, transDebugInfo ** rpntr, afs_int32 * rcount)
+UV_VolserStatus(afs_uint32 server, transDebugInfo ** rpntr, afs_int32 * rcount)
{
struct rx_connection *aconn;
transDebugEntries transInfo;
/*delete the volume without interacting with the vldb */
int
-UV_VolumeZap(afs_int32 server, afs_int32 part, afs_int32 volid)
+UV_VolumeZap(afs_uint32 server, afs_int32 part, afs_uint32 volid)
{
- afs_int32 rcode, ttid, error, code;
+ afs_int32 error;
struct rx_connection *aconn;
- code = 0;
- error = 0;
- ttid = 0;
-
aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
- code = AFSVolTransCreate(aconn, volid, part, ITOffline, &ttid);
- if (code) {
- fprintf(STDERR, "Could not start transaction on volume %lu\n",
- (unsigned long)volid);
- error = code;
- goto zfail;
- }
- code = AFSVolDeleteVolume(aconn, ttid);
- if (code) {
- fprintf(STDERR, "Could not delete volume %lu\n",
- (unsigned long)volid);
- error = code;
- goto zfail;
- }
- code = AFSVolEndTrans(aconn, ttid, &rcode);
- ttid = 0;
- if (!code)
- code = rcode;
- if (code) {
- fprintf(STDERR, "Could not end transaction on volume %lu\n",
- (unsigned long)volid);
- error = code;
- goto zfail;
- }
- zfail:
- if (ttid) {
- code = AFSVolEndTrans(aconn, ttid, &rcode);
- if (!code)
- code = rcode;
- if (!error)
- error = code;
+ error = DoVolDelete(aconn, volid, part,
+ "the", 0, NULL, NULL);
+ if (error == VNOVOL) {
+ EPRINT1(error, "Failed to start transaction on %u\n", volid);
}
+
PrintError("", error);
if (aconn)
rx_DestroyConnection(aconn);
}
int
-UV_SetVolume(afs_int32 server, afs_int32 partition, afs_int32 volid,
+UV_SetVolume(afs_uint32 server, afs_int32 partition, afs_uint32 volid,
afs_int32 transflag, afs_int32 setflag, int sleeptime)
{
struct rx_connection *conn = 0;
ERROR_EXIT(-1);
}
- code = AFSVolTransCreate(conn, volid, partition, transflag, &tid);
+ code = AFSVolTransCreate_retry(conn, volid, partition, transflag, &tid);
if (code) {
fprintf(STDERR, "SetVolumeStatus: TransCreate Failed\n");
ERROR_EXIT(code);
}
int
-UV_SetVolumeInfo(afs_int32 server, afs_int32 partition, afs_int32 volid,
+UV_SetVolumeInfo(afs_uint32 server, afs_int32 partition, afs_uint32 volid,
volintInfo * infop)
{
struct rx_connection *conn = 0;
ERROR_EXIT(-1);
}
- code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
+ code = AFSVolTransCreate_retry(conn, volid, partition, ITOffline, &tid);
if (code) {
fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
ERROR_EXIT(code);
}
int
-UV_GetSize(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
+UV_GetSize(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
afs_int32 fromdate, struct volintSize *vol_size)
{
struct rx_connection *aconn = (struct rx_connection *)0;
aconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
VPRINT1("Starting transaction on volume %u...", afromvol);
- code = AFSVolTransCreate(aconn, afromvol, afrompart, ITBusy, &tid);
+ code = AFSVolTransCreate_retry(aconn, afromvol, afrompart, ITBusy, &tid);
EGOTO1(error_exit, code,
"Could not start transaction on the volume %u to be measured\n",
afromvol);