diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/namespace.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-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 | 124 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 51 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 53 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 42 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 6 | ||||
-rw-r--r-- | fs/nfs/read.c | 4 | ||||
-rw-r--r-- | fs/nfs/super.c | 13 | ||||
-rw-r--r-- | fs/nfs/write.c | 8 |
13 files changed, 209 insertions, 160 deletions
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 89fc160fd5b0..1f063bacd285 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -119,7 +119,7 @@ Elong: | |||
119 | } | 119 | } |
120 | 120 | ||
121 | #ifdef CONFIG_NFS_V4 | 121 | #ifdef CONFIG_NFS_V4 |
122 | static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode) | 122 | static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) |
123 | { | 123 | { |
124 | struct gss_api_mech *mech; | 124 | struct gss_api_mech *mech; |
125 | struct xdr_netobj oid; | 125 | struct xdr_netobj oid; |
@@ -166,7 +166,7 @@ static int nfs_negotiate_security(const struct dentry *parent, | |||
166 | } | 166 | } |
167 | flavors = page_address(page); | 167 | flavors = page_address(page); |
168 | ret = secinfo(parent->d_inode, &dentry->d_name, flavors); | 168 | ret = secinfo(parent->d_inode, &dentry->d_name, flavors); |
169 | *flavor = nfs_find_best_sec(flavors, dentry->d_inode); | 169 | *flavor = nfs_find_best_sec(flavors); |
170 | put_page(page); | 170 | put_page(page); |
171 | } | 171 | } |
172 | 172 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index e1c261ddd65d..c4a69833dd0d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -47,6 +47,7 @@ enum nfs4_client_state { | |||
47 | NFS4CLNT_LAYOUTRECALL, | 47 | NFS4CLNT_LAYOUTRECALL, |
48 | NFS4CLNT_SESSION_RESET, | 48 | NFS4CLNT_SESSION_RESET, |
49 | NFS4CLNT_RECALL_SLOT, | 49 | NFS4CLNT_RECALL_SLOT, |
50 | NFS4CLNT_LEASE_CONFIRM, | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | enum nfs4_session_state { | 53 | enum nfs4_session_state { |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 6f8192f4cfc7..be79dc9f386d 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 7c44579f5832..2b461d77b43a 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 de5350f2b249..db07c7af1395 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 9bf41eab3e46..cf1b339c3937 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/nfs4.h> | 46 | #include <linux/nfs4.h> |
47 | #include <linux/nfs_fs.h> | 47 | #include <linux/nfs_fs.h> |
48 | #include <linux/nfs_page.h> | 48 | #include <linux/nfs_page.h> |
49 | #include <linux/nfs_mount.h> | ||
49 | #include <linux/namei.h> | 50 | #include <linux/namei.h> |
50 | #include <linux/mount.h> | 51 | #include <linux/mount.h> |
51 | #include <linux/module.h> | 52 | #include <linux/module.h> |
@@ -299,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
299 | ret = nfs4_delay(server->client, &exception->timeout); | 300 | ret = nfs4_delay(server->client, &exception->timeout); |
300 | if (ret != 0) | 301 | if (ret != 0) |
301 | break; | 302 | break; |
303 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
302 | case -NFS4ERR_OLD_STATEID: | 304 | case -NFS4ERR_OLD_STATEID: |
303 | exception->retry = 1; | 305 | exception->retry = 1; |
304 | break; | 306 | break; |
@@ -443,8 +445,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
443 | if (res->sr_status == 1) | 445 | if (res->sr_status == 1) |
444 | res->sr_status = NFS_OK; | 446 | res->sr_status = NFS_OK; |
445 | 447 | ||
446 | /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ | 448 | /* don't increment the sequence number if the task wasn't sent */ |
447 | if (!res->sr_slot) | 449 | if (!RPC_WAS_SENT(task)) |
448 | goto out; | 450 | goto out; |
449 | 451 | ||
450 | /* Check the SEQUENCE operation status */ | 452 | /* Check the SEQUENCE operation status */ |
@@ -2185,9 +2187,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2185 | struct nfs4_exception exception = { }; | 2187 | struct nfs4_exception exception = { }; |
2186 | int err; | 2188 | int err; |
2187 | do { | 2189 | do { |
2188 | err = nfs4_handle_exception(server, | 2190 | err = _nfs4_lookup_root(server, fhandle, info); |
2189 | _nfs4_lookup_root(server, fhandle, info), | 2191 | switch (err) { |
2190 | &exception); | 2192 | case 0: |
2193 | case -NFS4ERR_WRONGSEC: | ||
2194 | break; | ||
2195 | default: | ||
2196 | err = nfs4_handle_exception(server, err, &exception); | ||
2197 | } | ||
2191 | } while (exception.retry); | 2198 | } while (exception.retry); |
2192 | return err; | 2199 | return err; |
2193 | } | 2200 | } |
@@ -2208,25 +2215,47 @@ out: | |||
2208 | return ret; | 2215 | return ret; |
2209 | } | 2216 | } |
2210 | 2217 | ||
2211 | /* | 2218 | static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, |
2212 | * get the file handle for the "/" directory on the server | ||
2213 | */ | ||
2214 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2215 | struct nfs_fsinfo *info) | 2219 | struct nfs_fsinfo *info) |
2216 | { | 2220 | { |
2217 | int i, len, status = 0; | 2221 | int i, len, status = 0; |
2218 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; | 2222 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2219 | 2223 | ||
2220 | flav_array[0] = RPC_AUTH_UNIX; | 2224 | len = gss_mech_list_pseudoflavors(&flav_array[0]); |
2221 | len = gss_mech_list_pseudoflavors(&flav_array[1]); | 2225 | flav_array[len] = RPC_AUTH_NULL; |
2222 | flav_array[1+len] = RPC_AUTH_NULL; | 2226 | len += 1; |
2223 | len += 2; | ||
2224 | 2227 | ||
2225 | for (i = 0; i < len; i++) { | 2228 | for (i = 0; i < len; i++) { |
2226 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | 2229 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); |
2227 | if (status != -EPERM) | 2230 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) |
2228 | break; | 2231 | continue; |
2232 | break; | ||
2229 | } | 2233 | } |
2234 | /* | ||
2235 | * -EACCESS could mean that the user doesn't have correct permissions | ||
2236 | * to access the mount. It could also mean that we tried to mount | ||
2237 | * with a gss auth flavor, but rpc.gssd isn't running. Either way, | ||
2238 | * existing mount programs don't handle -EACCES very well so it should | ||
2239 | * be mapped to -EPERM instead. | ||
2240 | */ | ||
2241 | if (status == -EACCES) | ||
2242 | status = -EPERM; | ||
2243 | return status; | ||
2244 | } | ||
2245 | |||
2246 | /* | ||
2247 | * get the file handle for the "/" directory on the server | ||
2248 | */ | ||
2249 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2250 | struct nfs_fsinfo *info) | ||
2251 | { | ||
2252 | int status = nfs4_lookup_root(server, fhandle, info); | ||
2253 | if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) | ||
2254 | /* | ||
2255 | * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM | ||
2256 | * by nfs4_map_errors() as this function exits. | ||
2257 | */ | ||
2258 | status = nfs4_find_root_sec(server, fhandle, info); | ||
2230 | if (status == 0) | 2259 | if (status == 0) |
2231 | status = nfs4_server_capabilities(server, fhandle); | 2260 | status = nfs4_server_capabilities(server, fhandle); |
2232 | if (status == 0) | 2261 | if (status == 0) |
@@ -3667,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3667 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3696 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
3668 | task->tk_status = 0; | 3697 | task->tk_status = 0; |
3669 | return -EAGAIN; | 3698 | return -EAGAIN; |
3699 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
3670 | case -NFS4ERR_OLD_STATEID: | 3700 | case -NFS4ERR_OLD_STATEID: |
3671 | task->tk_status = 0; | 3701 | task->tk_status = 0; |
3672 | return -EAGAIN; | 3702 | return -EAGAIN; |
@@ -3723,21 +3753,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3723 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", | 3753 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
3724 | clp->cl_ipaddr, port >> 8, port & 255); | 3754 | clp->cl_ipaddr, port >> 8, port & 255); |
3725 | 3755 | ||
3726 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3756 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3727 | if (status != -NFS4ERR_CLID_INUSE) | 3757 | if (status != -NFS4ERR_CLID_INUSE) |
3728 | break; | 3758 | break; |
3729 | if (signalled()) | 3759 | if (loop != 0) { |
3760 | ++clp->cl_id_uniquifier; | ||
3730 | break; | 3761 | break; |
3731 | if (loop++ & 1) | 3762 | } |
3732 | ssleep(clp->cl_lease_time / HZ + 1); | 3763 | ++loop; |
3733 | else | 3764 | ssleep(clp->cl_lease_time / HZ + 1); |
3734 | if (++clp->cl_id_uniquifier == 0) | ||
3735 | break; | ||
3736 | } | 3765 | } |
3737 | return status; | 3766 | return status; |
3738 | } | 3767 | } |
3739 | 3768 | ||
3740 | static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | 3769 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
3741 | struct nfs4_setclientid_res *arg, | 3770 | struct nfs4_setclientid_res *arg, |
3742 | struct rpc_cred *cred) | 3771 | struct rpc_cred *cred) |
3743 | { | 3772 | { |
@@ -3752,7 +3781,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3752 | int status; | 3781 | int status; |
3753 | 3782 | ||
3754 | now = jiffies; | 3783 | now = jiffies; |
3755 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3784 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3756 | if (status == 0) { | 3785 | if (status == 0) { |
3757 | spin_lock(&clp->cl_lock); | 3786 | spin_lock(&clp->cl_lock); |
3758 | clp->cl_lease_time = fsinfo.lease_time * HZ; | 3787 | clp->cl_lease_time = fsinfo.lease_time * HZ; |
@@ -3762,26 +3791,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3762 | return status; | 3791 | return status; |
3763 | } | 3792 | } |
3764 | 3793 | ||
3765 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | ||
3766 | struct nfs4_setclientid_res *arg, | ||
3767 | struct rpc_cred *cred) | ||
3768 | { | ||
3769 | long timeout = 0; | ||
3770 | int err; | ||
3771 | do { | ||
3772 | err = _nfs4_proc_setclientid_confirm(clp, arg, cred); | ||
3773 | switch (err) { | ||
3774 | case 0: | ||
3775 | return err; | ||
3776 | case -NFS4ERR_RESOURCE: | ||
3777 | /* The IBM lawyers misread another document! */ | ||
3778 | case -NFS4ERR_DELAY: | ||
3779 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
3780 | } | ||
3781 | } while (err == 0); | ||
3782 | return err; | ||
3783 | } | ||
3784 | |||
3785 | struct nfs4_delegreturndata { | 3794 | struct nfs4_delegreturndata { |
3786 | struct nfs4_delegreturnargs args; | 3795 | struct nfs4_delegreturnargs args; |
3787 | struct nfs4_delegreturnres res; | 3796 | struct nfs4_delegreturnres res; |
@@ -4786,7 +4795,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4786 | init_utsname()->domainname, | 4795 | init_utsname()->domainname, |
4787 | clp->cl_rpcclient->cl_auth->au_flavor); | 4796 | clp->cl_rpcclient->cl_auth->au_flavor); |
4788 | 4797 | ||
4789 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 4798 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4790 | if (!status) | 4799 | if (!status) |
4791 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 4800 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); |
4792 | dprintk("<-- %s status= %d\n", __func__, status); | 4801 | dprintk("<-- %s status= %d\n", __func__, status); |
@@ -4837,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4837 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 4846 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); |
4838 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 4847 | rpc_delay(task, NFS4_POLL_RETRY_MIN); |
4839 | task->tk_status = 0; | 4848 | task->tk_status = 0; |
4849 | /* fall through */ | ||
4850 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
4840 | nfs_restart_rpc(task, data->clp); | 4851 | nfs_restart_rpc(task, data->clp); |
4841 | return; | 4852 | return; |
4842 | } | 4853 | } |
@@ -4869,7 +4880,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
4869 | .rpc_client = clp->cl_rpcclient, | 4880 | .rpc_client = clp->cl_rpcclient, |
4870 | .rpc_message = &msg, | 4881 | .rpc_message = &msg, |
4871 | .callback_ops = &nfs4_get_lease_time_ops, | 4882 | .callback_ops = &nfs4_get_lease_time_ops, |
4872 | .callback_data = &data | 4883 | .callback_data = &data, |
4884 | .flags = RPC_TASK_TIMEOUT, | ||
4873 | }; | 4885 | }; |
4874 | int status; | 4886 | int status; |
4875 | 4887 | ||
@@ -5171,7 +5183,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp) | |||
5171 | nfs4_init_channel_attrs(&args); | 5183 | nfs4_init_channel_attrs(&args); |
5172 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); | 5184 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); |
5173 | 5185 | ||
5174 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | 5186 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5175 | 5187 | ||
5176 | if (!status) | 5188 | if (!status) |
5177 | /* Verify the session's negotiated channel_attrs values */ | 5189 | /* Verify the session's negotiated channel_attrs values */ |
@@ -5194,20 +5206,10 @@ int nfs4_proc_create_session(struct nfs_client *clp) | |||
5194 | int status; | 5206 | int status; |
5195 | unsigned *ptr; | 5207 | unsigned *ptr; |
5196 | struct nfs4_session *session = clp->cl_session; | 5208 | struct nfs4_session *session = clp->cl_session; |
5197 | long timeout = 0; | ||
5198 | int err; | ||
5199 | 5209 | ||
5200 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); | 5210 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); |
5201 | 5211 | ||
5202 | do { | 5212 | status = _nfs4_proc_create_session(clp); |
5203 | status = _nfs4_proc_create_session(clp); | ||
5204 | if (status == -NFS4ERR_DELAY) { | ||
5205 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
5206 | if (err) | ||
5207 | status = err; | ||
5208 | } | ||
5209 | } while (status == -NFS4ERR_DELAY); | ||
5210 | |||
5211 | if (status) | 5213 | if (status) |
5212 | goto out; | 5214 | goto out; |
5213 | 5215 | ||
@@ -5248,7 +5250,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
5248 | msg.rpc_argp = session; | 5250 | msg.rpc_argp = session; |
5249 | msg.rpc_resp = NULL; | 5251 | msg.rpc_resp = NULL; |
5250 | msg.rpc_cred = NULL; | 5252 | msg.rpc_cred = NULL; |
5251 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | 5253 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5252 | 5254 | ||
5253 | if (status) | 5255 | if (status) |
5254 | printk(KERN_WARNING | 5256 | printk(KERN_WARNING |
@@ -5481,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf | |||
5481 | break; | 5483 | break; |
5482 | case -NFS4ERR_DELAY: | 5484 | case -NFS4ERR_DELAY: |
5483 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5485 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5486 | /* fall through */ | ||
5487 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
5484 | return -EAGAIN; | 5488 | return -EAGAIN; |
5485 | default: | 5489 | default: |
5486 | nfs4_schedule_lease_recovery(clp); | 5490 | nfs4_schedule_lease_recovery(clp); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index a6804f704d9d..036f5adc9e1f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -64,10 +64,15 @@ static LIST_HEAD(nfs4_clientid_list); | |||
64 | 64 | ||
65 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 65 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) |
66 | { | 66 | { |
67 | struct nfs4_setclientid_res clid; | 67 | struct nfs4_setclientid_res clid = { |
68 | .clientid = clp->cl_clientid, | ||
69 | .confirm = clp->cl_confirm, | ||
70 | }; | ||
68 | unsigned short port; | 71 | unsigned short port; |
69 | int status; | 72 | int status; |
70 | 73 | ||
74 | if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) | ||
75 | goto do_confirm; | ||
71 | port = nfs_callback_tcpport; | 76 | port = nfs_callback_tcpport; |
72 | if (clp->cl_addr.ss_family == AF_INET6) | 77 | if (clp->cl_addr.ss_family == AF_INET6) |
73 | port = nfs_callback_tcpport6; | 78 | port = nfs_callback_tcpport6; |
@@ -75,10 +80,14 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
75 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); | 80 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); |
76 | if (status != 0) | 81 | if (status != 0) |
77 | goto out; | 82 | goto out; |
83 | clp->cl_clientid = clid.clientid; | ||
84 | clp->cl_confirm = clid.confirm; | ||
85 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
86 | do_confirm: | ||
78 | status = nfs4_proc_setclientid_confirm(clp, &clid, cred); | 87 | status = nfs4_proc_setclientid_confirm(clp, &clid, cred); |
79 | if (status != 0) | 88 | if (status != 0) |
80 | goto out; | 89 | goto out; |
81 | clp->cl_clientid = clid.clientid; | 90 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
82 | nfs4_schedule_state_renewal(clp); | 91 | nfs4_schedule_state_renewal(clp); |
83 | out: | 92 | out: |
84 | return status; | 93 | return status; |
@@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
230 | { | 239 | { |
231 | int status; | 240 | int status; |
232 | 241 | ||
242 | if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) | ||
243 | goto do_confirm; | ||
233 | nfs4_begin_drain_session(clp); | 244 | nfs4_begin_drain_session(clp); |
234 | status = nfs4_proc_exchange_id(clp, cred); | 245 | status = nfs4_proc_exchange_id(clp, cred); |
235 | if (status != 0) | 246 | if (status != 0) |
236 | goto out; | 247 | goto out; |
248 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
249 | do_confirm: | ||
237 | status = nfs4_proc_create_session(clp); | 250 | status = nfs4_proc_create_session(clp); |
238 | if (status != 0) | 251 | if (status != 0) |
239 | goto out; | 252 | goto out; |
253 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
240 | nfs41_setup_state_renewal(clp); | 254 | nfs41_setup_state_renewal(clp); |
241 | nfs_mark_client_ready(clp, NFS_CS_READY); | 255 | nfs_mark_client_ready(clp, NFS_CS_READY); |
242 | out: | 256 | out: |
@@ -1584,20 +1598,23 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | |||
1584 | */ | 1598 | */ |
1585 | static void nfs4_set_lease_expired(struct nfs_client *clp, int status) | 1599 | static void nfs4_set_lease_expired(struct nfs_client *clp, int status) |
1586 | { | 1600 | { |
1587 | if (nfs4_has_session(clp)) { | 1601 | switch (status) { |
1588 | switch (status) { | 1602 | case -NFS4ERR_CLID_INUSE: |
1589 | case -NFS4ERR_DELAY: | 1603 | case -NFS4ERR_STALE_CLIENTID: |
1590 | case -NFS4ERR_CLID_INUSE: | 1604 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
1591 | case -EAGAIN: | 1605 | break; |
1592 | break; | 1606 | case -NFS4ERR_DELAY: |
1607 | case -ETIMEDOUT: | ||
1608 | case -EAGAIN: | ||
1609 | ssleep(1); | ||
1610 | break; | ||
1593 | 1611 | ||
1594 | case -EKEYEXPIRED: | 1612 | case -EKEYEXPIRED: |
1595 | nfs4_warn_keyexpired(clp->cl_hostname); | 1613 | nfs4_warn_keyexpired(clp->cl_hostname); |
1596 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | 1614 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery |
1597 | * in nfs4_exchange_id */ | 1615 | * in nfs4_exchange_id */ |
1598 | default: | 1616 | default: |
1599 | return; | 1617 | return; |
1600 | } | ||
1601 | } | 1618 | } |
1602 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1619 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
1603 | } | 1620 | } |
@@ -1607,7 +1624,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1607 | int status = 0; | 1624 | int status = 0; |
1608 | 1625 | ||
1609 | /* Ensure exclusive access to NFSv4 state */ | 1626 | /* Ensure exclusive access to NFSv4 state */ |
1610 | for(;;) { | 1627 | do { |
1611 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { | 1628 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { |
1612 | /* We're going to have to re-establish a clientid */ | 1629 | /* We're going to have to re-establish a clientid */ |
1613 | status = nfs4_reclaim_lease(clp); | 1630 | status = nfs4_reclaim_lease(clp); |
@@ -1691,7 +1708,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1691 | break; | 1708 | break; |
1692 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) | 1709 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) |
1693 | break; | 1710 | break; |
1694 | } | 1711 | } while (atomic_read(&clp->cl_count) > 1); |
1695 | return; | 1712 | return; |
1696 | out_error: | 1713 | out_error: |
1697 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" | 1714 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index dddfb5795d7b..c3ccd2c46834 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1452,26 +1452,25 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1452 | 1452 | ||
1453 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1453 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
1454 | { | 1454 | { |
1455 | uint32_t attrs[2] = {0, 0}; | 1455 | uint32_t attrs[2] = { |
1456 | FATTR4_WORD0_RDATTR_ERROR, | ||
1457 | FATTR4_WORD1_MOUNTED_ON_FILEID, | ||
1458 | }; | ||
1456 | uint32_t dircount = readdir->count >> 1; | 1459 | uint32_t dircount = readdir->count >> 1; |
1457 | __be32 *p; | 1460 | __be32 *p; |
1458 | 1461 | ||
1459 | if (readdir->plus) { | 1462 | if (readdir->plus) { |
1460 | attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| | 1463 | attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| |
1461 | FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE; | 1464 | FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; |
1462 | attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| | 1465 | attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| |
1463 | FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| | 1466 | FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| |
1464 | FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| | 1467 | FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| |
1465 | FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 1468 | FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
1466 | dircount >>= 1; | 1469 | dircount >>= 1; |
1467 | } | 1470 | } |
1468 | attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID; | 1471 | /* Use mounted_on_fileid only if the server supports it */ |
1469 | attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; | 1472 | if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) |
1470 | /* Switch to mounted_on_fileid if the server supports it */ | 1473 | attrs[0] |= FATTR4_WORD0_FILEID; |
1471 | if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) | ||
1472 | attrs[0] &= ~FATTR4_WORD0_FILEID; | ||
1473 | else | ||
1474 | attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | ||
1475 | 1474 | ||
1476 | p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); | 1475 | p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); |
1477 | *p++ = cpu_to_be32(OP_READDIR); | 1476 | *p++ = cpu_to_be32(OP_READDIR); |
@@ -3140,7 +3139,7 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma | |||
3140 | goto out_overflow; | 3139 | goto out_overflow; |
3141 | xdr_decode_hyper(p, fileid); | 3140 | xdr_decode_hyper(p, fileid); |
3142 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | 3141 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; |
3143 | ret = NFS_ATTR_FATTR_FILEID; | 3142 | ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; |
3144 | } | 3143 | } |
3145 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 3144 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
3146 | return ret; | 3145 | return ret; |
@@ -4002,7 +4001,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4002 | { | 4001 | { |
4003 | int status; | 4002 | int status; |
4004 | umode_t fmode = 0; | 4003 | umode_t fmode = 0; |
4005 | uint64_t fileid; | ||
4006 | uint32_t type; | 4004 | uint32_t type; |
4007 | 4005 | ||
4008 | status = decode_attr_type(xdr, bitmap, &type); | 4006 | status = decode_attr_type(xdr, bitmap, &type); |
@@ -4101,13 +4099,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4101 | goto xdr_error; | 4099 | goto xdr_error; |
4102 | fattr->valid |= status; | 4100 | fattr->valid |= status; |
4103 | 4101 | ||
4104 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid); | 4102 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); |
4105 | if (status < 0) | 4103 | if (status < 0) |
4106 | goto xdr_error; | 4104 | goto xdr_error; |
4107 | if (status != 0 && !(fattr->valid & status)) { | 4105 | fattr->valid |= status; |
4108 | fattr->fileid = fileid; | ||
4109 | fattr->valid |= status; | ||
4110 | } | ||
4111 | 4106 | ||
4112 | xdr_error: | 4107 | xdr_error: |
4113 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4108 | dprintk("%s: xdr returned %d\n", __func__, -status); |
@@ -4838,17 +4833,21 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |||
4838 | struct nfs4_secinfo_flavor *sec_flavor; | 4833 | struct nfs4_secinfo_flavor *sec_flavor; |
4839 | int status; | 4834 | int status; |
4840 | __be32 *p; | 4835 | __be32 *p; |
4841 | int i; | 4836 | int i, num_flavors; |
4842 | 4837 | ||
4843 | status = decode_op_hdr(xdr, OP_SECINFO); | 4838 | status = decode_op_hdr(xdr, OP_SECINFO); |
4839 | if (status) | ||
4840 | goto out; | ||
4844 | p = xdr_inline_decode(xdr, 4); | 4841 | p = xdr_inline_decode(xdr, 4); |
4845 | if (unlikely(!p)) | 4842 | if (unlikely(!p)) |
4846 | goto out_overflow; | 4843 | goto out_overflow; |
4847 | res->flavors->num_flavors = be32_to_cpup(p); | ||
4848 | 4844 | ||
4849 | for (i = 0; i < res->flavors->num_flavors; i++) { | 4845 | res->flavors->num_flavors = 0; |
4846 | num_flavors = be32_to_cpup(p); | ||
4847 | |||
4848 | for (i = 0; i < num_flavors; i++) { | ||
4850 | sec_flavor = &res->flavors->flavors[i]; | 4849 | sec_flavor = &res->flavors->flavors[i]; |
4851 | if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE) | 4850 | if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) |
4852 | break; | 4851 | break; |
4853 | 4852 | ||
4854 | p = xdr_inline_decode(xdr, 4); | 4853 | p = xdr_inline_decode(xdr, 4); |
@@ -4857,13 +4856,15 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |||
4857 | sec_flavor->flavor = be32_to_cpup(p); | 4856 | sec_flavor->flavor = be32_to_cpup(p); |
4858 | 4857 | ||
4859 | if (sec_flavor->flavor == RPC_AUTH_GSS) { | 4858 | if (sec_flavor->flavor == RPC_AUTH_GSS) { |
4860 | if (decode_secinfo_gss(xdr, sec_flavor)) | 4859 | status = decode_secinfo_gss(xdr, sec_flavor); |
4861 | break; | 4860 | if (status) |
4861 | goto out; | ||
4862 | } | 4862 | } |
4863 | res->flavors->num_flavors++; | ||
4863 | } | 4864 | } |
4864 | 4865 | ||
4865 | return 0; | 4866 | out: |
4866 | 4867 | return status; | |
4867 | out_overflow: | 4868 | out_overflow: |
4868 | print_overflow_msg(__func__, xdr); | 4869 | print_overflow_msg(__func__, xdr); |
4869 | return -EIO; | 4870 | return -EIO; |
@@ -6408,7 +6409,9 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
6408 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 6409 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
6409 | entry->server, 1) < 0) | 6410 | entry->server, 1) < 0) |
6410 | goto out_overflow; | 6411 | goto out_overflow; |
6411 | if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | 6412 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
6413 | entry->ino = entry->fattr->mounted_on_fileid; | ||
6414 | else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | ||
6412 | entry->ino = entry->fattr->fileid; | 6415 | entry->ino = entry->fattr->fileid; |
6413 | 6416 | ||
6414 | entry->d_type = DT_UNKNOWN; | 6417 | entry->d_type = DT_UNKNOWN; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index d9ab97269ce6..f57f5281a520 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 | } |
@@ -1004,6 +1010,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
1004 | { | 1010 | { |
1005 | struct nfs_inode *nfsi = NFS_I(wdata->inode); | 1011 | struct nfs_inode *nfsi = NFS_I(wdata->inode); |
1006 | loff_t end_pos = wdata->args.offset + wdata->res.count; | 1012 | loff_t end_pos = wdata->args.offset + wdata->res.count; |
1013 | bool mark_as_dirty = false; | ||
1007 | 1014 | ||
1008 | spin_lock(&nfsi->vfs_inode.i_lock); | 1015 | spin_lock(&nfsi->vfs_inode.i_lock); |
1009 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1016 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
@@ -1011,13 +1018,18 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
1011 | get_lseg(wdata->lseg); | 1018 | get_lseg(wdata->lseg); |
1012 | wdata->lseg->pls_lc_cred = | 1019 | wdata->lseg->pls_lc_cred = |
1013 | get_rpccred(wdata->args.context->state->owner->so_cred); | 1020 | get_rpccred(wdata->args.context->state->owner->so_cred); |
1014 | mark_inode_dirty_sync(wdata->inode); | 1021 | mark_as_dirty = true; |
1015 | dprintk("%s: Set layoutcommit for inode %lu ", | 1022 | dprintk("%s: Set layoutcommit for inode %lu ", |
1016 | __func__, wdata->inode->i_ino); | 1023 | __func__, wdata->inode->i_ino); |
1017 | } | 1024 | } |
1018 | if (end_pos > wdata->lseg->pls_end_pos) | 1025 | if (end_pos > wdata->lseg->pls_end_pos) |
1019 | wdata->lseg->pls_end_pos = end_pos; | 1026 | wdata->lseg->pls_end_pos = end_pos; |
1020 | spin_unlock(&nfsi->vfs_inode.i_lock); | 1027 | spin_unlock(&nfsi->vfs_inode.i_lock); |
1028 | |||
1029 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one | ||
1030 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ | ||
1031 | if (mark_as_dirty) | ||
1032 | mark_inode_dirty_sync(wdata->inode); | ||
1021 | } | 1033 | } |
1022 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | 1034 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); |
1023 | 1035 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index bc4827202e7a..0c015bad9e7a 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 7cded2b12a05..2bcf0dc306a1 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/super.c b/fs/nfs/super.c index 2b8e9a5e366a..e288f06d3fa7 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1004,6 +1004,7 @@ static int nfs_parse_security_flavors(char *value, | |||
1004 | return 0; | 1004 | return 0; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | mnt->flags |= NFS_MOUNT_SECFLAVOUR; | ||
1007 | mnt->auth_flavor_len = 1; | 1008 | mnt->auth_flavor_len = 1; |
1008 | return 1; | 1009 | return 1; |
1009 | } | 1010 | } |
@@ -1976,6 +1977,15 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) | |||
1976 | if (error < 0) | 1977 | if (error < 0) |
1977 | goto out; | 1978 | goto out; |
1978 | 1979 | ||
1980 | /* | ||
1981 | * noac is a special case. It implies -o sync, but that's not | ||
1982 | * necessarily reflected in the mtab options. do_remount_sb | ||
1983 | * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the | ||
1984 | * remount options, so we have to explicitly reset it. | ||
1985 | */ | ||
1986 | if (data->flags & NFS_MOUNT_NOAC) | ||
1987 | *flags |= MS_SYNCHRONOUS; | ||
1988 | |||
1979 | /* compare new mount options with old ones */ | 1989 | /* compare new mount options with old ones */ |
1980 | error = nfs_compare_remount_data(nfss, data); | 1990 | error = nfs_compare_remount_data(nfss, data); |
1981 | out: | 1991 | out: |
@@ -2235,8 +2245,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2235 | if (!s->s_root) { | 2245 | if (!s->s_root) { |
2236 | /* initial superblock/root creation */ | 2246 | /* initial superblock/root creation */ |
2237 | nfs_fill_super(s, data); | 2247 | nfs_fill_super(s, data); |
2238 | nfs_fscache_get_super_cookie( | 2248 | nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL); |
2239 | s, data ? data->fscache_uniq : NULL, NULL); | ||
2240 | } | 2249 | } |
2241 | 2250 | ||
2242 | mntroot = nfs_get_root(s, mntfh, dev_name); | 2251 | mntroot = nfs_get_root(s, mntfh, dev_name); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e4cbc11a74ab..49c715b4ac92 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -680,7 +680,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
680 | req = nfs_setup_write_request(ctx, page, offset, count); | 680 | req = nfs_setup_write_request(ctx, page, offset, count); |
681 | if (IS_ERR(req)) | 681 | if (IS_ERR(req)) |
682 | return PTR_ERR(req); | 682 | return PTR_ERR(req); |
683 | nfs_mark_request_dirty(req); | ||
684 | /* Update file length */ | 683 | /* Update file length */ |
685 | nfs_grow_file(page, offset, count); | 684 | nfs_grow_file(page, offset, count); |
686 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | 685 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); |
@@ -940,7 +939,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
940 | atomic_set(&req->wb_complete, requests); | 939 | atomic_set(&req->wb_complete, requests); |
941 | 940 | ||
942 | BUG_ON(desc->pg_lseg); | 941 | BUG_ON(desc->pg_lseg); |
943 | 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); |
944 | ClearPageError(page); | 943 | ClearPageError(page); |
945 | offset = 0; | 944 | offset = 0; |
946 | nbytes = desc->pg_count; | 945 | nbytes = desc->pg_count; |
@@ -1014,7 +1013,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | |||
1014 | } | 1013 | } |
1015 | req = nfs_list_entry(data->pages.next); | 1014 | req = nfs_list_entry(data->pages.next); |
1016 | if ((!lseg) && list_is_singular(&data->pages)) | 1015 | if ((!lseg) && list_is_singular(&data->pages)) |
1017 | 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); |
1018 | 1017 | ||
1019 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 1018 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
1020 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | 1019 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) |
@@ -1418,8 +1417,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1418 | task->tk_pid, task->tk_status); | 1417 | task->tk_pid, task->tk_status); |
1419 | 1418 | ||
1420 | /* Call the NFS version-specific code */ | 1419 | /* Call the NFS version-specific code */ |
1421 | if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) | 1420 | NFS_PROTO(data->inode)->commit_done(task, data); |
1422 | return; | ||
1423 | } | 1421 | } |
1424 | 1422 | ||
1425 | void nfs_commit_release_pages(struct nfs_write_data *data) | 1423 | void nfs_commit_release_pages(struct nfs_write_data *data) |