B<vos addsite> S<<< B<-server> <I<machine name for new site>> >>>
S<<< B<-partition> <I<partition name for new site>> >>>
- S<<< B<-id> <I<volume name or ID>> >>> [B<-valid>]
- S<<< [B<-cell> <I<cell name>>] >>> [B<-noauth>] [B<-localauth>]
+ S<<< B<-id> <I<volume name or ID>> >>>
+ S<<< [B<-roid> <I<readonly volume name or ID>>] >>>
+ [B<-valid>] S<<< [B<-cell> <I<cell name>>] >>>
+ [B<-noauth>] [B<-localauth>]
[B<-verbose>] [B<-help>]
B<vos ad> S<<< B<-s> <I<machine name for new site>> >>>
S<<< B<-p> <I<partition name for new site>> >>>
- S<<< B<-i> <I<volume name or ID>> >>> [B<-va>]
- S<<< [B<-c> <I<cell name>>] >>> [B<-n>] [B<-l>] [B<-ve>] [B<-h>]
+ S<<< B<-i> <I<volume name or ID>> >>>
+ S<<< [B<-r> <I<readonly volume name or ID>>] >>>
+ [B<-va>] [B<-c> <I<cell name>>] >>> [B<-n>] [B<-l>] [B<-v>] [B<-h>]
=for html
</div>
Specifies either the complete name or volume ID number of the read/write
source volume.
+=item B<-roid> <I<readonly volume name or ID>>
+
+Specifies either the complete name or volume ID number of the readonly
+volume. This will only be honored if the source read/write volume does not
+already have a readonly volume ID associated with it. If the source
+read/write volume already has a readonly volume ID, the specified ID will
+be ignored, and a warning will be printed.
+
+If this is not specified and the source read/write volume does not already
+have a readonly volume ID, a volume ID for the readonly volume will be
+allocated for it when the B<vos release> command is run.
+
+The automatically allocated readonly volume IDs should be fine for almost
+all cases, so you should almost never need to specify this option.
+
=item B<-valid>
Marks the site as up-to-date in the VLDB. You should only do this if the
B<vos create> S<<< B<-server> <I<machine name>> >>> S<<< B<-partition> <I<partition name>> >>>
S<<< B<-name> <I<volume name>> >>> S<<< [B<-maxquota> <I<initial quota (KB)>>] >>>
+ S<<< [B<-id> <I<volume ID>>] >>> S<<< [B<-roid> <I<readonly volume ID>>] >>>
S<<< [B<-cell> <I<cell name>>] >>> [B<-noauth>] [B<-localauth>] [B<-verbose>]
[B<-help>]
B<vos cr> S<<< B<-s> <I<machine name>> >>> S<<< B<-p> <I<partition name>> >>>
S<<< B<-na> <I<volume name>> >>> S<<< [B<-m> <I<initial quota (KB)>>] >>>
+ S<<< [B<-i> <I<volume ID>>] >>> S<<< [B<-r> <I<readonly volume ID>>] >>>
S<<< [B<-c> <I<cell name>>] >>> [B<-no>] [B<-l>] [B<-v>] [B<-h>]
=for html
houses the volume places an absolute limit on its size. If this argument
is omitted, the default value is C<5000>.
+=item B<-id> <I<volume ID>>
+
+Specifies the volume ID for the read/write volume. If this options is not
+specified, or the given volume ID is 0, a volume ID will be allocated for
+the volume automatically. The volume IDs allocated should be fine for
+almost all cases, so you should almost never need to specify this option.
+
+=item B<-roid> <I<readonly volume ID>>
+
+Specifies the volume ID for the readonly volume corresponding to the
+read/write volume that is being created. The readonly volume will not be
+created; this merely specifies what volume ID the readonly volume will use
+when it is created. If a volume ID of 0 is specified here, no readonly
+volume ID will be assigned to the created volume immediately. A readonly
+volume ID can still be assigned later when B<vos addsite> is run; if a
+volume does not have a readonly volume ID associated with it by the time
+B<vos release> is run, a volume ID will be allocated for it.
+
+If this option is not specified, the default readonly volume ID is one
+number higher than the read-write volume ID, whether or not that ID was
+manually specified.
+
+As with the B<-id> option, the default allocated volume IDs should be
+sufficient for almost all cases, so you should almost never need to
+specify this option.
+
=item B<-cell> <I<cell name>>
Names the cell in which to run the command. Do not combine this argument
afs_int32 aquota, afs_int32 aspare1,
afs_int32 aspare2, afs_int32 aspare3,
afs_int32 aspare4, afs_uint32 * anewid);
+extern int UV_CreateVolume3(afs_int32 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);
extern int UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname,
afs_uint32 aid);
extern int UV_DeleteVolume(afs_int32 aserver, afs_int32 apart,
extern int UV_LockRelease(afs_uint32 volid);
extern int UV_AddSite(afs_int32 server, afs_int32 part, afs_uint32 volid,
afs_int32 valid);
+extern int UV_AddSite2(afs_int32 server, afs_int32 part, afs_uint32 volid,
+ afs_uint32 rovolid, afs_int32 valid);
extern int UV_RemoveSite(afs_int32 server, afs_int32 part, afs_uint32 volid);
extern int UV_ChangeLocation(afs_int32 server, afs_int32 part,
afs_uint32 volid);
{
afs_int32 pnum;
char part[10];
- afs_uint32 volid;
+ afs_uint32 volid = 0, rovolid = 0, bkvolid = 0;
+ afs_uint32 *arovolid;
afs_int32 code;
struct nvldbentry entry;
afs_int32 vcode;
afs_int32 quota;
+ arovolid = &rovolid;
+
quota = 5000;
tserver = GetServer(as->parms[0].items->data);
if (!tserver) {
}
}
+ if (as->parms[4].items) {
+ if (!IsNumeric(as->parms[4].items->data)) {
+ fprintf(STDERR, "vos: Given volume ID %s should be numeric.\n",
+ as->parms[4].items->data);
+ return EINVAL;
+ }
+
+ code = util_GetInt32(as->parms[4].items->data, &volid);
+ if (code) {
+ fprintf(STDERR, "vos: bad integer specified for volume ID.\n");
+ return code;
+ }
+ }
+
+ if (as->parms[5].items) {
+ if (!IsNumeric(as->parms[5].items->data)) {
+ fprintf(STDERR, "vos: Given RO volume ID %s should be numeric.\n",
+ as->parms[5].items->data);
+ return EINVAL;
+ }
+
+ code = util_GetInt32(as->parms[5].items->data, &rovolid);
+ if (code) {
+ fprintf(STDERR, "vos: bad integer specified for volume ID.\n");
+ return code;
+ }
+
+ if (rovolid == 0) {
+ arovolid = NULL;
+ }
+ }
+
code =
- UV_CreateVolume2(tserver, pnum, as->parms[2].items->data, quota, 0,
- 0, 0, 0, &volid);
+ UV_CreateVolume3(tserver, pnum, as->parms[2].items->data, quota, 0,
+ 0, 0, 0, &volid, arovolid, &bkvolid);
if (code) {
PrintDiagnostics("create", code);
return code;
AddSite(register struct cmd_syndesc *as, void *arock)
{
afs_uint32 avolid;
- afs_int32 aserver, apart, code, err, valid = 0;
+ afs_int32 aserver, apart, code, err, arovolid, valid = 0;
char apartName[10], avolname[VOLSER_MAXVOLNAME + 1];
vsu_ExtractName(avolname, as->parms[2].items->data);;
as->parms[2].items->data);
exit(1);
}
+ arovolid = 0;
+ if (as->parms[3].items) {
+ vsu_ExtractName(avolname, as->parms[3].items->data);
+ arovolid = vsu_GetVolumeID(avolname, cstruct, &err);
+ if (!arovolid) {
+ fprintf(STDERR, "vos: invalid ro volume id '%s'\n",
+ as->parms[3].items->data);
+ exit(1);
+ }
+ }
aserver = GetServer(as->parms[0].items->data);
if (aserver == 0) {
fprintf(STDERR, "vos: server '%s' not found in host table\n",
as->parms[1].items->data);
exit(1);
}
- if (as->parms[3].items) {
+ if (as->parms[4].items) {
valid = 1;
}
- code = UV_AddSite(aserver, apart, avolid, valid);
+ code = UV_AddSite2(aserver, apart, avolid, arovolid, valid);
if (code) {
PrintDiagnostics("addsite", code);
exit(1);
cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "volume name");
cmd_AddParm(ts, "-maxquota", CMD_SINGLE, CMD_OPTIONAL,
"initial quota (KB)");
+ cmd_AddParm(ts, "-id", CMD_SINGLE, CMD_OPTIONAL, "volume ID");
+ cmd_AddParm(ts, "-roid", CMD_SINGLE, CMD_OPTIONAL, "readonly volume ID");
#ifdef notdef
cmd_AddParm(ts, "-minquota", CMD_SINGLE, CMD_OPTIONAL, "");
#endif
cmd_AddParm(ts, "-partition", CMD_SINGLE, 0,
"partition name for new site");
cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID");
+ cmd_AddParm(ts, "-roid", CMD_SINGLE, CMD_OPTIONAL, "volume name or ID for RO");
cmd_AddParm(ts, "-valid", CMD_FLAG, CMD_OPTIONAL, "publish as an up-to-date site in VLDB");
COMMONPARMS;
return code;
}
-/* old interface to create volume */
+/* old interface to create volumes */
int
UV_CreateVolume(afs_int32 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,
afs_int32 aquota, afs_int32 aspare1, afs_int32 aspare2,
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);
+}
+
+/**
+ * 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_int32 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)
+{
register struct rx_connection *aconn;
afs_int32 tid;
register afs_int32 code;
afs_int32 error;
afs_int32 rcode, vcode;
+ afs_int32 lastid;
struct nvldbentry entry, storeEntry; /*the new vldb entry */
struct volintInfo tstatus;
+ afs_int32 alloc_roid = 0, alloc_bkid = 0;
+
+ if (aroid && *aroid == 0) {
+ alloc_roid = 1;
+ }
+ if (abkid && *abkid == 0) {
+ alloc_bkid = 1;
+ }
tid = 0;
aconn = (struct rx_connection *)0;
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 (*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 {
+ /* get the next 3 available ids from the VLDB */
+ int alloc_ids = 3;
+
+ /* if the RO or BK id are specified, we don't need to allocate as
+ * many IDs */
+ if (!alloc_roid) {
+ --alloc_ids;
+ }
+ if (!alloc_bkid) {
+ --alloc_ids;
+ }
+ vcode = ubik_VL_GetNewVolumeId(cstruct, 0, alloc_ids, anewid);
+ EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n", aname);
+ }
+
+ /* rw,ro, bk id are related in the default case */
+ lastid = *anewid;
+ if (aroid && *aroid) {
+ VPRINT1("Using RO volume ID %d.\n", aroid);
+ } else if (aroid) {
+ *aroid = ++lastid;
+ }
+ if (abkid && *abkid) {
+ VPRINT1("Using backup volume ID %d.\n", abkid);
+ } else if (abkid) {
+ *abkid = ++lastid;
+ }
+
code =
- AFSVolCreateVolume_retry(aconn, apart, aname, volser_RW, 0, anewid, &tid);
+ AFSVolCreateVolume_retry(aconn, apart, aname, volser_RW, 0, anewid, &tid);
EGOTO2(cfail, code, "Failed to create the volume %s %u \n", aname,
*anewid);
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);
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 */
}
+/* old interface to add rosites */
+int
+UV_AddSite(afs_int32 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_uint32 volid, afs_int32 valid)
+UV_AddSite2(afs_int32 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;