LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [GIT] Please pull nfs client bugfixes
@ 2008-10-28 19:26 Trond Myklebust
  0 siblings, 0 replies; 3+ messages in thread
From: Trond Myklebust @ 2008-10-28 19:26 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-nfs, linux-kernel

Hi Linus,

Please pull from the "bugfixes" branch of the repository at

   git pull git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git bugfixes

This will update the following files through the appended changesets.

  Cheers,
    Trond

----
 fs/nfs/inode.c        |   11 ++------
 net/sunrpc/auth.c     |   18 ++++++++------
 net/sunrpc/xprtsock.c |   58 ++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 61 insertions(+), 26 deletions(-)

commit 5f707eb429e2c98dfd564ffbbd9f536bf493d869
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Tue Oct 28 15:21:42 2008 -0400

    SUNRPC: Fix potential race in put_rpccred()
    
    We have to be careful when we try to unhash the credential in
    put_rpccred(), because we're not holding the credcache lock, so the call to
    rpcauth_unhash_cred() may fail if someone else has looked the cred up, and
    obtained a reference to it.
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit eac0d18d44705f8a1b72cccec3a453e1a43eb20a
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Tue Oct 28 15:21:41 2008 -0400

    SUNRPC: Fix rpcauth_prune_expired
    
    We need to make sure that we don't remove creds from the cred_unused list
    if they are still under the moratorium, or else they will never get
    garbage collected.
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit ae05f269400533cbb32bfba131ab528d78dffd16
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Tue Oct 28 15:21:40 2008 -0400

    NFS: Convert nfs_attr_generation_counter into an atomic_long
    
    The most important property we need from nfs_attr_generation_counter is
    monotonicity, which is not guaranteed by the current system of smp memory
    barriers. We should convert it to an atomic_long_t, and drop the memory
    barriers.
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit 2a9e1cfa23fb62da37739af81127dab5af095d99
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Tue Oct 28 15:21:39 2008 -0400

    SUNRPC: Respond promptly to server TCP resets
    
    If the server sends us an RST error while we're in the TCP_ESTABLISHED
    state, then that will not result in a state change, and so the RPC client
    ends up hanging forever (see
    http://bugzilla.kernel.org/show_bug.cgi?id=11154)
    
    We can intercept the reset by setting up an sk->sk_error_report callback,
    which will then allow us to initiate a proper shutdown and retry...
    
    We also make sure that if the send request receives an ECONNRESET, then we
    shutdown too...
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index dc52793..d22eb38 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -908,21 +908,16 @@ static int nfs_size_need_update(const struct inode *inode, const struct nfs_fatt
 	return nfs_size_to_loff_t(fattr->size) > i_size_read(inode);
 }
 
-static unsigned long nfs_attr_generation_counter;
+static atomic_long_t nfs_attr_generation_counter;
 
 static unsigned long nfs_read_attr_generation_counter(void)
 {
-	smp_rmb();
-	return nfs_attr_generation_counter;
+	return atomic_long_read(&nfs_attr_generation_counter);
 }
 
 unsigned long nfs_inc_attr_generation_counter(void)
 {
-	unsigned long ret;
-	smp_rmb();
-	ret = ++nfs_attr_generation_counter;
-	smp_wmb();
-	return ret;
+	return atomic_long_inc_return(&nfs_attr_generation_counter);
 }
 
 void nfs_fattr_init(struct nfs_fattr *fattr)
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 436bf1b..cb216b2 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -228,19 +228,21 @@ static int
 rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 {
 	spinlock_t *cache_lock;
-	struct rpc_cred *cred;
+	struct rpc_cred *cred, *next;
 	unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
 
-	while (!list_empty(&cred_unused)) {
-		cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+	list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) {
+
+		/* Enforce a 60 second garbage collection moratorium */
+		if (time_in_range(cred->cr_expire, expired, jiffies) &&
+		    test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
+			continue;
+
 		list_del_init(&cred->cr_lru);
 		number_cred_unused--;
 		if (atomic_read(&cred->cr_count) != 0)
 			continue;
-		/* Enforce a 5 second garbage collection moratorium */
-		if (time_in_range(cred->cr_expire, expired, jiffies) &&
-		    test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0)
-			continue;
+
 		cache_lock = &cred->cr_auth->au_credcache->lock;
 		spin_lock(cache_lock);
 		if (atomic_read(&cred->cr_count) == 0) {
@@ -453,7 +455,7 @@ need_lock:
 	}
 	if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
 		rpcauth_unhash_cred(cred);
-	else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
+	if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
 		cred->cr_expire = jiffies;
 		list_add_tail(&cred->cr_lru, &cred_unused);
 		number_cred_unused++;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 9a288d5..0a50361 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -249,6 +249,7 @@ struct sock_xprt {
 	void			(*old_data_ready)(struct sock *, int);
 	void			(*old_state_change)(struct sock *);
 	void			(*old_write_space)(struct sock *);
+	void			(*old_error_report)(struct sock *);
 };
 
 /*
@@ -698,8 +699,9 @@ static int xs_tcp_send_request(struct rpc_task *task)
 	case -EAGAIN:
 		xs_nospace(task);
 		break;
-	case -ECONNREFUSED:
 	case -ECONNRESET:
+		xs_tcp_shutdown(xprt);
+	case -ECONNREFUSED:
 	case -ENOTCONN:
 	case -EPIPE:
 		status = -ENOTCONN;
@@ -742,6 +744,22 @@ out_release:
 	xprt_release_xprt(xprt, task);
 }
 
+static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
+{
+	transport->old_data_ready = sk->sk_data_ready;
+	transport->old_state_change = sk->sk_state_change;
+	transport->old_write_space = sk->sk_write_space;
+	transport->old_error_report = sk->sk_error_report;
+}
+
+static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
+{
+	sk->sk_data_ready = transport->old_data_ready;
+	sk->sk_state_change = transport->old_state_change;
+	sk->sk_write_space = transport->old_write_space;
+	sk->sk_error_report = transport->old_error_report;
+}
+
 /**
  * xs_close - close a socket
  * @xprt: transport
@@ -765,9 +783,8 @@ static void xs_close(struct rpc_xprt *xprt)
 	transport->sock = NULL;
 
 	sk->sk_user_data = NULL;
-	sk->sk_data_ready = transport->old_data_ready;
-	sk->sk_state_change = transport->old_state_change;
-	sk->sk_write_space = transport->old_write_space;
+
+	xs_restore_old_callbacks(transport, sk);
 	write_unlock_bh(&sk->sk_callback_lock);
 
 	sk->sk_no_check = 0;
@@ -1180,6 +1197,28 @@ static void xs_tcp_state_change(struct sock *sk)
 }
 
 /**
+ * xs_tcp_error_report - callback mainly for catching RST events
+ * @sk: socket
+ */
+static void xs_tcp_error_report(struct sock *sk)
+{
+	struct rpc_xprt *xprt;
+
+	read_lock(&sk->sk_callback_lock);
+	if (sk->sk_err != ECONNRESET || sk->sk_state != TCP_ESTABLISHED)
+		goto out;
+	if (!(xprt = xprt_from_sock(sk)))
+		goto out;
+	dprintk("RPC:       %s client %p...\n"
+			"RPC:       error %d\n",
+			__func__, xprt, sk->sk_err);
+
+	xprt_force_disconnect(xprt);
+out:
+	read_unlock(&sk->sk_callback_lock);
+}
+
+/**
  * xs_udp_write_space - callback invoked when socket buffer space
  *                             becomes available
  * @sk: socket whose state has changed
@@ -1454,10 +1493,9 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
 
 		write_lock_bh(&sk->sk_callback_lock);
 
+		xs_save_old_callbacks(transport, sk);
+
 		sk->sk_user_data = xprt;
-		transport->old_data_ready = sk->sk_data_ready;
-		transport->old_state_change = sk->sk_state_change;
-		transport->old_write_space = sk->sk_write_space;
 		sk->sk_data_ready = xs_udp_data_ready;
 		sk->sk_write_space = xs_udp_write_space;
 		sk->sk_no_check = UDP_CSUM_NORCV;
@@ -1589,13 +1627,13 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
 
 		write_lock_bh(&sk->sk_callback_lock);
 
+		xs_save_old_callbacks(transport, sk);
+
 		sk->sk_user_data = xprt;
-		transport->old_data_ready = sk->sk_data_ready;
-		transport->old_state_change = sk->sk_state_change;
-		transport->old_write_space = sk->sk_write_space;
 		sk->sk_data_ready = xs_tcp_data_ready;
 		sk->sk_state_change = xs_tcp_state_change;
 		sk->sk_write_space = xs_tcp_write_space;
+		sk->sk_error_report = xs_tcp_error_report;
 		sk->sk_allocation = GFP_ATOMIC;
 
 		/* socket options */

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [GIT] Please pull NFS client bugfixes
@ 2009-11-19 16:35 Trond Myklebust
  0 siblings, 0 replies; 3+ messages in thread
From: Trond Myklebust @ 2009-11-19 16:35 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux-nfs

Hi Linus,

Please pull from the "bugfixes" branch of the repository at

   git pull git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git bugfixes

This will update the following files through the appended changesets.

  Cheers,
    Trond

----
 fs/nfs/nfs4proc.c |    2 +-
 net/sunrpc/addr.c |   18 ++++++++----------
 2 files changed, 9 insertions(+), 11 deletions(-)

commit 1e360a60b24ad8f8685af66fa6de10ce46693a4b
Author: Chuck Lever <chuck.lever@oracle.com>
Date:   Fri Nov 13 10:52:55 2009 -0500

    SUNRPC: Address buffer overrun in rpc_uaddr2sockaddr()
    
    The size of buf[] must account for the string termination needed for
    the first strict_strtoul() call.  Introduced in commit a02d6926.
    
    Fábio Olivé Leite points out that strict_strtoul() requires _either_
    '\n\0' _or_ '\0' termination, so use the simpler '\0' here instead.
    
    See http://bugzilla.kernel.org/show_bug.cgi?id=14546 .
    
    Reported-by: argp@census-labs.com
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Signed-off-by: Fábio Olivé Leite <fleite@redhat.com>
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit 96d25e532234bec1a1989e6e1baf702d43a78b0d
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Wed Nov 11 16:15:42 2009 +0900

    NFSv4: Fix a cache validation bug which causes getcwd() to return ENOENT
    
    Changeset a65318bf3afc93ce49227e849d213799b072c5fd (NFSv4: Simplify some
    cache consistency post-op GETATTRs) incorrectly changed the getattr
    bitmap for readdir().
    This causes the readdir() function to fail to return a
    fileid/inode number, which again exposed a bug in the NFS readdir code that
    causes spurious ENOENT errors to appear in applications (see
    http://bugzilla.kernel.org/show_bug.cgi?id=14541).
    
    The immediate band aid is to revert the incorrect bitmap change, but more
    long term, we should change the NFS readdir code to cope with the
    fact that NFSv4 servers are not required to support fileids/inode numbers.
    
    Reported-by: Daniel J Blueman <daniel.blueman@gmail.com>
    Cc: stable@kernel.org
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [GIT] Please pull NFS client bugfixes...
@ 2009-10-27 21:35 Trond Myklebust
  0 siblings, 0 replies; 3+ messages in thread
From: Trond Myklebust @ 2009-10-27 21:35 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-nfs, linux-kernel

Hi Linus,

Please pull from the "bugfixes" branch of the repository at

   git pull git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git bugfixes

This will update the following files through the appended changesets.

  Cheers,
    Trond

----
 fs/nfs/dir.c      |    2 ++
 fs/nfs/direct.c   |    1 +
 fs/nfs/nfs4proc.c |   15 ++++++++-------
 fs/nfs/nfs4xdr.c  |    1 -
 4 files changed, 11 insertions(+), 8 deletions(-)

commit 9a3936aac133037f65124fcb2d676a6c201a90a4
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Mon Oct 26 08:09:46 2009 -0400

    NFSv4: The link() operation should return any delegation on the file
    
    Otherwise, we have to wait for the server to recall it.
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit 141aeb9f26f9f12f1584c128ce8697cdffb046e7
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Mon Oct 26 08:09:46 2009 -0400

    NFSv4: Fix two unbalanced put_rpccred() issues.
    
    Commits 29fba38b (nfs41: lease renewal) and fc01cea9 (nfs41: sequence
    operation) introduce a couple of put_rpccred() calls on credentials for
    which there is no corresponding get_rpccred().
    
    See http://bugzilla.kernel.org/show_bug.cgi?id=14249
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit 52567b03ca38b6e556ced450d64dba8d66e23b0e
Author: Trond Myklebust <Trond.Myklebust@netapp.com>
Date:   Fri Oct 23 14:46:42 2009 -0400

    NFSv4: Fix a bug when the server returns NFS4ERR_RESOURCE
    
    RFC 3530 states that when we recieve the error NFS4ERR_RESOURCE, we are not
    supposed to bump the sequence number on OPEN, LOCK, LOCKU, CLOSE, etc
    operations. The problem is that we map that error into EREMOTEIO in the XDR
    layer, and so the NFSv4 middle-layer routines like seqid_mutating_err(),
    and nfs_increment_seqid() don't recognise it.
    
    The fix is to defer the mapping until after the middle layers have
    processed the error.
    
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

commit a8b40bc7e635831b61c43acc71a86d3a68b2dff0
Author: Terry Loftin <terry.loftin@hp.com>
Date:   Thu Oct 22 21:36:01 2009 -0400

    nfs: Panic when commit fails
    
    Actually pass the NFS_FILE_SYNC option to the server to avoid a
    Panic in nfs_direct_write_complete() when a commit fails.
    
    At the end of an nfs write, if the nfs commit fails, all the writes
    will be rescheduled.  They are supposed to be rescheduled as NFS_FILE_SYNC
    writes, but the rpc_task structure is not completely intialized and so
    the option is not passed.  When the rescheduled writes complete, the
    return indicates that they are NFS_UNSTABLE and we try to do another
    commit.  This leads to a Panic because the commit data structure pointer
    was set to null in the initial (failed) commit attempt.
    
    Signed-off-by: Terry Loftin <terry.loftin@hp.com>
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 32062c3..7cb2985 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1536,6 +1536,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
+	nfs_inode_return_delegation(inode);
+
 	d_drop(dentry);
 	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
 	if (error == 0) {
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 6c32100..e1d415e 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -457,6 +457,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 	};
 	struct rpc_task_setup task_setup_data = {
 		.rpc_client = NFS_CLIENT(inode),
+		.rpc_message = &msg,
 		.callback_ops = &nfs_write_direct_ops,
 		.workqueue = nfsiod_workqueue,
 		.flags = RPC_TASK_ASYNC,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ed7c269..ff37454 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -72,12 +72,17 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 /* Prevent leaks of NFSv4 errors into userland */
 static int nfs4_map_errors(int err)
 {
-	if (err < -1000) {
+	if (err >= -1000)
+		return err;
+	switch (err) {
+	case -NFS4ERR_RESOURCE:
+		return -EREMOTEIO;
+	default:
 		dprintk("%s could not handle NFSv4 error %d\n",
 				__func__, -err);
-		return -EIO;
+		break;
 	}
-	return err;
+	return -EIO;
 }
 
 /*
@@ -3060,9 +3065,6 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
 	if (time_before(clp->cl_last_renewal,timestamp))
 		clp->cl_last_renewal = timestamp;
 	spin_unlock(&clp->cl_lock);
-	dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__,
-				task->tk_msg.rpc_cred);
-	put_rpccred(task->tk_msg.rpc_cred);
 }
 
 static const struct rpc_call_ops nfs4_renew_ops = {
@@ -4877,7 +4879,6 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 	nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
 	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
 
-	put_rpccred(task->tk_msg.rpc_cred);
 	kfree(task->tk_msg.rpc_argp);
 	kfree(task->tk_msg.rpc_resp);
 
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 83ad47c..20b4e30 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -5681,7 +5681,6 @@ static struct {
 	{ NFS4ERR_SERVERFAULT,	-ESERVERFAULT	},
 	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
 	{ NFS4ERR_LOCKED,	-EAGAIN		},
-	{ NFS4ERR_RESOURCE,	-EREMOTEIO	},
 	{ NFS4ERR_SYMLINK,	-ELOOP		},
 	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
 	{ NFS4ERR_DEADLOCK,	-EDEADLK	},

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-11-19 16:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-28 19:26 [GIT] Please pull nfs client bugfixes Trond Myklebust
2009-10-27 21:35 [GIT] Please pull NFS " Trond Myklebust
2009-11-19 16:35 Trond Myklebust

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).