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;
|
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");
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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,6 +233,7 @@ 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_getattr_args getattr;
|
||||||
struct cb_recall_args recall;
|
struct cb_recall_args recall;
|
||||||
struct cb_notify_deviceid_args notify_deviceid;
|
struct cb_notify_deviceid_args notify_deviceid;
|
||||||
};
|
};
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue