diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-13 18:19:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-13 18:19:39 -0400 |
commit | cf70cc5b9d6a07d21ffd521aee690d26315d1bdf (patch) | |
tree | 4804c11071e693eb5d66799bb8e05431f7905c84 | |
parent | 087fbc9962e10a65fb0b542ecfc116ebf6cf1735 (diff) | |
parent | a75b9df9d3bfc3cd1083974c045ae31ce5f3434f (diff) |
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
NFSv4.1: Ensure that layoutget uses the correct gfp modes
NFSv4.1: remove pnfs_layout_hdr from pnfs_destroy_all_layouts tmp_list
NFSv41: Resend on NFS4ERR_RETRY_UNCACHED_REP
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 27 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 34 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 6 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 34 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 6 | ||||
-rw-r--r-- | fs/nfs/read.c | 4 | ||||
-rw-r--r-- | fs/nfs/write.c | 4 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
9 files changed, 68 insertions, 50 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 6f8192f4cfc..be79dc9f386 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -117,6 +117,8 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
117 | case -EKEYEXPIRED: | 117 | case -EKEYEXPIRED: |
118 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); | 118 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); |
119 | break; | 119 | break; |
120 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
121 | break; | ||
120 | default: | 122 | default: |
121 | dprintk("%s DS error. Retry through MDS %d\n", __func__, | 123 | dprintk("%s DS error. Retry through MDS %d\n", __func__, |
122 | task->tk_status); | 124 | task->tk_status); |
@@ -416,7 +418,8 @@ static int | |||
416 | filelayout_check_layout(struct pnfs_layout_hdr *lo, | 418 | filelayout_check_layout(struct pnfs_layout_hdr *lo, |
417 | struct nfs4_filelayout_segment *fl, | 419 | struct nfs4_filelayout_segment *fl, |
418 | struct nfs4_layoutget_res *lgr, | 420 | struct nfs4_layoutget_res *lgr, |
419 | struct nfs4_deviceid *id) | 421 | struct nfs4_deviceid *id, |
422 | gfp_t gfp_flags) | ||
420 | { | 423 | { |
421 | struct nfs4_file_layout_dsaddr *dsaddr; | 424 | struct nfs4_file_layout_dsaddr *dsaddr; |
422 | int status = -EINVAL; | 425 | int status = -EINVAL; |
@@ -439,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
439 | /* find and reference the deviceid */ | 442 | /* find and reference the deviceid */ |
440 | dsaddr = nfs4_fl_find_get_deviceid(id); | 443 | dsaddr = nfs4_fl_find_get_deviceid(id); |
441 | if (dsaddr == NULL) { | 444 | if (dsaddr == NULL) { |
442 | dsaddr = get_device_info(lo->plh_inode, id); | 445 | dsaddr = get_device_info(lo->plh_inode, id, gfp_flags); |
443 | if (dsaddr == NULL) | 446 | if (dsaddr == NULL) |
444 | goto out; | 447 | goto out; |
445 | } | 448 | } |
@@ -500,7 +503,8 @@ static int | |||
500 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, | 503 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, |
501 | struct nfs4_filelayout_segment *fl, | 504 | struct nfs4_filelayout_segment *fl, |
502 | struct nfs4_layoutget_res *lgr, | 505 | struct nfs4_layoutget_res *lgr, |
503 | struct nfs4_deviceid *id) | 506 | struct nfs4_deviceid *id, |
507 | gfp_t gfp_flags) | ||
504 | { | 508 | { |
505 | struct xdr_stream stream; | 509 | struct xdr_stream stream; |
506 | struct xdr_buf buf = { | 510 | struct xdr_buf buf = { |
@@ -516,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
516 | 520 | ||
517 | dprintk("%s: set_layout_map Begin\n", __func__); | 521 | dprintk("%s: set_layout_map Begin\n", __func__); |
518 | 522 | ||
519 | scratch = alloc_page(GFP_KERNEL); | 523 | scratch = alloc_page(gfp_flags); |
520 | if (!scratch) | 524 | if (!scratch) |
521 | return -ENOMEM; | 525 | return -ENOMEM; |
522 | 526 | ||
@@ -554,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
554 | goto out_err; | 558 | goto out_err; |
555 | 559 | ||
556 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 560 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), |
557 | GFP_KERNEL); | 561 | gfp_flags); |
558 | if (!fl->fh_array) | 562 | if (!fl->fh_array) |
559 | goto out_err; | 563 | goto out_err; |
560 | 564 | ||
561 | for (i = 0; i < fl->num_fh; i++) { | 565 | for (i = 0; i < fl->num_fh; i++) { |
562 | /* Do we want to use a mempool here? */ | 566 | /* Do we want to use a mempool here? */ |
563 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); | 567 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags); |
564 | if (!fl->fh_array[i]) | 568 | if (!fl->fh_array[i]) |
565 | goto out_err_free; | 569 | goto out_err_free; |
566 | 570 | ||
@@ -605,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) | |||
605 | 609 | ||
606 | static struct pnfs_layout_segment * | 610 | static struct pnfs_layout_segment * |
607 | filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | 611 | filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, |
608 | struct nfs4_layoutget_res *lgr) | 612 | struct nfs4_layoutget_res *lgr, |
613 | gfp_t gfp_flags) | ||
609 | { | 614 | { |
610 | struct nfs4_filelayout_segment *fl; | 615 | struct nfs4_filelayout_segment *fl; |
611 | int rc; | 616 | int rc; |
612 | struct nfs4_deviceid id; | 617 | struct nfs4_deviceid id; |
613 | 618 | ||
614 | dprintk("--> %s\n", __func__); | 619 | dprintk("--> %s\n", __func__); |
615 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); | 620 | fl = kzalloc(sizeof(*fl), gfp_flags); |
616 | if (!fl) | 621 | if (!fl) |
617 | return NULL; | 622 | return NULL; |
618 | 623 | ||
619 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id); | 624 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags); |
620 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) { | 625 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) { |
621 | _filelayout_free_lseg(fl); | 626 | _filelayout_free_lseg(fl); |
622 | return NULL; | 627 | return NULL; |
623 | } | 628 | } |
@@ -633,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | |||
633 | int size = (fl->stripe_type == STRIPE_SPARSE) ? | 638 | int size = (fl->stripe_type == STRIPE_SPARSE) ? |
634 | fl->dsaddr->ds_num : fl->dsaddr->stripe_count; | 639 | fl->dsaddr->ds_num : fl->dsaddr->stripe_count; |
635 | 640 | ||
636 | fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL); | 641 | fl->commit_buckets = kcalloc(size, sizeof(struct list_head), gfp_flags); |
637 | if (!fl->commit_buckets) { | 642 | if (!fl->commit_buckets) { |
638 | filelayout_free_lseg(&fl->generic_hdr); | 643 | filelayout_free_lseg(&fl->generic_hdr); |
639 | return NULL; | 644 | return NULL; |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 7c44579f583..2b461d77b43 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
@@ -104,6 +104,6 @@ extern struct nfs4_file_layout_dsaddr * | |||
104 | nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id); | 104 | nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id); |
105 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 105 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
106 | struct nfs4_file_layout_dsaddr * | 106 | struct nfs4_file_layout_dsaddr * |
107 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id); | 107 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); |
108 | 108 | ||
109 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ | 109 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index de5350f2b24..db07c7af139 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -225,11 +225,11 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | |||
225 | } | 225 | } |
226 | 226 | ||
227 | static struct nfs4_pnfs_ds * | 227 | static struct nfs4_pnfs_ds * |
228 | nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port) | 228 | nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port, gfp_t gfp_flags) |
229 | { | 229 | { |
230 | struct nfs4_pnfs_ds *tmp_ds, *ds; | 230 | struct nfs4_pnfs_ds *tmp_ds, *ds; |
231 | 231 | ||
232 | ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL); | 232 | ds = kzalloc(sizeof(*tmp_ds), gfp_flags); |
233 | if (!ds) | 233 | if (!ds) |
234 | goto out; | 234 | goto out; |
235 | 235 | ||
@@ -261,7 +261,7 @@ out: | |||
261 | * Currently only support ipv4, and one multi-path address. | 261 | * Currently only support ipv4, and one multi-path address. |
262 | */ | 262 | */ |
263 | static struct nfs4_pnfs_ds * | 263 | static struct nfs4_pnfs_ds * |
264 | decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) | 264 | decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode, gfp_t gfp_flags) |
265 | { | 265 | { |
266 | struct nfs4_pnfs_ds *ds = NULL; | 266 | struct nfs4_pnfs_ds *ds = NULL; |
267 | char *buf; | 267 | char *buf; |
@@ -303,7 +303,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) | |||
303 | rlen); | 303 | rlen); |
304 | goto out_err; | 304 | goto out_err; |
305 | } | 305 | } |
306 | buf = kmalloc(rlen + 1, GFP_KERNEL); | 306 | buf = kmalloc(rlen + 1, gfp_flags); |
307 | if (!buf) { | 307 | if (!buf) { |
308 | dprintk("%s: Not enough memory\n", __func__); | 308 | dprintk("%s: Not enough memory\n", __func__); |
309 | goto out_err; | 309 | goto out_err; |
@@ -333,7 +333,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) | |||
333 | sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]); | 333 | sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]); |
334 | port = htons((tmp[0] << 8) | (tmp[1])); | 334 | port = htons((tmp[0] << 8) | (tmp[1])); |
335 | 335 | ||
336 | ds = nfs4_pnfs_ds_add(inode, ip_addr, port); | 336 | ds = nfs4_pnfs_ds_add(inode, ip_addr, port, gfp_flags); |
337 | dprintk("%s: Decoded address and port %s\n", __func__, buf); | 337 | dprintk("%s: Decoded address and port %s\n", __func__, buf); |
338 | out_free: | 338 | out_free: |
339 | kfree(buf); | 339 | kfree(buf); |
@@ -343,7 +343,7 @@ out_err: | |||
343 | 343 | ||
344 | /* Decode opaque device data and return the result */ | 344 | /* Decode opaque device data and return the result */ |
345 | static struct nfs4_file_layout_dsaddr* | 345 | static struct nfs4_file_layout_dsaddr* |
346 | decode_device(struct inode *ino, struct pnfs_device *pdev) | 346 | decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) |
347 | { | 347 | { |
348 | int i; | 348 | int i; |
349 | u32 cnt, num; | 349 | u32 cnt, num; |
@@ -362,7 +362,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
362 | struct page *scratch; | 362 | struct page *scratch; |
363 | 363 | ||
364 | /* set up xdr stream */ | 364 | /* set up xdr stream */ |
365 | scratch = alloc_page(GFP_KERNEL); | 365 | scratch = alloc_page(gfp_flags); |
366 | if (!scratch) | 366 | if (!scratch) |
367 | goto out_err; | 367 | goto out_err; |
368 | 368 | ||
@@ -384,7 +384,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | /* read stripe indices */ | 386 | /* read stripe indices */ |
387 | stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL); | 387 | stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags); |
388 | if (!stripe_indices) | 388 | if (!stripe_indices) |
389 | goto out_err_free_scratch; | 389 | goto out_err_free_scratch; |
390 | 390 | ||
@@ -423,7 +423,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
423 | 423 | ||
424 | dsaddr = kzalloc(sizeof(*dsaddr) + | 424 | dsaddr = kzalloc(sizeof(*dsaddr) + |
425 | (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), | 425 | (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), |
426 | GFP_KERNEL); | 426 | gfp_flags); |
427 | if (!dsaddr) | 427 | if (!dsaddr) |
428 | goto out_err_free_stripe_indices; | 428 | goto out_err_free_stripe_indices; |
429 | 429 | ||
@@ -452,7 +452,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
452 | for (j = 0; j < mp_count; j++) { | 452 | for (j = 0; j < mp_count; j++) { |
453 | if (j == 0) { | 453 | if (j == 0) { |
454 | dsaddr->ds_list[i] = decode_and_add_ds(&stream, | 454 | dsaddr->ds_list[i] = decode_and_add_ds(&stream, |
455 | ino); | 455 | ino, gfp_flags); |
456 | if (dsaddr->ds_list[i] == NULL) | 456 | if (dsaddr->ds_list[i] == NULL) |
457 | goto out_err_free_deviceid; | 457 | goto out_err_free_deviceid; |
458 | } else { | 458 | } else { |
@@ -503,12 +503,12 @@ out_err: | |||
503 | * available devices. | 503 | * available devices. |
504 | */ | 504 | */ |
505 | static struct nfs4_file_layout_dsaddr * | 505 | static struct nfs4_file_layout_dsaddr * |
506 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev) | 506 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) |
507 | { | 507 | { |
508 | struct nfs4_file_layout_dsaddr *d, *new; | 508 | struct nfs4_file_layout_dsaddr *d, *new; |
509 | long hash; | 509 | long hash; |
510 | 510 | ||
511 | new = decode_device(inode, dev); | 511 | new = decode_device(inode, dev, gfp_flags); |
512 | if (!new) { | 512 | if (!new) { |
513 | printk(KERN_WARNING "%s: Could not decode or add device\n", | 513 | printk(KERN_WARNING "%s: Could not decode or add device\n", |
514 | __func__); | 514 | __func__); |
@@ -537,7 +537,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev) | |||
537 | * of available devices, and return it. | 537 | * of available devices, and return it. |
538 | */ | 538 | */ |
539 | struct nfs4_file_layout_dsaddr * | 539 | struct nfs4_file_layout_dsaddr * |
540 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) | 540 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags) |
541 | { | 541 | { |
542 | struct pnfs_device *pdev = NULL; | 542 | struct pnfs_device *pdev = NULL; |
543 | u32 max_resp_sz; | 543 | u32 max_resp_sz; |
@@ -556,17 +556,17 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) | |||
556 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", | 556 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", |
557 | __func__, inode, max_resp_sz, max_pages); | 557 | __func__, inode, max_resp_sz, max_pages); |
558 | 558 | ||
559 | pdev = kzalloc(sizeof(struct pnfs_device), GFP_KERNEL); | 559 | pdev = kzalloc(sizeof(struct pnfs_device), gfp_flags); |
560 | if (pdev == NULL) | 560 | if (pdev == NULL) |
561 | return NULL; | 561 | return NULL; |
562 | 562 | ||
563 | pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); | 563 | pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags); |
564 | if (pages == NULL) { | 564 | if (pages == NULL) { |
565 | kfree(pdev); | 565 | kfree(pdev); |
566 | return NULL; | 566 | return NULL; |
567 | } | 567 | } |
568 | for (i = 0; i < max_pages; i++) { | 568 | for (i = 0; i < max_pages; i++) { |
569 | pages[i] = alloc_page(GFP_KERNEL); | 569 | pages[i] = alloc_page(gfp_flags); |
570 | if (!pages[i]) | 570 | if (!pages[i]) |
571 | goto out_free; | 571 | goto out_free; |
572 | } | 572 | } |
@@ -587,7 +587,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) | |||
587 | * Found new device, need to decode it and then add it to the | 587 | * Found new device, need to decode it and then add it to the |
588 | * list of known devices for this mountpoint. | 588 | * list of known devices for this mountpoint. |
589 | */ | 589 | */ |
590 | dsaddr = decode_and_add_device(inode, pdev); | 590 | dsaddr = decode_and_add_device(inode, pdev, gfp_flags); |
591 | out_free: | 591 | out_free: |
592 | for (i = 0; i < max_pages; i++) | 592 | for (i = 0; i < max_pages; i++) |
593 | __free_page(pages[i]); | 593 | __free_page(pages[i]); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 69c0f3c5ee7..cf1b339c393 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -300,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
300 | ret = nfs4_delay(server->client, &exception->timeout); | 300 | ret = nfs4_delay(server->client, &exception->timeout); |
301 | if (ret != 0) | 301 | if (ret != 0) |
302 | break; | 302 | break; |
303 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
303 | case -NFS4ERR_OLD_STATEID: | 304 | case -NFS4ERR_OLD_STATEID: |
304 | exception->retry = 1; | 305 | exception->retry = 1; |
305 | break; | 306 | break; |
@@ -3695,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3695 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3696 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
3696 | task->tk_status = 0; | 3697 | task->tk_status = 0; |
3697 | return -EAGAIN; | 3698 | return -EAGAIN; |
3699 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
3698 | case -NFS4ERR_OLD_STATEID: | 3700 | case -NFS4ERR_OLD_STATEID: |
3699 | task->tk_status = 0; | 3701 | task->tk_status = 0; |
3700 | return -EAGAIN; | 3702 | return -EAGAIN; |
@@ -4844,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4844 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 4846 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); |
4845 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 4847 | rpc_delay(task, NFS4_POLL_RETRY_MIN); |
4846 | task->tk_status = 0; | 4848 | task->tk_status = 0; |
4849 | /* fall through */ | ||
4850 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
4847 | nfs_restart_rpc(task, data->clp); | 4851 | nfs_restart_rpc(task, data->clp); |
4848 | return; | 4852 | return; |
4849 | } | 4853 | } |
@@ -5479,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf | |||
5479 | break; | 5483 | break; |
5480 | case -NFS4ERR_DELAY: | 5484 | case -NFS4ERR_DELAY: |
5481 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5485 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5486 | /* fall through */ | ||
5487 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
5482 | return -EAGAIN; | 5488 | return -EAGAIN; |
5483 | default: | 5489 | default: |
5484 | nfs4_schedule_lease_recovery(clp); | 5490 | nfs4_schedule_lease_recovery(clp); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index ff681ab65d3..f57f5281a52 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -383,6 +383,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp) | |||
383 | plh_layouts); | 383 | plh_layouts); |
384 | dprintk("%s freeing layout for inode %lu\n", __func__, | 384 | dprintk("%s freeing layout for inode %lu\n", __func__, |
385 | lo->plh_inode->i_ino); | 385 | lo->plh_inode->i_ino); |
386 | list_del_init(&lo->plh_layouts); | ||
386 | pnfs_destroy_layout(NFS_I(lo->plh_inode)); | 387 | pnfs_destroy_layout(NFS_I(lo->plh_inode)); |
387 | } | 388 | } |
388 | } | 389 | } |
@@ -466,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, | |||
466 | static struct pnfs_layout_segment * | 467 | static struct pnfs_layout_segment * |
467 | send_layoutget(struct pnfs_layout_hdr *lo, | 468 | send_layoutget(struct pnfs_layout_hdr *lo, |
468 | struct nfs_open_context *ctx, | 469 | struct nfs_open_context *ctx, |
469 | u32 iomode) | 470 | u32 iomode, |
471 | gfp_t gfp_flags) | ||
470 | { | 472 | { |
471 | struct inode *ino = lo->plh_inode; | 473 | struct inode *ino = lo->plh_inode; |
472 | struct nfs_server *server = NFS_SERVER(ino); | 474 | struct nfs_server *server = NFS_SERVER(ino); |
@@ -479,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
479 | dprintk("--> %s\n", __func__); | 481 | dprintk("--> %s\n", __func__); |
480 | 482 | ||
481 | BUG_ON(ctx == NULL); | 483 | BUG_ON(ctx == NULL); |
482 | lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); | 484 | lgp = kzalloc(sizeof(*lgp), gfp_flags); |
483 | if (lgp == NULL) | 485 | if (lgp == NULL) |
484 | return NULL; | 486 | return NULL; |
485 | 487 | ||
@@ -487,12 +489,12 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
487 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | 489 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
488 | max_pages = max_resp_sz >> PAGE_SHIFT; | 490 | max_pages = max_resp_sz >> PAGE_SHIFT; |
489 | 491 | ||
490 | pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); | 492 | pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags); |
491 | if (!pages) | 493 | if (!pages) |
492 | goto out_err_free; | 494 | goto out_err_free; |
493 | 495 | ||
494 | for (i = 0; i < max_pages; i++) { | 496 | for (i = 0; i < max_pages; i++) { |
495 | pages[i] = alloc_page(GFP_KERNEL); | 497 | pages[i] = alloc_page(gfp_flags); |
496 | if (!pages[i]) | 498 | if (!pages[i]) |
497 | goto out_err_free; | 499 | goto out_err_free; |
498 | } | 500 | } |
@@ -508,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
508 | lgp->args.layout.pages = pages; | 510 | lgp->args.layout.pages = pages; |
509 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | 511 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; |
510 | lgp->lsegpp = &lseg; | 512 | lgp->lsegpp = &lseg; |
513 | lgp->gfp_flags = gfp_flags; | ||
511 | 514 | ||
512 | /* Synchronously retrieve layout information from server and | 515 | /* Synchronously retrieve layout information from server and |
513 | * store in lseg. | 516 | * store in lseg. |
@@ -665,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo, | |||
665 | } | 668 | } |
666 | 669 | ||
667 | static struct pnfs_layout_hdr * | 670 | static struct pnfs_layout_hdr * |
668 | alloc_init_layout_hdr(struct inode *ino) | 671 | alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags) |
669 | { | 672 | { |
670 | struct pnfs_layout_hdr *lo; | 673 | struct pnfs_layout_hdr *lo; |
671 | 674 | ||
672 | lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL); | 675 | lo = kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags); |
673 | if (!lo) | 676 | if (!lo) |
674 | return NULL; | 677 | return NULL; |
675 | atomic_set(&lo->plh_refcount, 1); | 678 | atomic_set(&lo->plh_refcount, 1); |
@@ -681,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino) | |||
681 | } | 684 | } |
682 | 685 | ||
683 | static struct pnfs_layout_hdr * | 686 | static struct pnfs_layout_hdr * |
684 | pnfs_find_alloc_layout(struct inode *ino) | 687 | pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags) |
685 | { | 688 | { |
686 | struct nfs_inode *nfsi = NFS_I(ino); | 689 | struct nfs_inode *nfsi = NFS_I(ino); |
687 | struct pnfs_layout_hdr *new = NULL; | 690 | struct pnfs_layout_hdr *new = NULL; |
@@ -696,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino) | |||
696 | return nfsi->layout; | 699 | return nfsi->layout; |
697 | } | 700 | } |
698 | spin_unlock(&ino->i_lock); | 701 | spin_unlock(&ino->i_lock); |
699 | new = alloc_init_layout_hdr(ino); | 702 | new = alloc_init_layout_hdr(ino, gfp_flags); |
700 | spin_lock(&ino->i_lock); | 703 | spin_lock(&ino->i_lock); |
701 | 704 | ||
702 | if (likely(nfsi->layout == NULL)) /* Won the race? */ | 705 | if (likely(nfsi->layout == NULL)) /* Won the race? */ |
@@ -756,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode) | |||
756 | struct pnfs_layout_segment * | 759 | struct pnfs_layout_segment * |
757 | pnfs_update_layout(struct inode *ino, | 760 | pnfs_update_layout(struct inode *ino, |
758 | struct nfs_open_context *ctx, | 761 | struct nfs_open_context *ctx, |
759 | enum pnfs_iomode iomode) | 762 | enum pnfs_iomode iomode, |
763 | gfp_t gfp_flags) | ||
760 | { | 764 | { |
761 | struct nfs_inode *nfsi = NFS_I(ino); | 765 | struct nfs_inode *nfsi = NFS_I(ino); |
762 | struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; | 766 | struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; |
@@ -767,7 +771,7 @@ pnfs_update_layout(struct inode *ino, | |||
767 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) | 771 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) |
768 | return NULL; | 772 | return NULL; |
769 | spin_lock(&ino->i_lock); | 773 | spin_lock(&ino->i_lock); |
770 | lo = pnfs_find_alloc_layout(ino); | 774 | lo = pnfs_find_alloc_layout(ino, gfp_flags); |
771 | if (lo == NULL) { | 775 | if (lo == NULL) { |
772 | dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); | 776 | dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); |
773 | goto out_unlock; | 777 | goto out_unlock; |
@@ -807,7 +811,7 @@ pnfs_update_layout(struct inode *ino, | |||
807 | spin_unlock(&clp->cl_lock); | 811 | spin_unlock(&clp->cl_lock); |
808 | } | 812 | } |
809 | 813 | ||
810 | lseg = send_layoutget(lo, ctx, iomode); | 814 | lseg = send_layoutget(lo, ctx, iomode, gfp_flags); |
811 | if (!lseg && first) { | 815 | if (!lseg && first) { |
812 | spin_lock(&clp->cl_lock); | 816 | spin_lock(&clp->cl_lock); |
813 | list_del_init(&lo->plh_layouts); | 817 | list_del_init(&lo->plh_layouts); |
@@ -846,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
846 | goto out; | 850 | goto out; |
847 | } | 851 | } |
848 | /* Inject layout blob into I/O device driver */ | 852 | /* Inject layout blob into I/O device driver */ |
849 | lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res); | 853 | lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags); |
850 | if (!lseg || IS_ERR(lseg)) { | 854 | if (!lseg || IS_ERR(lseg)) { |
851 | if (!lseg) | 855 | if (!lseg) |
852 | status = -ENOMEM; | 856 | status = -ENOMEM; |
@@ -899,7 +903,8 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio, | |||
899 | /* This is first coelesce call for a series of nfs_pages */ | 903 | /* This is first coelesce call for a series of nfs_pages */ |
900 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 904 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
901 | prev->wb_context, | 905 | prev->wb_context, |
902 | IOMODE_READ); | 906 | IOMODE_READ, |
907 | GFP_KERNEL); | ||
903 | } | 908 | } |
904 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); | 909 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); |
905 | } | 910 | } |
@@ -921,7 +926,8 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio, | |||
921 | /* This is first coelesce call for a series of nfs_pages */ | 926 | /* This is first coelesce call for a series of nfs_pages */ |
922 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 927 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
923 | prev->wb_context, | 928 | prev->wb_context, |
924 | IOMODE_RW); | 929 | IOMODE_RW, |
930 | GFP_NOFS); | ||
925 | } | 931 | } |
926 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); | 932 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); |
927 | } | 933 | } |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index bc4827202e7..0c015bad9e7 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -70,7 +70,7 @@ struct pnfs_layoutdriver_type { | |||
70 | const u32 id; | 70 | const u32 id; |
71 | const char *name; | 71 | const char *name; |
72 | struct module *owner; | 72 | struct module *owner; |
73 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); | 73 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags); |
74 | void (*free_lseg) (struct pnfs_layout_segment *lseg); | 74 | void (*free_lseg) (struct pnfs_layout_segment *lseg); |
75 | 75 | ||
76 | /* test for nfs page cache coalescing */ | 76 | /* test for nfs page cache coalescing */ |
@@ -126,7 +126,7 @@ void get_layout_hdr(struct pnfs_layout_hdr *lo); | |||
126 | void put_lseg(struct pnfs_layout_segment *lseg); | 126 | void put_lseg(struct pnfs_layout_segment *lseg); |
127 | struct pnfs_layout_segment * | 127 | struct pnfs_layout_segment * |
128 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | 128 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, |
129 | enum pnfs_iomode access_type); | 129 | enum pnfs_iomode access_type, gfp_t gfp_flags); |
130 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); | 130 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); |
131 | void unset_pnfs_layoutdriver(struct nfs_server *); | 131 | void unset_pnfs_layoutdriver(struct nfs_server *); |
132 | enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, | 132 | enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, |
@@ -245,7 +245,7 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg) | |||
245 | 245 | ||
246 | static inline struct pnfs_layout_segment * | 246 | static inline struct pnfs_layout_segment * |
247 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | 247 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, |
248 | enum pnfs_iomode access_type) | 248 | enum pnfs_iomode access_type, gfp_t gfp_flags) |
249 | { | 249 | { |
250 | return NULL; | 250 | return NULL; |
251 | } | 251 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 7cded2b12a0..2bcf0dc306a 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -288,7 +288,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc) | |||
288 | atomic_set(&req->wb_complete, requests); | 288 | atomic_set(&req->wb_complete, requests); |
289 | 289 | ||
290 | BUG_ON(desc->pg_lseg != NULL); | 290 | BUG_ON(desc->pg_lseg != NULL); |
291 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ); | 291 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL); |
292 | ClearPageError(page); | 292 | ClearPageError(page); |
293 | offset = 0; | 293 | offset = 0; |
294 | nbytes = desc->pg_count; | 294 | nbytes = desc->pg_count; |
@@ -351,7 +351,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc) | |||
351 | } | 351 | } |
352 | req = nfs_list_entry(data->pages.next); | 352 | req = nfs_list_entry(data->pages.next); |
353 | if ((!lseg) && list_is_singular(&data->pages)) | 353 | if ((!lseg) && list_is_singular(&data->pages)) |
354 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ); | 354 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL); |
355 | 355 | ||
356 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, | 356 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, |
357 | 0, lseg); | 357 | 0, lseg); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 3bd5d7e80f6..49c715b4ac9 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -939,7 +939,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
939 | atomic_set(&req->wb_complete, requests); | 939 | atomic_set(&req->wb_complete, requests); |
940 | 940 | ||
941 | BUG_ON(desc->pg_lseg); | 941 | BUG_ON(desc->pg_lseg); |
942 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); | 942 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS); |
943 | ClearPageError(page); | 943 | ClearPageError(page); |
944 | offset = 0; | 944 | offset = 0; |
945 | nbytes = desc->pg_count; | 945 | nbytes = desc->pg_count; |
@@ -1013,7 +1013,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | |||
1013 | } | 1013 | } |
1014 | req = nfs_list_entry(data->pages.next); | 1014 | req = nfs_list_entry(data->pages.next); |
1015 | if ((!lseg) && list_is_singular(&data->pages)) | 1015 | if ((!lseg) && list_is_singular(&data->pages)) |
1016 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); | 1016 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS); |
1017 | 1017 | ||
1018 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 1018 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
1019 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | 1019 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 890dce24263..7e371f7df9c 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -233,6 +233,7 @@ struct nfs4_layoutget { | |||
233 | struct nfs4_layoutget_args args; | 233 | struct nfs4_layoutget_args args; |
234 | struct nfs4_layoutget_res res; | 234 | struct nfs4_layoutget_res res; |
235 | struct pnfs_layout_segment **lsegpp; | 235 | struct pnfs_layout_segment **lsegpp; |
236 | gfp_t gfp_flags; | ||
236 | }; | 237 | }; |
237 | 238 | ||
238 | struct nfs4_getdeviceinfo_args { | 239 | struct nfs4_getdeviceinfo_args { |