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:
Casey Bodley 2011-08-30 12:53:26 -04:00 committed by unknown
parent 0184804498
commit 5880a8bb1d
6 changed files with 116 additions and 8 deletions

View file

@ -172,6 +172,18 @@ out:
return status; 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 */ /* OP_CB_RECALL */
static enum_t handle_cb_recall( static enum_t handle_cb_recall(
IN nfs41_rpc_clnt *rpc_clnt, 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; break;
case OP_CB_GETATTR: case OP_CB_GETATTR:
dprintf(1, "OP_CB_GETATTR\n"); dprintf(1, "OP_CB_GETATTR\n");
res->status = NFS4ERR_NOTSUPP; res->status = handle_cb_getattr(rpc_clnt,
&argop->args.getattr, &resop->res.getattr);
break; break;
case OP_CB_RECALL: case OP_CB_RECALL:
dprintf(1, "OP_CB_RECALL\n"); dprintf(1, "OP_CB_RECALL\n");

View file

@ -25,16 +25,18 @@
*/ */
#include "nfs41_callback.h" #include "nfs41_callback.h"
#include "nfs41_ops.h" #include "nfs41_ops.h"
#include "util.h"
#include "daemon_debug.h" #include "daemon_debug.h"
#define CBXLVL 2 /* dprintf level for callback xdr logging */ #define CBXLVL 2 /* dprintf level for callback xdr logging */
#define CBX_ERR(msg) dprintf((CBXLVL), __FUNCTION__ ": failed at " msg "\n") #define CBX_ERR(msg) dprintf((CBXLVL), __FUNCTION__ ": failed at " msg "\n")
/* common types */ /* common types */
bool_t xdr_bitmap4(XDR *xdr, bitmap4 *bitmap); 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) static bool_t common_stateid(XDR *xdr, stateid4 *stateid)
{ {
@ -245,12 +247,41 @@ out:
} }
/* OP_CB_GETATTR */ /* 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; bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid); result = common_fh(xdr, &args->fh);
if (!result) { CBX_ERR("getattr.target_highest_slotid"); goto out; } 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: out:
return result; 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); result = xdr_enum(xdr, &res->status);
if (!result) { CBX_ERR("getattr.status"); goto out; } 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: out:
return result; return result;
} }

View file

@ -26,6 +26,7 @@
#include "delegation.h" #include "delegation.h"
#include "nfs41_ops.h" #include "nfs41_ops.h"
#include "name_cache.h"
#include "util.h" #include "util.h"
#include "daemon_debug.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( void nfs41_client_delegation_free(
IN nfs41_client *client) IN nfs41_client *client)
{ {

View file

@ -91,6 +91,12 @@ int nfs41_delegation_recall(
IN const stateid4 *stateid, IN const stateid4 *stateid,
IN bool_t truncate); 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; /* after client state recovery, return any 'recalled' delegations;
* must be called under the client's state lock */ * must be called under the client's state lock */

View file

@ -124,11 +124,13 @@ struct cb_sequence_res {
/* OP_CB_GETATTR */ /* OP_CB_GETATTR */
struct cb_getattr_args { struct cb_getattr_args {
uint32_t target_highest_slotid; nfs41_fh fh;
bitmap4 attr_request;
}; };
struct cb_getattr_res { struct cb_getattr_res {
enum_t status; enum_t status;
nfs41_file_info info;
}; };
/* OP_CB_RECALL */ /* OP_CB_RECALL */
@ -231,7 +233,8 @@ union cb_op_args {
struct cb_layoutrecall_args layoutrecall; struct cb_layoutrecall_args layoutrecall;
struct cb_recall_slot_args recall_slot; struct cb_recall_slot_args recall_slot;
struct cb_sequence_args sequence; struct cb_sequence_args sequence;
struct cb_recall_args recall; struct cb_getattr_args getattr;
struct cb_recall_args recall;
struct cb_notify_deviceid_args notify_deviceid; struct cb_notify_deviceid_args notify_deviceid;
}; };
struct cb_argop { struct cb_argop {
@ -255,6 +258,7 @@ union cb_op_res {
struct cb_layoutrecall_res layoutrecall; struct cb_layoutrecall_res layoutrecall;
struct cb_recall_slot_res recall_slot; struct cb_recall_slot_res recall_slot;
struct cb_sequence_res sequence; struct cb_sequence_res sequence;
struct cb_getattr_res getattr;
struct cb_recall_res recall; struct cb_recall_res recall;
struct cb_notify_deviceid_res notify_deviceid; struct cb_notify_deviceid_res notify_deviceid;
}; };

View file

@ -146,7 +146,7 @@ static bool_t xdr_stateid4(
} }
/* fattr4 */ /* fattr4 */
static bool_t xdr_fattr4( bool_t xdr_fattr4(
XDR *xdr, XDR *xdr,
fattr4 *fattr) fattr4 *fattr)
{ {