diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-26 14:08:36 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-29 15:56:35 -0400 |
commit | 52b26a3e1bb3e065c32b3febdac1e1f117d88e15 (patch) | |
tree | bcad0ee4bfb02acd387c4ef7f10ffdb1b69d52fc /fs/nfs/nfs4filelayoutdev.c | |
parent | 5bc2afc2b53fc73f154e6344cd898585628e6d27 (diff) |
NFSv4.1: nfs4_fl_prepare_ds - fix bugs when the connect attempt fails
- 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>
Cc: <stable@vger.kernel.org> # v3.10+
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 95604f64cab8..cd3aef571c34 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -801,34 +801,34 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) | |||
801 | struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; | 801 | struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; |
802 | struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; | 802 | struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; |
803 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); | 803 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); |
804 | 804 | struct nfs4_pnfs_ds *ret = ds; | |
805 | if (filelayout_test_devid_unavailable(devid)) | ||
806 | return NULL; | ||
807 | 805 | ||
808 | if (ds == NULL) { | 806 | if (ds == NULL) { |
809 | printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", | 807 | printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", |
810 | __func__, ds_idx); | 808 | __func__, ds_idx); |
811 | filelayout_mark_devid_invalid(devid); | 809 | filelayout_mark_devid_invalid(devid); |
812 | return NULL; | 810 | goto out; |
813 | } | 811 | } |
814 | if (ds->ds_clp) | 812 | if (ds->ds_clp) |
815 | return ds; | 813 | goto out_test_devid; |
816 | 814 | ||
817 | if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { | 815 | if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { |
818 | struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); | 816 | struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); |
819 | int err; | 817 | int err; |
820 | 818 | ||
821 | err = nfs4_ds_connect(s, ds); | 819 | err = nfs4_ds_connect(s, ds); |
822 | if (err) { | 820 | if (err) |
823 | nfs4_mark_deviceid_unavailable(devid); | 821 | nfs4_mark_deviceid_unavailable(devid); |
824 | ds = NULL; | ||
825 | } | ||
826 | nfs4_clear_ds_conn_bit(ds); | 822 | nfs4_clear_ds_conn_bit(ds); |
827 | } else { | 823 | } else { |
828 | /* Either ds is connected, or ds is NULL */ | 824 | /* Either ds is connected, or ds is NULL */ |
829 | nfs4_wait_ds_connect(ds); | 825 | nfs4_wait_ds_connect(ds); |
830 | } | 826 | } |
831 | return ds; | 827 | out_test_devid: |
828 | if (filelayout_test_devid_unavailable(devid)) | ||
829 | ret = NULL; | ||
830 | out: | ||
831 | return ret; | ||
832 | } | 832 | } |
833 | 833 | ||
834 | module_param(dataserver_retrans, uint, 0644); | 834 | module_param(dataserver_retrans, uint, 0644); |