From 0ced63d1a245ac11241a5d37932e6d04d9c8040d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 26 May 2011 14:26:35 -0400 Subject: NFSv4: Handle expired stateids when the lease is still valid Currently, if the server returns NFS4ERR_EXPIRED in reply to a READ or WRITE, but the RENEW test determines that the lease is still active, we fail to recover and end up looping forever in a READ/WRITE + RENEW death spiral. Signed-off-by: Trond Myklebust Cc: stable@kernel.org --- fs/nfs/nfs4proc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index cf1b339c393..d0e15dba7a5 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -267,9 +267,11 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc break; nfs4_schedule_stateid_recovery(server, state); goto wait_on_recovery; + case -NFS4ERR_EXPIRED: + if (state != NULL) + nfs4_schedule_stateid_recovery(server, state); case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: - case -NFS4ERR_EXPIRED: nfs4_schedule_lease_recovery(clp); goto wait_on_recovery; #if defined(CONFIG_NFS_V4_1) @@ -3670,9 +3672,11 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, break; nfs4_schedule_stateid_recovery(server, state); goto wait_on_recovery; + case -NFS4ERR_EXPIRED: + if (state != NULL) + nfs4_schedule_stateid_recovery(server, state); case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: - case -NFS4ERR_EXPIRED: nfs4_schedule_lease_recovery(clp); goto wait_on_recovery; #if defined(CONFIG_NFS_V4_1) @@ -4543,6 +4547,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) case -ESTALE: goto out; case -NFS4ERR_EXPIRED: + nfs4_schedule_stateid_recovery(server, state); case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: nfs4_schedule_lease_recovery(server->nfs_client); -- cgit v1.2.3-18-g5258 From 444f72fe7e7b5f4db34cee933fa3546ebb8e9122 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 26 May 2011 14:26:35 -0400 Subject: NFSv4.1: Fix the handling of NFS4ERR_SEQ_MISORDERED errors Currently, the call to nfs4_schedule_session_recovery() will actually just result in a test of the lease when what we really want is to force a session reset. Signed-off-by: Trond Myklebust Cc: stable@kernel.org --- fs/nfs/nfs4state.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 036f5adc9e1..e97dd219f84 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1466,7 +1466,10 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) #ifdef CONFIG_NFS_V4_1 void nfs4_schedule_session_recovery(struct nfs4_session *session) { - nfs4_schedule_lease_recovery(session->clp); + struct nfs_client *clp = session->clp; + + set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); + nfs4_schedule_lease_recovery(clp); } EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); @@ -1549,6 +1552,7 @@ static int nfs4_reset_session(struct nfs_client *clp) status = nfs4_recovery_handle_error(clp, status); goto out; } + clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); /* create_session negotiated new slot table */ clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); -- cgit v1.2.3-18-g5258 From 60c16ea877546e559988a8b1e4f4256afbbd83e6 Mon Sep 17 00:00:00 2001 From: Harshula Jayasuriya Date: Mon, 23 May 2011 22:52:11 +1000 Subject: NFS: nfs_update_inode: print current and new inode size in debug output Hi Trond, In nfs_update_inode debug output, print the current and new inode size when the file size changes on the NFS server. Signed-off-by: Harshula Jayasuriya Reviewed-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 57bb31ad7a5..873c6fa8bc3 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1298,8 +1298,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) i_size_write(inode, new_isize); invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; } - dprintk("NFS: isize change on server for file %s/%ld\n", - inode->i_sb->s_id, inode->i_ino); + dprintk("NFS: isize change on server for file %s/%ld " + "(%Ld to %Ld)\n", + inode->i_sb->s_id, + inode->i_ino, + (long long)cur_isize, + (long long)new_isize); } } else invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR -- cgit v1.2.3-18-g5258 From 4b8ee2b82e8b0b6e17ee33feb74fcdb5c6d8dbdd Mon Sep 17 00:00:00 2001 From: Vitaliy Gusev Date: Fri, 20 May 2011 01:34:46 +0400 Subject: nfs41: Correct offset for LAYOUTCOMMIT A client sends offset to MDS as it was seen by DS. As result, file size after copy is only half of original file size in case of 2 DS. Signed-off-by: Vitaliy Gusev Cc: stable@kernel.org [2.6.39] Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index f57f5281a52..101c85a3644 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1009,7 +1009,7 @@ void pnfs_set_layoutcommit(struct nfs_write_data *wdata) { struct nfs_inode *nfsi = NFS_I(wdata->inode); - loff_t end_pos = wdata->args.offset + wdata->res.count; + loff_t end_pos = wdata->mds_offset + wdata->res.count; bool mark_as_dirty = false; spin_lock(&nfsi->vfs_inode.i_lock); -- cgit v1.2.3-18-g5258 From 26f04dde681c6a48b2bacfc5fe01fef204419b0c Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 1 May 2011 06:21:54 -0700 Subject: nfs,rcu: convert call_rcu(nfs_free_delegation_callback) to kfree_rcu() The rcu callback nfs_free_delegation_callback() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(nfs_free_delegation_callback). Signed-off-by: Lai Jiangshan Signed-off-by: Paul E. McKenney Cc: Trond Myklebust Signed-off-by: Trond Myklebust --- fs/nfs/delegation.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index bbbc6bf5cb2..dd25c2aec37 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -21,25 +21,13 @@ #include "delegation.h" #include "internal.h" -static void nfs_do_free_delegation(struct nfs_delegation *delegation) -{ - kfree(delegation); -} - -static void nfs_free_delegation_callback(struct rcu_head *head) -{ - struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu); - - nfs_do_free_delegation(delegation); -} - static void nfs_free_delegation(struct nfs_delegation *delegation) { if (delegation->cred) { put_rpccred(delegation->cred); delegation->cred = NULL; } - call_rcu(&delegation->rcu, nfs_free_delegation_callback); + kfree_rcu(delegation, rcu); } /** -- cgit v1.2.3-18-g5258 From 4251c94833aa516c1fc7a0f8f504a26eadd4b91e Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 9 May 2011 15:22:15 -0400 Subject: NFS: Revert NFSROOT default mount options Marek Belisko reports that recent attempts to fix regressions in NFSROOT have broken his configuration: > After update from 2.6.38-rc8 to 2.6.38 is mounting rootfs over nfs not possible. > Log: > VFS: Mounted root (nfs filesystem) on device 0:14. > Freeing init memory: 132K > nfs: server 10.146.1.21 not responding, still trying > nfs: server 10.146.1.21 not responding, still trying > > This is never ending. I make short bisect (not too much commits > between versions) > and bad commit was reported: 53d4737580535e073963b91ce87d4216e434fab5 > > NFS: NFSROOT should default to "proto=udp" > > I've tested on mini2440 board (DM9000, static IP). > Is there some missing option or something else to be checked? An examination of a network trace captured during the failure shows that the mount is actually succeeding, but that the client is not seeing READ replies larger than 16KB. This could be a local packet filtering issue on the client, but we didn't troubleshoot this further because of the reported "git bisect" result. Last fall we removed the ad hoc mount option parser in fs/nfs/nfsroot.c in favor of using the main parser in fs/nfs/super.c (see commit 56463e50 "NFS: Use super.c for NFSROOT mount option parsing"). That commit changed the default NFSROOT mount options to be the same as those employed by user space mounts. As it turns out, these new default mount options are not tolerated by many embedded systems. So far these problems have been due to specific behavior of certain embedded NICs. The NFS community does not have such hardware on hand for running tests. Commit 53d47375 recently introduced a clean way to specify default mount options for NFSROOT, so we can now easily restore the traditional defaults for NFSROOT: vers=2,udp,rsize=4096,wsize=4096 This should revert the new default NFSROOT mount options introduced with commit 56463e50. Tested-by: Marek Belisto Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/nfsroot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index c541093a5bf..c4744e1d513 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -87,7 +87,7 @@ #define NFS_ROOT "/tftpboot/%s" /* Default NFSROOT mount options. */ -#define NFS_DEF_OPTIONS "udp" +#define NFS_DEF_OPTIONS "vers=2,udp,rsize=4096,wsize=4096" /* Parameters passed from the kernel command line */ static char nfs_root_parms[256] __initdata = ""; -- cgit v1.2.3-18-g5258