Commit 3f052fdc authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Service delegation recall requests from the server.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
parent f092be42
...@@ -28,5 +28,6 @@ struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nf ...@@ -28,5 +28,6 @@ struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nf
void nfs_return_all_delegations(struct super_block *sb); void nfs_return_all_delegations(struct super_block *sb);
/* NFSv4 delegation-related procedures */ /* NFSv4 delegation-related procedures */
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
#endif #endif
...@@ -196,9 +196,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st ...@@ -196,9 +196,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
{ {
struct inode *inode = state->inode; struct inode *inode = state->inode;
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
struct nfs_fattr fattr = {
.valid = 0,
};
struct nfs_openargs o_arg = { struct nfs_openargs o_arg = {
.fh = NFS_FH(inode), .fh = NFS_FH(inode),
.seqid = sp->so_seqid, .seqid = sp->so_seqid,
...@@ -209,11 +206,10 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st ...@@ -209,11 +206,10 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
.bitmask = server->attr_bitmask, .bitmask = server->attr_bitmask,
}; };
struct nfs_openres o_res = { struct nfs_openres o_res = {
.f_attr = &fattr,
.server = server, /* Grrr */ .server = server, /* Grrr */
}; };
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_RECLAIM], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
.rpc_argp = &o_arg, .rpc_argp = &o_arg,
.rpc_resp = &o_res, .rpc_resp = &o_res,
.rpc_cred = sp->so_cred, .rpc_cred = sp->so_cred,
...@@ -222,10 +218,17 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st ...@@ -222,10 +218,17 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
status = rpc_call_sync(server->client, &msg, 0); status = rpc_call_sync(server->client, &msg, 0);
nfs4_increment_seqid(status, sp); nfs4_increment_seqid(status, sp);
if (status == 0) if (status == 0) {
memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
/* Update the inode attributes */ if (o_res.delegation_type != 0) {
nfs_refresh_inode(inode, &fattr); nfs_inode_set_delegation(inode, sp->so_cred, &o_res);
/* Did the server issue an immediate delegation recall? */
if (o_res.do_recall)
nfs_async_inode_return_delegation(inode, &o_res.stateid);
}
}
/* Ensure we update the inode attributes */
NFS_CACHEINV(inode);
return status; return status;
} }
...@@ -248,7 +251,76 @@ int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) ...@@ -248,7 +251,76 @@ int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
return err; return err;
} }
static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fhandle *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid) static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
{
struct nfs4_state_owner *sp = state->owner;
struct inode *inode = dentry->d_inode;
struct nfs_server *server = NFS_SERVER(inode);
struct dentry *parent = dget_parent(dentry);
struct nfs_openargs arg = {
.fh = NFS_FH(parent->d_inode),
.clientid = server->nfs4_state->cl_clientid,
.name = &dentry->d_name,
.id = sp->so_id,
.server = server,
.bitmask = server->attr_bitmask,
.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR,
};
struct nfs_openres res = {
.server = server,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = sp->so_cred,
};
int status = 0;
down(&sp->so_sema);
if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
goto out;
if (state->state == 0)
goto out;
arg.seqid = sp->so_seqid;
arg.open_flags = state->state;
memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
status = rpc_call_sync(server->client, &msg, 0);
nfs4_increment_seqid(status, sp);
if (status >= 0) {
memcpy(state->stateid.data, res.stateid.data,
sizeof(state->stateid.data));
clear_bit(NFS_DELEGATED_STATE, &state->flags);
}
out:
up(&sp->so_sema);
dput(parent);
return status;
}
int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
{
struct nfs4_exception exception = { };
struct nfs_server *server = NFS_SERVER(dentry->d_inode);
int err;
do {
err = _nfs4_open_delegation_recall(dentry, state);
switch (err) {
case 0:
return err;
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
/* Don't recall a delegation if it was lost */
nfs4_schedule_state_recovery(server->nfs4_state);
return err;
}
err = nfs4_handle_exception(server, err, &exception);
} while (exception.retry);
return err;
}
static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
{ {
struct nfs_open_confirmargs arg = { struct nfs_open_confirmargs arg = {
.fh = fh, .fh = fh,
......
...@@ -180,16 +180,14 @@ static int nfs_stat_to_errno(int); ...@@ -180,16 +180,14 @@ static int nfs_stat_to_errno(int);
#define NFS4_dec_open_confirm_sz (compound_decode_hdr_maxsz + \ #define NFS4_dec_open_confirm_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
op_decode_hdr_maxsz + 4) op_decode_hdr_maxsz + 4)
#define NFS4_enc_open_reclaim_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \ encode_putfh_maxsz + \
op_encode_hdr_maxsz + \ op_encode_hdr_maxsz + \
11 + \ 11)
encode_getattr_maxsz) #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
#define NFS4_dec_open_reclaim_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
op_decode_hdr_maxsz + \ op_decode_hdr_maxsz + \
4 + 5 + 2 + 3 + \ 4 + 5 + 2 + 3)
decode_getattr_maxsz)
#define NFS4_enc_open_downgrade_sz \ #define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \ (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \ encode_putfh_maxsz + \
...@@ -1425,13 +1423,13 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n ...@@ -1425,13 +1423,13 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n
} }
/* /*
* Encode an OPEN request * Encode an OPEN request with no attributes.
*/ */
static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args) static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr = { struct compound_hdr hdr = {
.nops = 3, .nops = 2,
}; };
int status; int status;
...@@ -1441,9 +1439,6 @@ static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct n ...@@ -1441,9 +1439,6 @@ static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct n
if (status) if (status)
goto out; goto out;
status = encode_open(&xdr, args); status = encode_open(&xdr, args);
if (status)
goto out;
status = encode_getfattr(&xdr, args->bitmask);
out: out:
return status; return status;
} }
...@@ -3491,9 +3486,9 @@ static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, uint32_t *p, struct ...@@ -3491,9 +3486,9 @@ static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, uint32_t *p, struct
} }
/* /*
* Decode OPEN_RECLAIM response * Decode OPEN response
*/ */
static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr; struct compound_hdr hdr;
...@@ -3507,11 +3502,6 @@ static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct ...@@ -3507,11 +3502,6 @@ static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct
if (status) if (status)
goto out; goto out;
status = decode_open(&xdr, res); status = decode_open(&xdr, res);
if (status)
goto out;
status = decode_getfattr(&xdr, res->f_attr, res->server);
if (status == NFS4ERR_DELAY)
status = 0;
out: out:
return status; return status;
} }
...@@ -3993,7 +3983,7 @@ struct rpc_procinfo nfs4_procedures[] = { ...@@ -3993,7 +3983,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(COMMIT, enc_commit, dec_commit), PROC(COMMIT, enc_commit, dec_commit),
PROC(OPEN, enc_open, dec_open), PROC(OPEN, enc_open, dec_open),
PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm),
PROC(OPEN_RECLAIM, enc_open_reclaim, dec_open_reclaim), PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr),
PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade), PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade),
PROC(CLOSE, enc_close, dec_close), PROC(CLOSE, enc_close, dec_close),
PROC(SETATTR, enc_setattr, dec_setattr), PROC(SETATTR, enc_setattr, dec_setattr),
......
...@@ -355,7 +355,7 @@ enum { ...@@ -355,7 +355,7 @@ enum {
NFSPROC4_CLNT_COMMIT, NFSPROC4_CLNT_COMMIT,
NFSPROC4_CLNT_OPEN, NFSPROC4_CLNT_OPEN,
NFSPROC4_CLNT_OPEN_CONFIRM, NFSPROC4_CLNT_OPEN_CONFIRM,
NFSPROC4_CLNT_OPEN_RECLAIM, NFSPROC4_CLNT_OPEN_NOATTR,
NFSPROC4_CLNT_OPEN_DOWNGRADE, NFSPROC4_CLNT_OPEN_DOWNGRADE,
NFSPROC4_CLNT_CLOSE, NFSPROC4_CLNT_CLOSE,
NFSPROC4_CLNT_SETATTR, NFSPROC4_CLNT_SETATTR,
......
...@@ -630,6 +630,7 @@ struct nfs4_lock_state { ...@@ -630,6 +630,7 @@ struct nfs4_lock_state {
/* bits for nfs4_state->flags */ /* bits for nfs4_state->flags */
enum { enum {
LK_STATE_IN_USE, LK_STATE_IN_USE,
NFS_DELEGATED_STATE,
}; };
struct nfs4_state { struct nfs4_state {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment