struct list_head        ds_addrs;
        struct nfs_client       *ds_clp;
        atomic_t                ds_count;
+       unsigned long           ds_state;
+#define NFS4DS_CONNECTING      0       /* ds is establishing connection */
 };
 
 struct nfs4_file_layout_dsaddr {
 
        return flseg->fh_array[i];
 }
 
+static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds)
+{
+       might_sleep();
+       wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING,
+                       nfs_wait_bit_killable, TASK_KILLABLE);
+}
+
+static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
+{
+       smp_mb__before_clear_bit();
+       clear_bit(NFS4DS_CONNECTING, &ds->ds_state);
+       smp_mb__after_clear_bit();
+       wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
+}
+
+
 struct nfs4_pnfs_ds *
 nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
 {
                filelayout_mark_devid_invalid(devid);
                return NULL;
        }
+       if (ds->ds_clp)
+               return ds;
 
-       if (!ds->ds_clp) {
+       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) {
                        nfs4_mark_deviceid_unavailable(devid);
-                       return NULL;
+                       ds = NULL;
                }
+               nfs4_clear_ds_conn_bit(ds);
+       } else {
+               /* Either ds is connected, or ds is NULL */
+               nfs4_wait_ds_connect(ds);
        }
        return ds;
 }