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
void nfs_return_all_delegations(struct super_block *sb);
/* NFSv4 delegation-related procedures */
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
......@@ -196,9 +196,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
{
struct inode *inode = state->inode;
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_fattr fattr = {
.valid = 0,
};
struct nfs_openargs o_arg = {
.fh = NFS_FH(inode),
.seqid = sp->so_seqid,
......@@ -209,11 +206,10 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
.bitmask = server->attr_bitmask,
};
struct nfs_openres o_res = {
.f_attr = &fattr,
.server = server, /* Grrr */
};
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_resp = &o_res,
.rpc_cred = sp->so_cred,
......@@ -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);
nfs4_increment_seqid(status, sp);
if (status == 0)
if (status == 0) {
memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
/* Update the inode attributes */
nfs_refresh_inode(inode, &fattr);
if (o_res.delegation_type != 0) {
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;
}
......@@ -248,7 +251,76 @@ int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
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 = {
.fh = fh,
......
......@@ -180,16 +180,14 @@ static int nfs_stat_to_errno(int);
#define NFS4_dec_open_confirm_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
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 + \
op_encode_hdr_maxsz + \
11 + \
encode_getattr_maxsz)
#define NFS4_dec_open_reclaim_sz (compound_decode_hdr_maxsz + \
11)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + \
4 + 5 + 2 + 3 + \
decode_getattr_maxsz)
4 + 5 + 2 + 3)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
......@@ -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 compound_hdr hdr = {
.nops = 3,
.nops = 2,
};
int status;
......@@ -1441,9 +1439,6 @@ static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct n
if (status)
goto out;
status = encode_open(&xdr, args);
if (status)
goto out;
status = encode_getfattr(&xdr, args->bitmask);
out:
return status;
}
......@@ -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 compound_hdr hdr;
......@@ -3507,11 +3502,6 @@ static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct
if (status)
goto out;
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:
return status;
}
......@@ -3993,7 +3983,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(COMMIT, enc_commit, dec_commit),
PROC(OPEN, enc_open, dec_open),
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(CLOSE, enc_close, dec_close),
PROC(SETATTR, enc_setattr, dec_setattr),
......
......@@ -355,7 +355,7 @@ enum {
NFSPROC4_CLNT_COMMIT,
NFSPROC4_CLNT_OPEN,
NFSPROC4_CLNT_OPEN_CONFIRM,
NFSPROC4_CLNT_OPEN_RECLAIM,
NFSPROC4_CLNT_OPEN_NOATTR,
NFSPROC4_CLNT_OPEN_DOWNGRADE,
NFSPROC4_CLNT_CLOSE,
NFSPROC4_CLNT_SETATTR,
......
......@@ -630,6 +630,7 @@ struct nfs4_lock_state {
/* bits for nfs4_state->flags */
enum {
LK_STATE_IN_USE,
NFS_DELEGATED_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