deleg: support for CB_GETATTR
on CB_GETATTR, search for a delegation with the given filehandle. if found, use its fileid to get its cached attributes. when encoding the response, only include change and size attributes Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
0184804498
commit
5880a8bb1d
6 changed files with 116 additions and 8 deletions
|
|
@ -172,6 +172,18 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
/* OP_CB_GETATTR */
|
||||
static enum_t handle_cb_getattr(
|
||||
IN nfs41_rpc_clnt *rpc_clnt,
|
||||
IN struct cb_getattr_args *args,
|
||||
OUT struct cb_getattr_res *res)
|
||||
{
|
||||
/* look up cached attributes for the given filehandle */
|
||||
res->status = nfs41_delegation_getattr(rpc_clnt->client,
|
||||
&args->fh, &args->attr_request, &res->info);
|
||||
return res->status;
|
||||
}
|
||||
|
||||
/* OP_CB_RECALL */
|
||||
static enum_t handle_cb_recall(
|
||||
IN nfs41_rpc_clnt *rpc_clnt,
|
||||
|
|
@ -437,7 +449,8 @@ static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_
|
|||
break;
|
||||
case OP_CB_GETATTR:
|
||||
dprintf(1, "OP_CB_GETATTR\n");
|
||||
res->status = NFS4ERR_NOTSUPP;
|
||||
res->status = handle_cb_getattr(rpc_clnt,
|
||||
&argop->args.getattr, &resop->res.getattr);
|
||||
break;
|
||||
case OP_CB_RECALL:
|
||||
dprintf(1, "OP_CB_RECALL\n");
|
||||
|
|
|
|||
|
|
@ -25,16 +25,18 @@
|
|||
*/
|
||||
|
||||
#include "nfs41_callback.h"
|
||||
|
||||
#include "nfs41_ops.h"
|
||||
#include "util.h"
|
||||
#include "daemon_debug.h"
|
||||
|
||||
|
||||
#define CBXLVL 2 /* dprintf level for callback xdr logging */
|
||||
#define CBX_ERR(msg) dprintf((CBXLVL), __FUNCTION__ ": failed at " msg "\n")
|
||||
|
||||
|
||||
/* common types */
|
||||
bool_t xdr_bitmap4(XDR *xdr, bitmap4 *bitmap);
|
||||
bool_t xdr_fattr4(XDR *xdr, fattr4 *fattr);
|
||||
|
||||
static bool_t common_stateid(XDR *xdr, stateid4 *stateid)
|
||||
{
|
||||
|
|
@ -245,12 +247,41 @@ out:
|
|||
}
|
||||
|
||||
/* OP_CB_GETATTR */
|
||||
static bool_t op_cb_getattr_args(XDR *xdr, struct cb_getattr_args *res)
|
||||
static bool_t op_cb_getattr_args(XDR *xdr, struct cb_getattr_args *args)
|
||||
{
|
||||
bool_t result;
|
||||
|
||||
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
|
||||
if (!result) { CBX_ERR("getattr.target_highest_slotid"); goto out; }
|
||||
result = common_fh(xdr, &args->fh);
|
||||
if (!result) { CBX_ERR("getattr.fh"); goto out; }
|
||||
|
||||
result = xdr_bitmap4(xdr, &args->attr_request);
|
||||
if (!result) { CBX_ERR("getattr.attr_request"); goto out; }
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool_t info_to_fattr4(nfs41_file_info *info, fattr4 *fattr)
|
||||
{
|
||||
XDR fattr_xdr;
|
||||
bool_t result = TRUE;
|
||||
|
||||
/* encode nfs41_file_info into fattr4 */
|
||||
xdrmem_create(&fattr_xdr, (char*)fattr->attr_vals,
|
||||
NFS4_OPAQUE_LIMIT, XDR_ENCODE);
|
||||
|
||||
/* The only attributes that the server can reliably
|
||||
* query via CB_GETATTR are size and change. */
|
||||
if (bitmap_isset(&info->attrmask, 0, FATTR4_WORD0_CHANGE)) {
|
||||
result = xdr_u_hyper(&fattr_xdr, &info->change);
|
||||
if (!result) { CBX_ERR("getattr.info.change"); goto out; }
|
||||
bitmap_set(&fattr->attrmask, 0, FATTR4_WORD0_CHANGE);
|
||||
}
|
||||
if (bitmap_isset(&info->attrmask, 0, FATTR4_WORD0_SIZE)) {
|
||||
result = xdr_u_hyper(&fattr_xdr, &info->size);
|
||||
if (!result) { CBX_ERR("getattr.info.size"); goto out; }
|
||||
bitmap_set(&fattr->attrmask, 0, FATTR4_WORD0_SIZE);
|
||||
}
|
||||
fattr->attr_vals_len = xdr_getpos(&fattr_xdr);
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
|
@ -261,6 +292,16 @@ static bool_t op_cb_getattr_res(XDR *xdr, struct cb_getattr_res *res)
|
|||
|
||||
result = xdr_enum(xdr, &res->status);
|
||||
if (!result) { CBX_ERR("getattr.status"); goto out; }
|
||||
|
||||
if (res->status == NFS4_OK) {
|
||||
fattr4 fattr = { 0 };
|
||||
|
||||
result = info_to_fattr4(&res->info, &fattr);
|
||||
if (!result) { goto out; }
|
||||
|
||||
result = xdr_fattr4(xdr, &fattr);
|
||||
if (!result) { CBX_ERR("getattr.obj_attributes"); goto out; }
|
||||
}
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "delegation.h"
|
||||
#include "nfs41_ops.h"
|
||||
#include "name_cache.h"
|
||||
#include "util.h"
|
||||
#include "daemon_debug.h"
|
||||
|
||||
|
|
@ -725,6 +726,49 @@ out_deleg:
|
|||
}
|
||||
|
||||
|
||||
int nfs41_delegation_getattr(
|
||||
IN nfs41_client *client,
|
||||
IN const nfs41_fh *fh,
|
||||
IN const bitmap4 *attr_request,
|
||||
OUT nfs41_file_info *info)
|
||||
{
|
||||
nfs41_delegation_state *deleg;
|
||||
uint64_t fileid;
|
||||
int status;
|
||||
|
||||
dprintf(2, "--> nfs41_delegation_getattr()\n");
|
||||
|
||||
/* search for a delegation on this file handle */
|
||||
status = delegation_find(client, fh, deleg_fh_cmp, &deleg);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
AcquireSRWLockShared(&deleg->lock);
|
||||
fileid = deleg->file.fh.fileid;
|
||||
if (deleg->status != DELEGATION_GRANTED ||
|
||||
deleg->state.type != OPEN_DELEGATE_WRITE) {
|
||||
status = NFS4ERR_BADHANDLE;
|
||||
}
|
||||
ReleaseSRWLockShared(&deleg->lock);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
ZeroMemory(&info, sizeof(nfs41_file_info));
|
||||
|
||||
/* find attributes for the given fileid */
|
||||
status = nfs41_attr_cache_lookup(
|
||||
client_name_cache(client), fileid, info);
|
||||
if (status) {
|
||||
status = NFS4ERR_BADHANDLE;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
dprintf(DGLVL, "<-- nfs41_delegation_getattr() returning %s\n",
|
||||
nfs_error_string(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void nfs41_client_delegation_free(
|
||||
IN nfs41_client *client)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -91,6 +91,12 @@ int nfs41_delegation_recall(
|
|||
IN const stateid4 *stateid,
|
||||
IN bool_t truncate);
|
||||
|
||||
int nfs41_delegation_getattr(
|
||||
IN nfs41_client *client,
|
||||
IN const nfs41_fh *fh,
|
||||
IN const bitmap4 *attr_request,
|
||||
OUT nfs41_file_info *info);
|
||||
|
||||
|
||||
/* after client state recovery, return any 'recalled' delegations;
|
||||
* must be called under the client's state lock */
|
||||
|
|
|
|||
|
|
@ -124,11 +124,13 @@ struct cb_sequence_res {
|
|||
|
||||
/* OP_CB_GETATTR */
|
||||
struct cb_getattr_args {
|
||||
uint32_t target_highest_slotid;
|
||||
nfs41_fh fh;
|
||||
bitmap4 attr_request;
|
||||
};
|
||||
|
||||
struct cb_getattr_res {
|
||||
enum_t status;
|
||||
nfs41_file_info info;
|
||||
};
|
||||
|
||||
/* OP_CB_RECALL */
|
||||
|
|
@ -231,6 +233,7 @@ union cb_op_args {
|
|||
struct cb_layoutrecall_args layoutrecall;
|
||||
struct cb_recall_slot_args recall_slot;
|
||||
struct cb_sequence_args sequence;
|
||||
struct cb_getattr_args getattr;
|
||||
struct cb_recall_args recall;
|
||||
struct cb_notify_deviceid_args notify_deviceid;
|
||||
};
|
||||
|
|
@ -255,6 +258,7 @@ union cb_op_res {
|
|||
struct cb_layoutrecall_res layoutrecall;
|
||||
struct cb_recall_slot_res recall_slot;
|
||||
struct cb_sequence_res sequence;
|
||||
struct cb_getattr_res getattr;
|
||||
struct cb_recall_res recall;
|
||||
struct cb_notify_deviceid_res notify_deviceid;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ static bool_t xdr_stateid4(
|
|||
}
|
||||
|
||||
/* fattr4 */
|
||||
static bool_t xdr_fattr4(
|
||||
bool_t xdr_fattr4(
|
||||
XDR *xdr,
|
||||
fattr4 *fattr)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue