fs/nfs/delegation.h | 2 + fs/nfs/nfs4proc.c | 90 ++++++++++++++++++++++++++++++++++++++++++++----- fs/nfs/nfs4xdr.c | 28 +++++---------- include/linux/nfs4.h | 2 - include/linux/nfs_fs.h | 1 5 files changed, 95 insertions(+), 28 deletions(-) diff -u --recursive --new-file --show-c-function linux-2.6.7-15-open_cleanup2/fs/nfs/delegation.h linux-2.6.7-16-delegation_recall/fs/nfs/delegation.h --- linux-2.6.7-15-open_cleanup2/fs/nfs/delegation.h 2004-06-14 18:09:55.000000000 -0400 +++ linux-2.6.7-16-delegation_recall/fs/nfs/delegation.h 2004-06-14 18:19:16.000000000 -0400 @@ -28,5 +29,6 @@ struct inode *nfs_delegation_find_inode( 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 diff -u --recursive --new-file --show-c-function linux-2.6.7-15-open_cleanup2/fs/nfs/nfs4proc.c linux-2.6.7-16-delegation_recall/fs/nfs/nfs4proc.c --- linux-2.6.7-15-open_cleanup2/fs/nfs/nfs4proc.c 2004-06-14 18:10:08.000000000 -0400 +++ linux-2.6.7-16-delegation_recall/fs/nfs/nfs4proc.c 2004-06-14 18:21:24.000000000 -0400 @@ -196,9 +196,6 @@ static int _nfs4_open_reclaim(struct nfs { 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 nfs .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 nfs 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_ 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, diff -u --recursive --new-file --show-c-function linux-2.6.7-15-open_cleanup2/fs/nfs/nfs4xdr.c linux-2.6.7-16-delegation_recall/fs/nfs/nfs4xdr.c --- linux-2.6.7-15-open_cleanup2/fs/nfs/nfs4xdr.c 2004-06-14 18:10:03.000000000 -0400 +++ linux-2.6.7-16-delegation_recall/fs/nfs/nfs4xdr.c 2004-06-14 18:19:16.000000000 -0400 @@ -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 + \ @@ -1424,13 +1422,13 @@ out: } /* - * 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; @@ -1440,9 +1438,6 @@ static int nfs4_xdr_enc_open_reclaim(str if (status) goto out; status = encode_open(&xdr, args); - if (status) - goto out; - status = encode_getfattr(&xdr, args->bitmask); out: return status; } @@ -3504,9 +3499,9 @@ out: } /* - * 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; @@ -3520,9 +3515,6 @@ static int nfs4_xdr_dec_open_reclaim(str if (status) goto out; status = decode_open(&xdr, res); - if (status) - goto out; - status = decode_getfattr(&xdr, res->f_attr, res->server); out: return status; } @@ -3995,7 +3987,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), diff -u --recursive --new-file --show-c-function linux-2.6.7-15-open_cleanup2/include/linux/nfs4.h linux-2.6.7-16-delegation_recall/include/linux/nfs4.h --- linux-2.6.7-15-open_cleanup2/include/linux/nfs4.h 2004-06-14 18:09:51.000000000 -0400 +++ linux-2.6.7-16-delegation_recall/include/linux/nfs4.h 2004-06-14 18:19:16.000000000 -0400 @@ -298,7 +298,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, diff -u --recursive --new-file --show-c-function linux-2.6.7-15-open_cleanup2/include/linux/nfs_fs.h linux-2.6.7-16-delegation_recall/include/linux/nfs_fs.h --- linux-2.6.7-15-open_cleanup2/include/linux/nfs_fs.h 2004-06-14 18:09:55.000000000 -0400 +++ linux-2.6.7-16-delegation_recall/include/linux/nfs_fs.h 2004-06-14 18:19:16.000000000 -0400 @@ -643,6 +643,7 @@ struct nfs4_lock_state { /* bits for nfs4_state->flags */ enum { LK_STATE_IN_USE, + NFS_DELEGATED_STATE, }; struct nfs4_state {