/* Protos for static routines */
-#if 0
-static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
- 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_uint32 * crtimePtr, afs_uint32 * uptimePtr,
afs_int32 fromtid, afs_int32 fromdate,
manyDests * tr, afs_int32 flags,
void *cookie, manyResults * results);
-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,
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_uint32 okvol, afs_uint32 delvol)
-{
- afs_int32 error, code, tid, rcode;
- error = 0;
- code = 0;
-
- if (okvol == 0) {
- code = AFSVolTransCreate_retry(aconn, delvol, apart, ITOffline, &tid);
- if (!error && code)
- error = code;
- code = AFSVolDeleteVolume(aconn, tid);
- if (!error && code)
- error = code;
- code = AFSVolEndTrans(aconn, tid, &rcode);
- if (!code)
- code = rcode;
- if (!error && code)
- error = code;
- return error;
- } else {
- 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_retry(aconn, delvol, apart, ITOffline, &tid);
- if (!error && code)
- error = code;
- code = AFSVolDeleteVolume(aconn, tid);
- if (!error && code)
- error = code;
- code = AFSVolEndTrans(aconn, tid, &rcode);
- if (!code)
- code = rcode;
- if (!error && code)
- error = code;
- } else
- error = code;
- return error;
- }
-}
-
-#endif
-
/* called by EmuerateEntry, show vldb entry in a reasonable format */
void
SubEnumerateEntry(struct nvldbentry *entry)
int isMixed = 0;
char hoststr[16];
-#ifdef notdef
- fprintf(STDOUT, " readWriteID %-10u ", entry->volumeId[RWVOL]);
- if (entry->flags & VLF_RWEXISTS)
- fprintf(STDOUT, " valid \n");
- else
- fprintf(STDOUT, " invalid \n");
- fprintf(STDOUT, " readOnlyID %-10u ", entry->volumeId[ROVOL]);
- if (entry->flags & VLF_ROEXISTS)
- fprintf(STDOUT, " valid \n");
- else
- fprintf(STDOUT, " invalid \n");
- fprintf(STDOUT, " backUpID %-10u ", entry->volumeId[BACKVOL]);
- if (entry->flags & VLF_BACKEXISTS)
- fprintf(STDOUT, " valid \n");
- else
- fprintf(STDOUT, " invalid \n");
- if ((entry->cloneId != 0) && (entry->flags & VLF_ROEXISTS))
- fprintf(STDOUT, " releaseClone %-10u \n", entry->cloneId);
-#else
if (entry->flags & VLF_RWEXISTS)
fprintf(STDOUT, " RWrite: %-10u", entry->volumeId[RWVOL]);
if (entry->flags & VLF_ROEXISTS)
if ((entry->cloneId != 0) && (entry->flags & VLF_ROEXISTS))
fprintf(STDOUT, " RClone: %-10lu", (unsigned long)entry->cloneId);
fprintf(STDOUT, "\n");
-#endif
fprintf(STDOUT, " number of sites -> %lu\n",
(unsigned long)entry->nServers);
for (i = 0; i < entry->nServers; i++) {
tid = 0;
error = 0;
+ memset(&storeEntry, 0, sizeof(struct nvldbentry));
+
init_volintInfo(&tstatus);
tstatus.maxquota = aquota;
afs_int32 vcode;
struct nvldbentry entry, storeEntry; /*the new vldb entry */
+ memset(&storeEntry, 0, sizeof(struct nvldbentry));
+
aconn = (struct rx_connection *)0;
error = 0;
entry.flags = VLF_RWEXISTS; /* this records that rw volume exists */
entry.serverFlags[0] = VLSF_RWVOL; /*this rep site has rw vol */
entry.volumeId[RWVOL] = aid;
-#ifdef notdef
- entry.volumeId[ROVOL] = anewid + 1; /* rw,ro, bk id are related in the default case */
- entry.volumeId[BACKVOL] = *anewid + 2;
-#else
entry.volumeId[ROVOL] = 0;
entry.volumeId[BACKVOL] = 0;
-#endif
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 */
afs_int32 avoltype = -1, vtype;
int notondisk = 0, notinvldb = 0;
+ memset(&storeEntry, 0, sizeof(struct nvldbentry));
+
/* Find and read bhe VLDB entry for this volume */
code = ubik_VL_SetLock(cstruct, 0, avolid, avoltype, VLOP_DELETE);
if (code) {
afs_uint32 roserver = 0;
struct rx_connection *aconn;
+ memset(&storeEntry, 0, sizeof(struct nvldbentry));
+
vcode =
ubik_VL_SetLock(cstruct, 0, entry->volumeId[RWVOL], RWVOL,
VLOP_MOVE);
}
}
+ /* volume must be inaccessible during this process */
+ code = UV_SetVolume(server, partition, volid, ITOffline, VTOutOfService, 0);
+ if (code != 0) {
+ fprintf(STDERR, "Taking RO volume %u offline failed with code %d.\n",
+ volid, code);
+ goto error_exit;
+ }
+
aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
code = AFSVolConvertROtoRWvolume(aconn, partition, volid);
if (code) {
PrintError("convertROtoRW ", code);
goto error_exit;
}
+
+ /*
+ * Since the inService flag is copied from the RO volume, the new RW copy is
+ * offline. Change the status of this RW volume to online.
+ */
+ code = UV_SetVolume(server, partition, entry->volumeId[RWVOL], ITOffline,
+ 0 /* online */, 0);
+ if (code != 0) {
+ fprintf(STDERR, "Warning: Attempt to set RW volume %u as online failed "
+ "with code %d.\n", entry->volumeId[RWVOL], code);
+ }
+
/* Update the VLDB to match what we did on disk as much as possible. */
/* If the converted RO was in the VLDB, make it look like the new RW. */
if (roserver) {
fflush(STDOUT);
if (fscanf(stdin, "%c", &in) < 1)
in = 0;
- if (fscanf(stdin, "%c", &lf) < 0) /* toss away */
- ; /* don't care */
+ if (fscanf(stdin, "%c", &lf) < 0) {
+ /* toss away; don't care */
+ }
if (in == 'y') {
fprintf(STDOUT, "type control-c\n");
while (1) {
fflush(STDOUT);
if (fscanf(stdin, "%c", &in) < 1)
in = 0;
- if (fscanf(stdin, "%c", &lf) < 0) /* toss away */
- ; /* don't care */
+ if (fscanf(stdin, "%c", &lf) < 0) {
+ /* toss away, don't care */
+ }
if (in == 'y') {
fprintf(STDOUT, "type control-c\n");
while (1) {
fflush(STDOUT);
if (fscanf(stdin, "%c", &in) < 1)
in = 0;
- if (fscanf(stdin, "%c", &lf) < 0) /* toss away */
- ; /* don't care */
+ if (fscanf(stdin, "%c", &lf) < 0) {
+ /* toss away; don't care */
+ }
if (in == 'y') {
fprintf(STDOUT, "type control-c\n");
while (1) {
}
/* or drop through */
}
-#ifdef notdef
- /* This is tricky. File server is very stupid, and if you mark the volume
- * as VTOutOfService, it may mark the *good* instance (if you're moving
- * between partitions on the same machine) as out of service. Since
- * we're cleaning this code up in DEcorum, we're just going to kludge around
- * it for now by removing this call. */
- /* already out of service, just zap it now */
- code =
- AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
- if (code) {
- fprintf(STDERR,
- "Failed to set the flags to make the old source volume offline\n");
- goto mfail;
- }
-#endif
if (atoserver != afromserver) {
/* set forwarding pointer for moved volumes */
VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
if (!(flags & RV_NOCLONE)) {
code = DoVolDelete(fromconn, newVol, afrompart,
"cloned", 0, NULL, NULL);
- if (code) {
- if (code == VNOVOL) {
- EPRINT1(code, "Failed to start transaction on %u\n", newVol);
- }
+ if (code && code != VNOVOL) {
error = code;
goto mfail;
}
+
+ code = 0; /* clone missing? that's okay */
}
/* fall through */
fflush(STDOUT);
if (fscanf(stdin, "%c", &in) < 1)
in = 0;
- if (fscanf(stdin, "%c", &lf) < 0) /* toss away */
- ; /* don't care */
+ if (fscanf(stdin, "%c", &lf) < 0) { /* toss away */
+ /* don't care */
+ }
if (in == 'y') {
fprintf(STDOUT, "type control-c\n");
while (1) {
if (!(flags & RV_NOCLONE)) {
code = DoVolDelete(fromconn, cloneVol, afrompart,
"cloned", 0, NULL, NULL);
- if (code) {
- if (code == VNOVOL) {
- EPRINT1(code, "Failed to start transaction on %u\n", cloneVol);
- }
+ if (code && code != VNOVOL) {
error = code;
goto mfail;
}
+
+ code = 0; /* clone missing? that's ok */
}
if (!(flags & RV_NOVLDB)) {
/* common cleanup - delete local clone */
if (cloneVol) {
- code = DoVolDelete(fromconn, cloneVol, afrompart,
- "clone", 0, NULL, "Recovery:");
- if (code == VNOVOL) {
- EPRINT1(code, "Recovery: Failed to start transaction on %u\n", cloneVol);
- }
+ DoVolDelete(fromconn, cloneVol, afrompart, "clone", 0, NULL,
+ "Recovery:");
}
done: /* routine cleanup */
goto bfail;
}
- VDONE;
-
/* Will update the vldb below */
bfail:
}
}
- VDONE;
-
bfail:
if (ttid) {
code = AFSVolEndTrans(aconn, ttid, &rcode);
}
}
-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;
-}
-
/**
* Release a volume to read-only sites
*
- * Release volume <afromvol> on <afromserver> <afrompart> to all
- * its RO sites (full release). Unless the previous release was
- * incomplete: in which case we bring the remaining incomplete
- * volumes up to date with the volumes that were released
- * successfully.
+ * Release volume <afromvol> on <afromserver> <afrompart> to all its RO
+ * sites (complete release), unless the previous release was incomplete
+ * or new sites were added without changes to the read-write volume, in
+ * which case we bring the remaining volumes up to date with the volumes
+ * that were previously released successfully.
*
* Will create a clone from the RW, then dump the clone out to
* the remaining replicas. If there is more than 1 RO sites,
* @param[in] flags bitmap of options
* REL_COMPLETE - force a complete release
* REL_FULLDUMPS - force full dumps
- * REL_STAYUP - dump to clones to avoid offline time
*/
int
UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
int justnewsites = 0; /* are we just trying to release to new RO sites? */
int sites = 0; /* number of ro sites */
int new_sites = 0; /* number of ro sites markes as new */
- int stayUp = (flags & REL_STAYUP);
typedef enum {
- CR_RECOVER = 0x0000, /**< not complete: a recovery from a previous failed release */
+ CR_PARTIAL = 0x0000, /**< just new sites added or recover from a previous failed release */
CR_FORCED = 0x0001, /**< complete: forced by caller */
CR_LAST_OK = 0x0002, /**< complete: no sites have been marked as new release */
CR_ALL_NEW = 0x0004, /**< complete: all sites have been marked as new release */
CR_RO_MISSING = 0x0010, /**< complete: ro clone is missing */
} complete_release_t;
- complete_release_t complete_release = CR_RECOVER;
+ complete_release_t complete_release = CR_PARTIAL;
memset(remembertime, 0, sizeof(remembertime));
memset(&results, 0, sizeof(results));
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] & VLSF_ROVOL)) {
- 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,
"This is a recovery of previously failed release\n");
} else {
fprintf(STDOUT, "This is a complete release of volume %u", afromvol);
- /* Give the reasons for a complete release, except if only CR_LAST_OK. */
- if (complete_release != CR_LAST_OK) {
+ if (complete_release == CR_LAST_OK) {
+ if (justnewsites) {
+ tried_justnewsites = 1;
+ fprintf(STDOUT, "\nThere are new RO sites; we will try to "
+ "only release to new sites");
+ }
+ } else {
char *sep = " (";
if (complete_release & CR_FORCED) {
fprintf(STDOUT, "%sforced", sep);
fprintf(STDOUT, ")");
}
fprintf(STDOUT, "\n");
- if (justnewsites) {
- tried_justnewsites = 1;
- fprintf(STDOUT, "There are new RO sites; we will try to "
- "only release to new sites\n");
- }
}
}
* (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] & VLSF_DONTUSE))) {
code = DoVolDelete(fromconn,
- stayUp ? entry.volumeId[ROVOL] : cloneVolId,
+ cloneVolId,
afrompart, "the", 0, NULL, NULL);
if (code && (code != VNOVOL))
ERROREXIT(code);
if (roclone) {
strcpy(vname, entry.name);
- if (stayUp)
- strcat(vname, ".roclone");
- else
- strcat(vname, ".readonly");
+ strcat(vname, ".readonly");
} else {
strcpy(vname, "readonly-clone-temp");
}
code = DoVolClone(fromconn, afromvol, afrompart, readonlyVolume,
- cloneVolId, (roclone && !stayUp)?"permanent RO":
+ cloneVolId, roclone?"permanent RO":
"temporary RO", NULL, vname, NULL, &volstatus, NULL);
if (code) {
error = code;
/* Remember clone volume ID in case we fail or are interrupted */
entry.cloneId = cloneVolId;
- if (roclone && !stayUp) {
+ if (roclone) {
/* Bring the RO clone online - though not if it's a temporary clone */
VPRINT1("Starting transaction on RO clone volume %u...",
cloneVolId);
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 */
- complete_release = CR_RECOVER;
+ complete_release = CR_PARTIAL;
} else if (tried_justnewsites) {
VPRINT("RW vol has changed; releasing to all sites\n");
}
*/
strcpy(vname, entry.name);
- if (stayUp)
- strcat(vname, ".roclone");
- else
- strcat(vname, ".readonly");
+ strcat(vname, ".readonly");
memset(&cookie, 0, sizeof(cookie));
strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
cookie.type = ROVOL;
cookie.clone = 0;
/* how many to do at once, excluding clone */
- if (stayUp || justnewsites)
+ if (justnewsites)
nservers = entry.nServers; /* can do all, none offline */
else
nservers = entry.nServers / 2;
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 && !complete_release) {
- entry.serverFlags[roindex] |= VLSF_NEWREPSITE;
- entry.serverFlags[roindex] &= ~VLSF_DONTUSE;
- entry.flags |= VLF_ROEXISTS;
-
- releasecount++;
- }
-
/* For each index in the VLDB */
for (vldbindex = 0; vldbindex < entry.nServers;) {
/* Get a transaction on the replicas. Pick replicas which have an old release. */
for (volcount = 0;
((volcount < nservers) && (vldbindex < entry.nServers));
vldbindex++) {
- if (!stayUp && !justnewsites) {
+ if (!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
&(replicas[volcount].trans),
&(times[volcount].crtime),
&(times[volcount].uptime),
- origflags, stayUp?cloneVolId:0);
+ origflags, 0);
if (code)
continue;
/* Do a full dump when forced by the caller. */
VPRINT("This will be a full dump: forced\n");
thisdate = 0;
- } else if (!complete_release) {
- /* If this release is a recovery of a failed release, we can't be
- * sure the creation date is good, so do a full dump.
- */
- VPRINT("This will be a full dump: previous release failed\n");
+ } else if (complete_release == CR_PARTIAL) {
+ if (justnewsites) {
+ VPRINT("This will be a full dump: read-only volume needs be created for new site\n");
+ } else {
+ /*
+ * We cannot be sure the creation date is good since the previous
+ * release failed, so do a full dump.
+ */
+ VPRINT("This will be a full dump: previous release failed\n");
+ }
thisdate = 0;
} else if (times[volcount].crtime == 0) {
/* A full dump is needed for a new read-only volume. */
code = CheckTrans(fromconn, &fromtid, afrompart, &orig_status);
if (code) {
- code = ENOENT;
+ error = ENOENT;
goto rfail;
}
if (verbose) {
fprintf(STDOUT, "Starting ForwardMulti from %lu to %u on %s",
- (unsigned long)cloneVolId, stayUp?
- cloneVolId:entry.volumeId[ROVOL],
+ (unsigned long)cloneVolId,
+ entry.volumeId[ROVOL],
noresolve ? afs_inet_ntoa_r(entry.serverNumber[times[0].
vldbEntryIndex], hoststr) :
hostutil_GetNameByINet(entry.
}
}
- 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] &= ~VLSF_NEWREPSITE;
- entry.serverFlags[roindex] |= VLSF_DONTUSE;
- } else {
- entry.serverFlags[roindex] |= VLSF_NEWREPSITE;
- entry.serverFlags[roindex] &= ~VLSF_DONTUSE;
- entry.flags |= VLF_ROEXISTS;
- 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);
- }
- } else {
- PrintError("Unable to end transaction on temporary clone: ", code);
- }
-
- 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 (!times[s].crtime) {
- entry.serverFlags[vldbindex] |= VLSF_DONTUSE;
- }
- entry.serverFlags[vldbindex] &= ~VLSF_NEWREPSITE;
- PrintError("Failed: ",
- code);
- } else
- VDONE;
-
- if (entry.serverFlags[vldbindex] != VLSF_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] &= ~VLSF_NEWREPSITE;
- entry.serverFlags[s] |= VLSF_DONTUSE;
- if (code != ENOENT) {
- PrintError("Failed to set correct names and ids: ",
- code);
- }
- } else
- VDONE;
- }
-
- VPRINT("Marking temporary clone for deletion...\n");
- code = AFSVolSetFlags(toconns[s],
- replicas[s].trans,
- VTDeleteOnSalvage |
- VTOutOfService);
- if (code)
- EPRINT(code, "Failed: ");
- else
- VDONE;
-
- VPRINT("Ending transaction on temporary clone...\n");
- code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode);
- 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;
- }
- }
- }
-
- /* done. put the vldb entry in the success tail case*/
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 */
/* End the transaction on the cloned volume */
code = AFSVolEndTrans(fromconn, fromtid, &rcode);
entry.cloneId = 0;
/* All the ROs were release successfully. Remove the temporary clone */
- if (!roclone || stayUp) {
+ if (!roclone) {
if (verbose) {
fprintf(STDOUT, "Deleting the releaseClone %lu ...",
(unsigned long)cloneVolId);
}
code = DoVolDelete(fromconn, cloneVolId, afrompart, NULL, 0, NULL,
NULL);
- ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
+ if (code && code != VNOVOL)
+ ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
VDONE;
}
afs_int32 fromtid = 0, rcode = 0;
afs_int32 code = 0, error = 0;
afs_uint32 tmpVol;
- char vname[64];
time_t tmv = fromdate;
+ char *volName = NULL;
if (setjmp(env))
ERROR_EXIT(EPIPE);
afromvol);
VEDONE;
+ VEPRINT1("Getting the name for volume %u ...", afromvol);
+ code = AFSVolGetName(fromconn, fromtid, &volName);
+ EGOTO1(error_exit, code,
+ "Failed to get the name of the volume %u\n",afromvol);
+ VEDONE;
+
/* Get a clone id */
VEPRINT1("Allocating new volume id for clone of volume %u ...", afromvol);
tmpVol = clonevol;
/* Do the clone. Default flags on clone are set to delete on salvage and out of service */
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, &tmpVol);
+ AFSVolClone(fromconn, fromtid, 0, readonlyVolume, volName, &tmpVol);
clonevol = tmpVol;
EGOTO1(error_exit, code, "Failed to clone the source volume %u\n",
afromvol);
VEDONE;
error_exit:
+ if (volName)
+ free(volName);
+
/* now delete the clone */
VEPRINT1("Deleting the cloned volume %u ...", clonevol);
code = AFSVolDeleteVolume(fromconn, clonetid);
int reuseID;
afs_int32 volflag, voltype, volsertype;
afs_int32 oldCreateDate, oldUpdateDate, newCreateDate, newUpdateDate;
+ VolumeId oldCloneId = 0;
+ VolumeId oldBackupId = 0;
int index, same, errcode;
char apartName[10];
char hoststr[16];
noresolve ? afs_inet_ntoa_r(toserver, hoststr) :
hostutil_GetNameByINet(toserver), partName);
fflush(STDOUT);
- code =
- AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid, &pvolid,
- &totid);
- if (code) {
- if (flags & RV_FULLRST) { /* full restore: delete then create anew */
- code = DoVolDelete(toconn, pvolid, topart, "the previous", 0,
- &tstatus, NULL);
- if (code && code != VNOVOL) {
- error = code;
- goto refail;
- }
- code =
- AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid,
- &pvolid, &totid);
+ /*
+ * Obtain a transaction and get the status of the target volume. Create a new
+ * volume if the target volume does not already exist.
+ */
+ memset(&tstatus, 0, sizeof(tstatus));
+ if ((flags & RV_FULLRST) != 0) {
+ /* Full restore: Delete existing volume then create anew. */
+ code = DoVolDelete(toconn, pvolid, topart, "the previous", 0, &tstatus, NULL);
+ if (code && code != VNOVOL) {
+ error = code;
+ goto refail;
+ }
+ code = AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid,
+ &pvolid, &totid);
+ EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
+ } else {
+ /* Incremental restore: Obtain a transaction on the existing volume. */
+ code = AFSVolTransCreate_retry(toconn, pvolid, topart, ITOffline, &totid);
+ if (code == 0) {
+ code = AFSVolGetStatus(toconn, totid, &tstatus);
+ EGOTO1(refail, code, "Could not get timestamp from volume %u\n", pvolid);
+ } else if (code == VNOVOL) {
+ code = AFSVolCreateVolume(toconn, topart, tovolreal, volsertype,
+ pparentid, &pvolid, &totid);
EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
} else {
- code =
- AFSVolTransCreate_retry(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);
-
+ EGOTO1(refail, code, "Failed to start transaction on %u\n", pvolid);
}
- oldCreateDate = tstatus.creationDate;
- oldUpdateDate = tstatus.updateDate;
- } else {
- oldCreateDate = 0;
- oldUpdateDate = 0;
}
+ oldCreateDate = tstatus.creationDate;
+ oldUpdateDate = tstatus.updateDate;
+ oldCloneId = tstatus.cloneID;
+ oldBackupId = tstatus.backupID;
cookie.parent = pparentid;
cookie.type = voltype;
error = code;
goto refail;
}
- code = AFSVolSetIdsTypes(toconn, totid, tovolreal, voltype, pparentid, 0, 0);
+ code = AFSVolSetIdsTypes(toconn, totid, tovolreal, voltype, pparentid,
+ oldCloneId, oldBackupId);
if (code) {
- fprintf(STDERR, "Could not set the right type and ID on %lu\n",
+ fprintf(STDERR, "Could not set the right type and IDs on %lu\n",
(unsigned long)pvolid);
error = code;
goto refail;
LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
return (vcode);
}
- VDONE;
+ fprintf(STDOUT, " done\n");
+ fflush(STDOUT);
}
return 0;
}
afs_int32 code = 0;
volEntries volumeInfo;
- code = 0;
*size = 0;
*resultPtr = (volintInfo *) 0;
volumeInfo.volEntries_val = (volintInfo *) 0; /*this hints the stub to allocate space */
aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
/* Set up attributes to search VLDB */
+ memset(&attributes, 0, sizeof(attributes));
attributes.server = ntohl(aserver);
attributes.Mask = VLLIST_SERVER;
if ((flags & 1)) {
goto rvfail;
}
islocked = 1;
+
+ /*
+ * Match the flags we just set via SetLock,
+ * so we don't invalidate our compare below.
+ */
+ entry->flags &= ~VLOP_ALLOPERS;
+ entry->flags |= VLOP_ADDSITE;
+
+ /*
+ * Now get the entry again (under lock) and
+ * verify the volume hasn't otherwise changed.
+ */
+ vcode = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, &storeEntry);
+ if (vcode) {
+ fprintf(STDERR,
+ "Could not obtain the VLDB entry for the volume %u\n",
+ entry->volumeId[RWVOL]);
+ error = vcode;
+ goto rvfail;
+ }
+ /* Convert to net order to match entry, which was passed in net order. */
+ MapHostToNetwork(&storeEntry);
+ if (memcmp(entry, &storeEntry, sizeof(*entry)) != 0) {
+ fprintf(STDERR,
+ "VLDB entry for volume %u has changed; "
+ "please reissue the command.\n",
+ entry->volumeId[RWVOL]);
+ error = VL_BADENTRY; /* an arbitrary choice, but closest to the truth */
+ goto rvfail;
+ }
+
strncpy(entry->name, newname, VOLSER_OLDMAXVOLNAME);
+ /* Note that we are reusing storeEntry. */
MapNetworkToHost(entry, &storeEntry);
vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry, 0);
if (vcode) {
{
int i, count;
+ memset(new, 0, sizeof(struct nvldbentry));
+
/*copy all the fields */
strcpy(new->name, old->name);
/* new->volumeType = old->volumeType;*/