aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4filelayout.c22
-rw-r--r--fs/nfs/nfs4filelayout.h8
-rw-r--r--fs/nfs/nfs4filelayoutdev.c15
-rw-r--r--fs/nfs/pnfs.h4
-rw-r--r--fs/nfs/pnfs_dev.c27
5 files changed, 59 insertions, 17 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index af6ee4ad3f15..dac2162c3ac4 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -205,7 +205,7 @@ static int filelayout_async_handle_error(struct rpc_task *task,
205 case -EPIPE: 205 case -EPIPE:
206 dprintk("%s DS connection error %d\n", __func__, 206 dprintk("%s DS connection error %d\n", __func__,
207 task->tk_status); 207 task->tk_status);
208 filelayout_mark_devid_invalid(devid); 208 nfs4_mark_deviceid_unavailable(devid);
209 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); 209 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
210 _pnfs_return_layout(inode); 210 _pnfs_return_layout(inode);
211 rpc_wake_up(&tbl->slot_tbl_waitq); 211 rpc_wake_up(&tbl->slot_tbl_waitq);
@@ -269,6 +269,22 @@ filelayout_set_layoutcommit(struct nfs_write_data *wdata)
269 (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); 269 (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
270} 270}
271 271
272bool
273filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node)
274{
275 return filelayout_test_devid_invalid(node) ||
276 nfs4_test_deviceid_unavailable(node);
277}
278
279static bool
280filelayout_reset_to_mds(struct pnfs_layout_segment *lseg)
281{
282 struct nfs4_deviceid_node *node = FILELAYOUT_DEVID_NODE(lseg);
283
284 return filelayout_test_layout_invalid(lseg->pls_layout) ||
285 filelayout_test_devid_unavailable(node);
286}
287
272/* 288/*
273 * Call ops for the async read/write cases 289 * Call ops for the async read/write cases
274 * In the case of dense layouts, the offset needs to be reset to its 290 * In the case of dense layouts, the offset needs to be reset to its
@@ -613,8 +629,8 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
613 goto out; 629 goto out;
614 } else 630 } else
615 dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); 631 dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
616 /* Found deviceid is being reaped */ 632 /* Found deviceid is unavailable */
617 if (test_bit(NFS_DEVICEID_INVALID, &dsaddr->id_node.flags)) 633 if (filelayout_test_devid_unavailable(&dsaddr->id_node))
618 goto out_put; 634 goto out_put;
619 635
620 fl->dsaddr = dsaddr; 636 fl->dsaddr = dsaddr;
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 11053c425a61..10b0f134400b 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -140,12 +140,8 @@ filelayout_test_devid_invalid(struct nfs4_deviceid_node *node)
140 return test_bit(NFS_DEVICEID_INVALID, &node->flags); 140 return test_bit(NFS_DEVICEID_INVALID, &node->flags);
141} 141}
142 142
143static inline bool 143extern bool
144filelayout_reset_to_mds(struct pnfs_layout_segment *lseg) 144filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node);
145{
146 return filelayout_test_devid_invalid(FILELAYOUT_DEVID_NODE(lseg)) ||
147 filelayout_test_layout_invalid(lseg->pls_layout);
148}
149 145
150extern struct nfs_fh * 146extern struct nfs_fh *
151nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); 147nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index b85a29df20ae..3336d5eaf879 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -804,13 +804,14 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
804 struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; 804 struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
805 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); 805 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
806 806
807 if (filelayout_test_devid_invalid(devid)) 807 if (filelayout_test_devid_unavailable(devid))
808 return NULL; 808 return NULL;
809 809
810 if (ds == NULL) { 810 if (ds == NULL) {
811 printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", 811 printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
812 __func__, ds_idx); 812 __func__, ds_idx);
813 goto mark_dev_invalid; 813 filelayout_mark_devid_invalid(devid);
814 return NULL;
814 } 815 }
815 816
816 if (!ds->ds_clp) { 817 if (!ds->ds_clp) {
@@ -818,14 +819,12 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
818 int err; 819 int err;
819 820
820 err = nfs4_ds_connect(s, ds); 821 err = nfs4_ds_connect(s, ds);
821 if (err) 822 if (err) {
822 goto mark_dev_invalid; 823 nfs4_mark_deviceid_unavailable(devid);
824 return NULL;
825 }
823 } 826 }
824 return ds; 827 return ds;
825
826mark_dev_invalid:
827 filelayout_mark_devid_invalid(devid);
828 return NULL;
829} 828}
830 829
831module_param(dataserver_retrans, uint, 0644); 830module_param(dataserver_retrans, uint, 0644);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index bc8e5001203d..9735031e1e1a 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -234,6 +234,7 @@ struct nfs4_threshold *pnfs_mdsthreshold_alloc(void);
234/* nfs4_deviceid_flags */ 234/* nfs4_deviceid_flags */
235enum { 235enum {
236 NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */ 236 NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */
237 NFS_DEVICEID_UNAVAILABLE, /* device temporarily unavailable */
237}; 238};
238 239
239/* pnfs_dev.c */ 240/* pnfs_dev.c */
@@ -243,6 +244,7 @@ struct nfs4_deviceid_node {
243 const struct pnfs_layoutdriver_type *ld; 244 const struct pnfs_layoutdriver_type *ld;
244 const struct nfs_client *nfs_client; 245 const struct nfs_client *nfs_client;
245 unsigned long flags; 246 unsigned long flags;
247 unsigned long timestamp_unavailable;
246 struct nfs4_deviceid deviceid; 248 struct nfs4_deviceid deviceid;
247 atomic_t ref; 249 atomic_t ref;
248}; 250};
@@ -255,6 +257,8 @@ void nfs4_init_deviceid_node(struct nfs4_deviceid_node *,
255 const struct nfs4_deviceid *); 257 const struct nfs4_deviceid *);
256struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); 258struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *);
257bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); 259bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
260void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node);
261bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node);
258void nfs4_deviceid_purge_client(const struct nfs_client *); 262void nfs4_deviceid_purge_client(const struct nfs_client *);
259 263
260static inline void 264static inline void
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index 73f701f1f4d3..d35b62e83ea6 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -40,6 +40,8 @@
40#define NFS4_DEVICE_ID_HASH_SIZE (1 << NFS4_DEVICE_ID_HASH_BITS) 40#define NFS4_DEVICE_ID_HASH_SIZE (1 << NFS4_DEVICE_ID_HASH_BITS)
41#define NFS4_DEVICE_ID_HASH_MASK (NFS4_DEVICE_ID_HASH_SIZE - 1) 41#define NFS4_DEVICE_ID_HASH_MASK (NFS4_DEVICE_ID_HASH_SIZE - 1)
42 42
43#define PNFS_DEVICE_RETRY_TIMEOUT (120*HZ)
44
43static struct hlist_head nfs4_deviceid_cache[NFS4_DEVICE_ID_HASH_SIZE]; 45static struct hlist_head nfs4_deviceid_cache[NFS4_DEVICE_ID_HASH_SIZE];
44static DEFINE_SPINLOCK(nfs4_deviceid_lock); 46static DEFINE_SPINLOCK(nfs4_deviceid_lock);
45 47
@@ -218,6 +220,30 @@ nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)
218} 220}
219EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); 221EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node);
220 222
223void
224nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node)
225{
226 node->timestamp_unavailable = jiffies;
227 set_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags);
228}
229EXPORT_SYMBOL_GPL(nfs4_mark_deviceid_unavailable);
230
231bool
232nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node)
233{
234 if (test_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags)) {
235 unsigned long start, end;
236
237 end = jiffies;
238 start = end - PNFS_DEVICE_RETRY_TIMEOUT;
239 if (time_in_range(node->timestamp_unavailable, start, end))
240 return true;
241 clear_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags);
242 }
243 return false;
244}
245EXPORT_SYMBOL_GPL(nfs4_test_deviceid_unavailable);
246
221static void 247static void
222_deviceid_purge_client(const struct nfs_client *clp, long hash) 248_deviceid_purge_client(const struct nfs_client *clp, long hash)
223{ 249{
@@ -276,3 +302,4 @@ nfs4_deviceid_mark_client_invalid(struct nfs_client *clp)
276 } 302 }
277 rcu_read_unlock(); 303 rcu_read_unlock();
278} 304}
305