Hi Jeffrey,
> Thank you for publishing the I-D which might be misnamed.
Ack.
Although it is true that IBM as part of the AFS 3.5 release repurposed struct
nvldbentry.spares1 as nvldbentry.matchindex the field is only defined for use
as part of a new RPC: VL_ListAttributesN2. Best practice is not to modify the
semantics of the structures used in existing RPCs. Instead, new RPCs should be
allocated to indicate that the caller understands the new semantics. If the
new RPC is supported by the server, then it will be executed with the expected
semantics. Otherwise, RXGEN_OPCODE is returned indicating to the caller that
the requested functionality is unavailable. The caller then falls back to an
older version of the RPC.
In general, service capability bits should not be used for the purpose of
altering the behavior of existing RPCs. The allocation of
CLiENT_CAPABILITY_ERRORTRANS when queried by the fileserver is used to alter
the output of RXAFS RPCs based upon whether or not the client understands the
portable UAE error tables. The VICED_CAPABILITY_ERRORTRANS informs the client
whether or not the server is capable of returning UAE error codes. If
VICED_CAPABILITY_ERRORTRANS is unavailable the client needs to be careful with
processing the return codes because the fileserver's OS error code assignments
might not match those of the caller.
Service capability bits for UBIK services are particularly problematic because
there is no requirement that all servers in the cell run the same version.
Lets say that VL_CAPABILITY_LOCKTIMESTAMP was allocated for the purpose of
indicating that nvldbentry.spares2 is a non-zero timestamp value if the entry
is locked. There is no guarantee that the VL_GetCapabilities RPC result will
be returned from the same server that responded to the VL_GetEntryByIDN RPC.
If VL_CAPABILITY_LOCKTIMESTAMP was set on the server that responded to
VL_GetCapabilities but the server responding to VL_GetEntryByIDN is older and
doesn't support that behavior, then the caller might believe that the zero
nvldbentry.spares2 field indicates that the entry isn't locked.
For UBIK services, the callers are not told which server responded to a given
RPC. The only way of knowing if a new behavior was supported is to issue a
new RPC and fallback to an older RPC if it is unavailable.
After the introduction of ubik_CallRock(), we can insert additional code to run
before relevant RPC. As an example:
ListAttributesN3(conn, ...)
{
code = VL_GetCapabilities(conn, &caps);
if (code != 0) return code;
if ((caps[0] & LOCKTIMESTAMP) == 0) return -1;
return VL_ListAttributesN(conn, ...);
}
VLDB_ListAttributesN3(...)
{
return ubik_CallRock(cstruct, 0, ListAttributesN3, &args);
}
Thank you for sharing your thoughts, your feedback is always appreciated.
Marcio Barbosa.