| From 52b26a3e1bb3e065c32b3febdac1e1f117d88e15 Mon Sep 17 00:00:00 2001 |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Date: Thu, 26 Sep 2013 14:08:36 -0400 |
| Subject: NFSv4.1: nfs4_fl_prepare_ds - fix bugs when the connect attempt fails |
| |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| |
| commit 52b26a3e1bb3e065c32b3febdac1e1f117d88e15 upstream. |
| |
| - Fix an Oops when nfs4_ds_connect() returns an error. |
| - Always check the device status after waiting for a connect to complete. |
| |
| Reported-by: Andy Adamson <andros@netapp.com> |
| Reported-by: Jeff Layton <jlayton@redhat.com> |
| Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfs/nfs4filelayoutdev.c | 18 +++++++++--------- |
| 1 file changed, 9 insertions(+), 9 deletions(-) |
| |
| --- a/fs/nfs/nfs4filelayoutdev.c |
| +++ b/fs/nfs/nfs4filelayoutdev.c |
| @@ -797,34 +797,34 @@ nfs4_fl_prepare_ds(struct pnfs_layout_se |
| struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; |
| struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; |
| struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); |
| - |
| - if (filelayout_test_devid_unavailable(devid)) |
| - return NULL; |
| + struct nfs4_pnfs_ds *ret = ds; |
| |
| if (ds == NULL) { |
| printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", |
| __func__, ds_idx); |
| filelayout_mark_devid_invalid(devid); |
| - return NULL; |
| + goto out; |
| } |
| if (ds->ds_clp) |
| - return ds; |
| + goto out_test_devid; |
| |
| if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { |
| struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); |
| int err; |
| |
| err = nfs4_ds_connect(s, ds); |
| - if (err) { |
| + if (err) |
| nfs4_mark_deviceid_unavailable(devid); |
| - ds = NULL; |
| - } |
| nfs4_clear_ds_conn_bit(ds); |
| } else { |
| /* Either ds is connected, or ds is NULL */ |
| nfs4_wait_ds_connect(ds); |
| } |
| - return ds; |
| +out_test_devid: |
| + if (filelayout_test_devid_unavailable(devid)) |
| + ret = NULL; |
| +out: |
| + return ret; |
| } |
| |
| module_param(dataserver_retrans, uint, 0644); |