diff options
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 22 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.h | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 15 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 4 | ||||
-rw-r--r-- | fs/nfs/pnfs_dev.c | 27 |
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 | ||
272 | bool | ||
273 | filelayout_test_devid_unavailable(struct nfs4_deviceid_node *node) | ||
274 | { | ||
275 | return filelayout_test_devid_invalid(node) || | ||
276 | nfs4_test_deviceid_unavailable(node); | ||
277 | } | ||
278 | |||
279 | static bool | ||
280 | filelayout_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 | ||
143 | static inline bool | 143 | extern bool |
144 | filelayout_reset_to_mds(struct pnfs_layout_segment *lseg) | 144 | filelayout_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 | ||
150 | extern struct nfs_fh * | 146 | extern struct nfs_fh * |
151 | nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); | 147 | nfs4_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 | |||
826 | mark_dev_invalid: | ||
827 | filelayout_mark_devid_invalid(devid); | ||
828 | return NULL; | ||
829 | } | 828 | } |
830 | 829 | ||
831 | module_param(dataserver_retrans, uint, 0644); | 830 | module_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 */ |
235 | enum { | 235 | enum { |
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 *); |
256 | struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); | 258 | struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); |
257 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); | 259 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); |
260 | void nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node); | ||
261 | bool nfs4_test_deviceid_unavailable(struct nfs4_deviceid_node *node); | ||
258 | void nfs4_deviceid_purge_client(const struct nfs_client *); | 262 | void nfs4_deviceid_purge_client(const struct nfs_client *); |
259 | 263 | ||
260 | static inline void | 264 | static 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 | |||
43 | static struct hlist_head nfs4_deviceid_cache[NFS4_DEVICE_ID_HASH_SIZE]; | 45 | static struct hlist_head nfs4_deviceid_cache[NFS4_DEVICE_ID_HASH_SIZE]; |
44 | static DEFINE_SPINLOCK(nfs4_deviceid_lock); | 46 | static DEFINE_SPINLOCK(nfs4_deviceid_lock); |
45 | 47 | ||
@@ -218,6 +220,30 @@ nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) | |||
218 | } | 220 | } |
219 | EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); | 221 | EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); |
220 | 222 | ||
223 | void | ||
224 | nfs4_mark_deviceid_unavailable(struct nfs4_deviceid_node *node) | ||
225 | { | ||
226 | node->timestamp_unavailable = jiffies; | ||
227 | set_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags); | ||
228 | } | ||
229 | EXPORT_SYMBOL_GPL(nfs4_mark_deviceid_unavailable); | ||
230 | |||
231 | bool | ||
232 | nfs4_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 | } | ||
245 | EXPORT_SYMBOL_GPL(nfs4_test_deviceid_unavailable); | ||
246 | |||
221 | static void | 247 | static 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 | |||