return error;
}
+/* Convert volume from RO to RW; adjust the VLDB entry to match.
+ * The nvldbentry passed to us has already been MapHostToNetwork'd
+ * by the caller.
+ */
+
+int
+UV_ConvertRO(afs_uint32 server, afs_uint32 partition, afs_uint32 volid,
+ struct nvldbentry *entry)
+{
+ afs_int32 code, i, same;
+ struct nvldbentry checkEntry, storeEntry;
+ afs_int32 vcode;
+ afs_int32 rwindex = 0;
+ afs_uint32 rwserver = 0;
+ afs_int32 roindex = 0;
+ afs_uint32 roserver = 0;
+ struct rx_connection *aconn;
+
+ vcode =
+ ubik_VL_SetLock(cstruct, 0, entry->volumeId[RWVOL], RWVOL,
+ VLOP_MOVE);
+ if (vcode) {
+ fprintf(STDERR,
+ "Unable to lock volume %lu, code %d\n",
+ (unsigned long)entry->volumeId[RWVOL],vcode);
+ PrintError("", vcode);
+ return -1;
+ }
+
+ /* make sure the VLDB entry hasn't changed since we started */
+ memset(&checkEntry, 0, sizeof(checkEntry));
+ vcode = VLDB_GetEntryByID(volid, -1, &checkEntry);
+ if (vcode) {
+ fprintf(STDERR,
+ "Could not fetch the entry for volume %lu from VLDB\n",
+ (unsigned long)volid);
+ PrintError("convertROtoRW ", vcode);
+ code = vcode;
+ goto error_exit;
+ }
+
+ MapHostToNetwork(&checkEntry);
+ entry->flags &= ~VLOP_ALLOPERS; /* clear any stale lock operation flags */
+ entry->flags |= VLOP_MOVE; /* set to match SetLock operation above */
+ if (memcmp(entry, &checkEntry, sizeof(*entry)) != 0) {
+ fprintf(STDERR,
+ "VLDB entry for volume %lu has changed; please reissue the command.\n",
+ (unsigned long)volid);
+ code = -1;
+ goto error_exit;
+ }
+
+ /* extract information from the original entry */
+ for (i = 0; i < entry->nServers; i++) {
+ if (entry->serverFlags[i] & ITSRWVOL) {
+ rwindex = i;
+ rwserver = entry->serverNumber[i];
+ /* rwpartition = entry->serverPartition[i]; */
+ if (roserver)
+ break;
+ } else if ((entry->serverFlags[i] & ITSROVOL) && !roserver) {
+ same = VLDB_IsSameAddrs(server, entry->serverNumber[i], &code);
+ if (code) {
+ fprintf(STDERR,
+ "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
+ server, code);
+ code = ENOENT;
+ goto error_exit;
+ }
+ if (same) {
+ roindex = i;
+ roserver = entry->serverNumber[i];
+ /* ropartition = entry->serverPartition[i]; */
+ if (rwserver)
+ break;
+ }
+ }
+ }
+
+ aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
+ code = AFSVolConvertROtoRWvolume(aconn, partition, volid);
+ if (code) {
+ fprintf(STDERR,
+ "Converting RO volume %lu to RW volume failed with code %d\n",
+ (unsigned long)volid, code);
+ PrintError("convertROtoRW ", code);
+ goto error_exit;
+ }
+ /* 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) {
+ entry->serverFlags[roindex] = ITSRWVOL;
+ } else {
+ /* Add a new site entry for the newly created RW. It's possible
+ * (but unlikely) that we are already at MAXNSERVERS and that this
+ * new site will invalidate the whole VLDB entry; however,
+ * VLDB_ReplaceEntry will detect this and return VL_BADSERVER,
+ * so we need no extra guard logic here.
+ */
+ afs_int32 newrwindex = entry->nServers;
+ (entry->nServers)++;
+ entry->serverNumber[newrwindex] = server;
+ entry->serverPartition[newrwindex] = partition;
+ entry->serverFlags[newrwindex] = ITSRWVOL;
+ }
+ entry->flags |= RW_EXISTS;
+ entry->flags &= ~BACK_EXISTS;
+
+ /* if the old RW was in the VLDB, remove it by decrementing the number */
+ /* of servers, replacing the RW entry with the last entry, and zeroing */
+ /* out the last entry. */
+ if (rwserver) {
+ (entry->nServers)--;
+ if (rwindex != entry->nServers) {
+ entry->serverNumber[rwindex] = entry->serverNumber[entry->nServers];
+ entry->serverPartition[rwindex] =
+ entry->serverPartition[entry->nServers];
+ entry->serverFlags[rwindex] = entry->serverFlags[entry->nServers];
+ entry->serverNumber[entry->nServers] = 0;
+ entry->serverPartition[entry->nServers] = 0;
+ entry->serverFlags[entry->nServers] = 0;
+ }
+ }
+ entry->flags &= ~RO_EXISTS;
+ for (i = 0; i < entry->nServers; i++) {
+ if (entry->serverFlags[i] & ITSROVOL) {
+ if (!(entry->serverFlags[i] & (RO_DONTUSE | NEW_REPSITE)))
+ entry->flags |= RO_EXISTS;
+ }
+ }
+ MapNetworkToHost(entry, &storeEntry);
+ code =
+ VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry,
+ (LOCKREL_OPCODE | LOCKREL_AFSID |
+ LOCKREL_TIMESTAMP));
+ if (code) {
+ fprintf(STDERR,
+ "Warning: volume converted, but vldb update failed with code %d!\n",
+ code);
+ }
+
+ error_exit:
+ vcode = UV_LockRelease(entry->volumeId[RWVOL]);
+ if (vcode) {
+ fprintf(STDERR,
+ "Unable to unlock volume %lu, code %d\n",
+ (unsigned long)entry->volumeId[RWVOL],vcode);
+ PrintError("", vcode);
+ }
+ return code;
+}
+
+
/* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
* <atopart>. The operation is almost idempotent. The following
* flags are recognized:
goto fail;
}
- if (tmpVolId)
- strcat(volname, ".roclone");
- else
- strcat(volname, ".readonly");
-
if (verbose) {
fprintf(STDOUT,
"Creating new volume %lu on replication site %s: ",
return code;
}
-/* UV_ReleaseVolume()
- * 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.
- * forceflag: Performs a full release.
+/**
+ * Release a volume to read-only sites
*
- * 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.
+ * 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.
+ *
+ * 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.
+ *
+ * @param[in] afromvol volume to be released
+ * @param[in] afromserver server containing afromvol
+ * @param[in] afrompart partition containing afromvol
+ * @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,
- afs_int32 afrompart, int forceflag, int stayUp)
+ afs_int32 afrompart, int flags)
{
char vname[64];
afs_int32 code = 0;
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 */
* vldb flags.
*
* The caller can override the vldb flags check using the -force
- * flag, to force this to be a complete release.
+ * or -force-reclone flag, to force this to be a complete release.
*/
for (i = 0; i < entry.nServers; i++) {
if (entry.serverFlags[i] & ITSROVOL) {
origflags[i] = entry.serverFlags[i];
}
- if (forceflag) {
+ if (flags & REL_COMPLETE) {
complete_release |= CR_FORCED;
}
&& !(complete_release & CR_FORCED)) {
if (notreleased && notreleased != sites) {
/* we have some new unreleased sites. try to just release to those,
- * if the RW has not changed. The caller can override with -force. */
+ * if the RW has not changed. The caller can override with -force
+ * or with -force-reclone. */
justnewsites = 1;
}
}
continue;
/* Thisdate is the date from which we want to pick up all changes */
- if (forceflag) {
+ if (flags & REL_FULLDUMPS) {
/* Do a full dump when forced by the caller. */
VPRINT("This will be a full dump: forced\n");
thisdate = 0;
struct rx_connection * volatile fromconn = NULL;
afs_int32 volatile fromtid = 0;
- afs_int32 rxError = 0, rcode = 0;
+ afs_int32 rcode = 0;
afs_int32 code, error = 0;
afs_int32 tmp;
time_t tmv = fromdate;
error_exit:
if (fromcall) {
- code = rx_EndCall(fromcall, rxError);
+ code = rx_EndCall(fromcall, 0);
if (code && code != RXGEN_OPCODE)
fprintf(STDERR, "Error in rx_EndCall\n");
if (code && !error)
afs_uint32 volatile clonevol = 0;
afs_int32 tmp;
- afs_int32 fromtid = 0, rxError = 0, rcode = 0;
+ afs_int32 fromtid = 0, rcode = 0;
afs_int32 code = 0, error = 0;
afs_uint32 tmpVol;
char vname[64];
}
if (fromcall) {
- code = rx_EndCall(fromcall, rxError);
+ code = rx_EndCall(fromcall, 0);
if (code) {
fprintf(STDERR, "Error in rx_EndCall\n");
if (!error)
struct rx_connection *toconn, *tempconn;
struct rx_call *tocall;
afs_int32 totid, code, rcode, vcode, terror = 0;
- afs_int32 rxError = 0;
struct volser_status tstatus;
struct volintInfo vinfo;
char partName[10];
error = code;
goto refail;
}
- terror = rx_EndCall(tocall, rxError);
+ terror = rx_EndCall(tocall, 0);
tocall = (struct rx_call *)0;
if (terror) {
fprintf(STDERR, "rx_EndCall Failed \n");
}
refail:
if (tocall) {
- code = rx_EndCall(tocall, rxError);
+ code = rx_EndCall(tocall, 0);
if (!error)
error = code;
}