X-Git-Url: https://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2Fvolser%2Fvsprocs.c;h=6bd35d6b4b5f441ef58f07709a8545c1ba1f1a8a;hp=9366dcb94e2bceb52dd9fb8d9f660081769d027c;hb=9fca71287d2c9730139a0472c6ee891603e72672;hpb=b78b7f0c3454be02048e4533ee26ef28dc8f78ff diff --git a/src/volser/vsprocs.c b/src/volser/vsprocs.c index 9366dcb..6bd35d6 100644 --- a/src/volser/vsprocs.c +++ b/src/volser/vsprocs.c @@ -1338,6 +1338,159 @@ cfail: 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 on to * . The operation is almost idempotent. The following * flags are recognized: