diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-03 16:01:51 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-03 16:01:51 -0500 |
commit | 0b08b07507d5ae733408fd4ebda1cd89d3a840ef (patch) | |
tree | c91d8b77610f640cd930f62407b9fc5fec283773 /fs/nfs | |
parent | 22763c5cf3690a681551162c15d34d935308c8d7 (diff) | |
parent | 1185a552e3d78807031f4021c5edb60d3e8838f1 (diff) |
Merge branch 'bugfixes' into nfs-for-next
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/delegation.c | 42 | ||||
-rw-r--r-- | fs/nfs/delegation.h | 2 | ||||
-rw-r--r-- | fs/nfs/dns_resolve.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 67 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 2 |
6 files changed, 83 insertions, 62 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 6dd48a4405b4..eeecd69c130c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -92,7 +92,7 @@ out: return status; } -static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) +static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *ctx; @@ -116,10 +116,11 @@ again: err = nfs_delegation_claim_locks(ctx, state); put_nfs_open_context(ctx); if (err != 0) - return; + return err; goto again; } spin_unlock(&inode->i_lock); + return 0; } /* @@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode) /* * Basic procedure for returning a delegation to the server */ -static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation) +static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { struct nfs_inode *nfsi = NFS_I(inode); + int err; - nfs_msync_inode(inode); /* * Guard against new delegated open/lock/unlock calls and against * state recovery */ down_write(&nfsi->rwsem); - nfs_delegation_claim_opens(inode, &delegation->stateid); + err = nfs_delegation_claim_opens(inode, &delegation->stateid); up_write(&nfsi->rwsem); - nfs_msync_inode(inode); + if (err) + goto out; - return nfs_do_return_delegation(inode, delegation, 1); + err = nfs_do_return_delegation(inode, delegation, issync); +out: + return err; } /* * Return all delegations that have been marked for return */ -void nfs_client_return_marked_delegations(struct nfs_client *clp) +int nfs_client_return_marked_delegations(struct nfs_client *clp) { struct nfs_delegation *delegation; struct inode *inode; + int err = 0; restart: rcu_read_lock(); @@ -298,12 +303,18 @@ restart: delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); spin_unlock(&clp->cl_lock); rcu_read_unlock(); - if (delegation != NULL) - __nfs_inode_return_delegation(inode, delegation); + if (delegation != NULL) { + filemap_flush(inode->i_mapping); + err = __nfs_inode_return_delegation(inode, delegation, 0); + } iput(inode); - goto restart; + if (!err) + goto restart; + set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); + return err; } rcu_read_unlock(); + return 0; } /* @@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode) spin_lock(&clp->cl_lock); delegation = nfs_detach_delegation_locked(nfsi, NULL); spin_unlock(&clp->cl_lock); - if (delegation != NULL) - err = __nfs_inode_return_delegation(inode, delegation); + if (delegation != NULL) { + nfs_msync_inode(inode); + err = __nfs_inode_return_delegation(inode, delegation, 1); + } } return err; } @@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb) spin_unlock(&delegation->lock); } rcu_read_unlock(); - nfs_client_return_marked_delegations(clp); + if (nfs_client_return_marked_delegations(clp) != 0) + nfs4_schedule_state_manager(clp); } static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 09f383795174..e225a1290127 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -42,7 +42,7 @@ void nfs_super_return_all_delegations(struct super_block *sb); void nfs_expire_all_delegations(struct nfs_client *clp); void nfs_expire_unreferenced_delegations(struct nfs_client *clp); void nfs_handle_cb_pathdown(struct nfs_client *clp); -void nfs_client_return_marked_delegations(struct nfs_client *clp); +int nfs_client_return_marked_delegations(struct nfs_client *clp); void nfs_delegation_mark_reclaim(struct nfs_client *clp); void nfs_delegation_reap_unclaimed(struct nfs_client *clp); diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index f4d54ba97cc6..95e1ca765d47 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd, return 0; } -struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, +static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, struct nfs_dns_ent *key) { struct cache_head *ch; @@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, return container_of(ch, struct nfs_dns_ent, h); } -struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, +static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, struct nfs_dns_ent *new, struct nfs_dns_ent *key) { diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 741a562177fc..df8a734f1c05 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1488,7 +1488,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s return ret; } -static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) +static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(state->inode); struct nfs4_exception exception = { }; @@ -1496,10 +1496,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4 do { err = _nfs4_open_expired(ctx, state); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); + switch (err) { + default: + goto out; + case -NFS4ERR_GRACE: + case -NFS4ERR_DELAY: + nfs4_handle_exception(server, err, &exception); + err = 0; + } } while (exception.retry); +out: return err; } @@ -1981,7 +1987,7 @@ out_drop: return 0; } -void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) +static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) { if (ctx->state == NULL) return; @@ -4049,10 +4055,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) return 0; err = _nfs4_do_setlk(state, F_SETLK, request, 0); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); + switch (err) { + default: + goto out; + case -NFS4ERR_GRACE: + case -NFS4ERR_DELAY: + nfs4_handle_exception(server, err, &exception); + err = 0; + } } while (exception.retry); +out: return err; } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 2ef4fecf3984..62927879572f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1046,20 +1046,19 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); } -static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) -{ - clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); -} - -static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) +static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) { switch (error) { case -NFS4ERR_CB_PATH_DOWN: nfs_handle_cb_pathdown(clp); - break; + return 0; + case -NFS4ERR_NO_GRACE: + nfs4_state_end_reclaim_reboot(clp); + return 0; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_LEASE_MOVED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); + nfs4_state_end_reclaim_reboot(clp); nfs4_state_start_reclaim_reboot(clp); break; case -NFS4ERR_EXPIRED: @@ -1074,6 +1073,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) case -NFS4ERR_SEQ_MISORDERED: set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); } + return error; } static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) @@ -1093,8 +1093,7 @@ restart: if (status < 0) { set_bit(ops->owner_flag_bit, &sp->so_flags); nfs4_put_state_owner(sp); - nfs4_recovery_handle_error(clp, status); - return status; + return nfs4_recovery_handle_error(clp, status); } nfs4_put_state_owner(sp); goto restart; @@ -1124,8 +1123,7 @@ static int nfs4_check_lease(struct nfs_client *clp) status = ops->renew_lease(clp, cred); put_rpccred(cred); out: - nfs4_recovery_handle_error(clp, status); - return status; + return nfs4_recovery_handle_error(clp, status); } static int nfs4_reclaim_lease(struct nfs_client *clp) @@ -1234,7 +1232,8 @@ static void nfs4_state_manager(struct nfs_client *clp) status = nfs4_reclaim_lease(clp); if (status) { nfs4_set_lease_expired(clp, status); - if (status == -EAGAIN) + if (test_bit(NFS4CLNT_LEASE_EXPIRED, + &clp->cl_state)) continue; if (clp->cl_cons_state == NFS_CS_SESSION_INITING) @@ -1246,9 +1245,12 @@ static void nfs4_state_manager(struct nfs_client *clp) if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { status = nfs4_check_lease(clp); - if (status != 0) + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) continue; + if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN) + goto out_error; } + /* Initialize or reset the session */ if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) && nfs4_has_session(clp)) { @@ -1256,41 +1258,36 @@ static void nfs4_state_manager(struct nfs_client *clp) status = nfs4_initialize_session(clp); else status = nfs4_reset_session(clp); - if (status) { - if (status == -NFS4ERR_STALE_CLIENTID) - continue; + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) + continue; + if (status < 0) goto out_error; - } } + /* First recover reboot state... */ - if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { + if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { status = nfs4_do_reclaim(clp, nfs4_reboot_recovery_ops[clp->cl_minorversion]); - if (status == -NFS4ERR_STALE_CLIENTID) - continue; - if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || + test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) continue; nfs4_state_end_reclaim_reboot(clp); - continue; + if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) + continue; + if (status < 0) + goto out_error; } /* Now recover expired state... */ if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { status = nfs4_do_reclaim(clp, nfs4_nograce_recovery_ops[clp->cl_minorversion]); - if (status < 0) { - set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); - if (status == -NFS4ERR_STALE_CLIENTID) - continue; - if (status == -NFS4ERR_EXPIRED) - continue; - if (test_bit(NFS4CLNT_SESSION_SETUP, - &clp->cl_state)) - continue; + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || + test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) || + test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) + continue; + if (status < 0) goto out_error; - } else - nfs4_state_end_reclaim_nograce(clp); - continue; } if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { @@ -1309,8 +1306,6 @@ static void nfs4_state_manager(struct nfs_client *clp) out_error: printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" " with error %d\n", clp->cl_hostname, -status); - if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) - nfs4_state_end_reclaim_reboot(clp); nfs4_clear_state_manager_bit(clp); } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 20b4e30e6c82..3a71b40a990a 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -2096,7 +2096,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p, encode_compound_hdr(&xdr, req, &hdr); encode_sequence(&xdr, &args->seq_args, &hdr); encode_putfh(&xdr, args->fh, &hdr); - replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1; + replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); xdr_inline_pages(&req->rq_rcv_buf, replen << 2, |