diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 09:44:06 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 09:44:06 -0400 |
| commit | ef78cc75f11ba3b085b105209cbfc6666ee10499 (patch) | |
| tree | 1820dbd8ebb422b0a5751981cdfb6a2ecd30e20b | |
| parent | 1442d1678ca7e53574fd403ba7bee6f4125d920c (diff) | |
| parent | 940aab490215424a269f93d2eba2794fc8b3e269 (diff) | |
Merge branch 'nfs-for-3.2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
* 'nfs-for-3.2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (26 commits)
Check validity of cl_rpcclient in nfs_server_list_show
NFS: Get rid of the nfs_rdata_mempool
NFS: Don't rely on PageError in nfs_readpage_release_partial
NFS: Get rid of unnecessary calls to ClearPageError() in read code
NFS: Get rid of nfs_restart_rpc()
NFS: Get rid of the unused nfs_write_data->flags field
NFS: Get rid of the unused nfs_read_data->flags field
NFSv4: Translate NFS4ERR_BADNAME into ENOENT when applied to a lookup
NFS: Remove the unused "lookupfh()" version of nfs4_proc_lookup()
NFS: Use the inode->i_version to cache NFSv4 change attribute information
SUNRPC: Remove unnecessary export of rpc_sockaddr2uaddr
SUNRPC: Fix rpc_sockaddr2uaddr
nfs/super.c: local functions should be static
pnfsblock: fix writeback deadlock
pnfsblock: fix NULL pointer dereference
pnfs: recoalesce when ld read pagelist fails
pnfs: recoalesce when ld write pagelist fails
pnfs: make _set_lo_fail generic
pnfsblock: add missing rpc_put_mount and path_put
SUNRPC/NFS: make rpc pipe upcall generic
...
| -rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 58 | ||||
| -rw-r--r-- | fs/nfs/blocklayout/blocklayout.h | 4 | ||||
| -rw-r--r-- | fs/nfs/blocklayout/blocklayoutdev.c | 35 | ||||
| -rw-r--r-- | fs/nfs/client.c | 4 | ||||
| -rw-r--r-- | fs/nfs/delegation.c | 2 | ||||
| -rw-r--r-- | fs/nfs/fscache-index.c | 4 | ||||
| -rw-r--r-- | fs/nfs/idmap.c | 25 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 16 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 10 | ||||
| -rw-r--r-- | fs/nfs/nfs4filelayout.c | 33 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 93 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 52 | ||||
| -rw-r--r-- | fs/nfs/pnfs.h | 5 | ||||
| -rw-r--r-- | fs/nfs/read.c | 40 | ||||
| -rw-r--r-- | fs/nfs/super.c | 17 | ||||
| -rw-r--r-- | fs/nfs/unlink.c | 4 | ||||
| -rw-r--r-- | fs/nfs/write.c | 73 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 1 | ||||
| -rw-r--r-- | include/linux/nfs_page.h | 1 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 5 | ||||
| -rw-r--r-- | include/linux/sunrpc/clnt.h | 3 | ||||
| -rw-r--r-- | include/linux/sunrpc/rpc_pipe_fs.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/addr.c | 6 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 24 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 4 | ||||
| -rw-r--r-- | net/sunrpc/rpc_pipe.c | 20 | ||||
| -rw-r--r-- | net/sunrpc/rpcb_clnt.c | 6 |
27 files changed, 238 insertions, 309 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 9561c8fc8bdb..281ae95932c9 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
| @@ -176,17 +176,6 @@ retry: | |||
| 176 | return bio; | 176 | return bio; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static void bl_set_lo_fail(struct pnfs_layout_segment *lseg) | ||
| 180 | { | ||
| 181 | if (lseg->pls_range.iomode == IOMODE_RW) { | ||
| 182 | dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__); | ||
| 183 | set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); | ||
| 184 | } else { | ||
| 185 | dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__); | ||
| 186 | set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | /* This is basically copied from mpage_end_io_read */ | 179 | /* This is basically copied from mpage_end_io_read */ |
| 191 | static void bl_end_io_read(struct bio *bio, int err) | 180 | static void bl_end_io_read(struct bio *bio, int err) |
| 192 | { | 181 | { |
| @@ -206,7 +195,7 @@ static void bl_end_io_read(struct bio *bio, int err) | |||
| 206 | if (!uptodate) { | 195 | if (!uptodate) { |
| 207 | if (!rdata->pnfs_error) | 196 | if (!rdata->pnfs_error) |
| 208 | rdata->pnfs_error = -EIO; | 197 | rdata->pnfs_error = -EIO; |
| 209 | bl_set_lo_fail(rdata->lseg); | 198 | pnfs_set_lo_fail(rdata->lseg); |
| 210 | } | 199 | } |
| 211 | bio_put(bio); | 200 | bio_put(bio); |
| 212 | put_parallel(par); | 201 | put_parallel(par); |
| @@ -303,6 +292,7 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
| 303 | bl_end_io_read, par); | 292 | bl_end_io_read, par); |
| 304 | if (IS_ERR(bio)) { | 293 | if (IS_ERR(bio)) { |
| 305 | rdata->pnfs_error = PTR_ERR(bio); | 294 | rdata->pnfs_error = PTR_ERR(bio); |
| 295 | bio = NULL; | ||
| 306 | goto out; | 296 | goto out; |
| 307 | } | 297 | } |
| 308 | } | 298 | } |
| @@ -370,7 +360,7 @@ static void bl_end_io_write_zero(struct bio *bio, int err) | |||
| 370 | if (!uptodate) { | 360 | if (!uptodate) { |
| 371 | if (!wdata->pnfs_error) | 361 | if (!wdata->pnfs_error) |
| 372 | wdata->pnfs_error = -EIO; | 362 | wdata->pnfs_error = -EIO; |
| 373 | bl_set_lo_fail(wdata->lseg); | 363 | pnfs_set_lo_fail(wdata->lseg); |
| 374 | } | 364 | } |
| 375 | bio_put(bio); | 365 | bio_put(bio); |
| 376 | put_parallel(par); | 366 | put_parallel(par); |
| @@ -386,7 +376,7 @@ static void bl_end_io_write(struct bio *bio, int err) | |||
| 386 | if (!uptodate) { | 376 | if (!uptodate) { |
| 387 | if (!wdata->pnfs_error) | 377 | if (!wdata->pnfs_error) |
| 388 | wdata->pnfs_error = -EIO; | 378 | wdata->pnfs_error = -EIO; |
| 389 | bl_set_lo_fail(wdata->lseg); | 379 | pnfs_set_lo_fail(wdata->lseg); |
| 390 | } | 380 | } |
| 391 | bio_put(bio); | 381 | bio_put(bio); |
| 392 | put_parallel(par); | 382 | put_parallel(par); |
| @@ -543,6 +533,11 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) | |||
| 543 | fill_invalid_ext: | 533 | fill_invalid_ext: |
| 544 | dprintk("%s need to zero %d pages\n", __func__, npg_zero); | 534 | dprintk("%s need to zero %d pages\n", __func__, npg_zero); |
| 545 | for (;npg_zero > 0; npg_zero--) { | 535 | for (;npg_zero > 0; npg_zero--) { |
| 536 | if (bl_is_sector_init(be->be_inval, isect)) { | ||
| 537 | dprintk("isect %llu already init\n", | ||
| 538 | (unsigned long long)isect); | ||
| 539 | goto next_page; | ||
| 540 | } | ||
| 546 | /* page ref released in bl_end_io_write_zero */ | 541 | /* page ref released in bl_end_io_write_zero */ |
| 547 | index = isect >> PAGE_CACHE_SECTOR_SHIFT; | 542 | index = isect >> PAGE_CACHE_SECTOR_SHIFT; |
| 548 | dprintk("%s zero %dth page: index %lu isect %llu\n", | 543 | dprintk("%s zero %dth page: index %lu isect %llu\n", |
| @@ -562,8 +557,7 @@ fill_invalid_ext: | |||
| 562 | * PageUptodate: It was read before | 557 | * PageUptodate: It was read before |
| 563 | * sector_initialized: already written out | 558 | * sector_initialized: already written out |
| 564 | */ | 559 | */ |
| 565 | if (PageDirty(page) || PageWriteback(page) || | 560 | if (PageDirty(page) || PageWriteback(page)) { |
| 566 | bl_is_sector_init(be->be_inval, isect)) { | ||
| 567 | print_page(page); | 561 | print_page(page); |
| 568 | unlock_page(page); | 562 | unlock_page(page); |
| 569 | page_cache_release(page); | 563 | page_cache_release(page); |
| @@ -592,6 +586,7 @@ fill_invalid_ext: | |||
| 592 | bl_end_io_write_zero, par); | 586 | bl_end_io_write_zero, par); |
| 593 | if (IS_ERR(bio)) { | 587 | if (IS_ERR(bio)) { |
| 594 | wdata->pnfs_error = PTR_ERR(bio); | 588 | wdata->pnfs_error = PTR_ERR(bio); |
| 589 | bio = NULL; | ||
| 595 | goto out; | 590 | goto out; |
| 596 | } | 591 | } |
| 597 | /* FIXME: This should be done in bi_end_io */ | 592 | /* FIXME: This should be done in bi_end_io */ |
| @@ -640,6 +635,7 @@ next_page: | |||
| 640 | bl_end_io_write, par); | 635 | bl_end_io_write, par); |
| 641 | if (IS_ERR(bio)) { | 636 | if (IS_ERR(bio)) { |
| 642 | wdata->pnfs_error = PTR_ERR(bio); | 637 | wdata->pnfs_error = PTR_ERR(bio); |
| 638 | bio = NULL; | ||
| 643 | goto out; | 639 | goto out; |
| 644 | } | 640 | } |
| 645 | isect += PAGE_CACHE_SECTORS; | 641 | isect += PAGE_CACHE_SECTORS; |
| @@ -805,7 +801,7 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | |||
| 805 | struct nfs4_deviceid *d_id) | 801 | struct nfs4_deviceid *d_id) |
| 806 | { | 802 | { |
| 807 | struct pnfs_device *dev; | 803 | struct pnfs_device *dev; |
| 808 | struct pnfs_block_dev *rv = NULL; | 804 | struct pnfs_block_dev *rv; |
| 809 | u32 max_resp_sz; | 805 | u32 max_resp_sz; |
| 810 | int max_pages; | 806 | int max_pages; |
| 811 | struct page **pages = NULL; | 807 | struct page **pages = NULL; |
| @@ -823,18 +819,20 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | |||
| 823 | dev = kmalloc(sizeof(*dev), GFP_NOFS); | 819 | dev = kmalloc(sizeof(*dev), GFP_NOFS); |
| 824 | if (!dev) { | 820 | if (!dev) { |
| 825 | dprintk("%s kmalloc failed\n", __func__); | 821 | dprintk("%s kmalloc failed\n", __func__); |
| 826 | return NULL; | 822 | return ERR_PTR(-ENOMEM); |
| 827 | } | 823 | } |
| 828 | 824 | ||
| 829 | pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS); | 825 | pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS); |
| 830 | if (pages == NULL) { | 826 | if (pages == NULL) { |
| 831 | kfree(dev); | 827 | kfree(dev); |
| 832 | return NULL; | 828 | return ERR_PTR(-ENOMEM); |
| 833 | } | 829 | } |
| 834 | for (i = 0; i < max_pages; i++) { | 830 | for (i = 0; i < max_pages; i++) { |
| 835 | pages[i] = alloc_page(GFP_NOFS); | 831 | pages[i] = alloc_page(GFP_NOFS); |
| 836 | if (!pages[i]) | 832 | if (!pages[i]) { |
| 833 | rv = ERR_PTR(-ENOMEM); | ||
| 837 | goto out_free; | 834 | goto out_free; |
| 835 | } | ||
| 838 | } | 836 | } |
| 839 | 837 | ||
| 840 | memcpy(&dev->dev_id, d_id, sizeof(*d_id)); | 838 | memcpy(&dev->dev_id, d_id, sizeof(*d_id)); |
| @@ -847,8 +845,10 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | |||
| 847 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); | 845 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); |
| 848 | rc = nfs4_proc_getdeviceinfo(server, dev); | 846 | rc = nfs4_proc_getdeviceinfo(server, dev); |
| 849 | dprintk("%s getdevice info returns %d\n", __func__, rc); | 847 | dprintk("%s getdevice info returns %d\n", __func__, rc); |
| 850 | if (rc) | 848 | if (rc) { |
| 849 | rv = ERR_PTR(rc); | ||
| 851 | goto out_free; | 850 | goto out_free; |
| 851 | } | ||
| 852 | 852 | ||
| 853 | rv = nfs4_blk_decode_device(server, dev); | 853 | rv = nfs4_blk_decode_device(server, dev); |
| 854 | out_free: | 854 | out_free: |
| @@ -866,7 +866,7 @@ bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh) | |||
| 866 | struct pnfs_devicelist *dlist = NULL; | 866 | struct pnfs_devicelist *dlist = NULL; |
| 867 | struct pnfs_block_dev *bdev; | 867 | struct pnfs_block_dev *bdev; |
| 868 | LIST_HEAD(block_disklist); | 868 | LIST_HEAD(block_disklist); |
| 869 | int status = 0, i; | 869 | int status, i; |
| 870 | 870 | ||
| 871 | dprintk("%s enter\n", __func__); | 871 | dprintk("%s enter\n", __func__); |
| 872 | 872 | ||
| @@ -898,8 +898,8 @@ bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh) | |||
| 898 | for (i = 0; i < dlist->num_devs; i++) { | 898 | for (i = 0; i < dlist->num_devs; i++) { |
| 899 | bdev = nfs4_blk_get_deviceinfo(server, fh, | 899 | bdev = nfs4_blk_get_deviceinfo(server, fh, |
| 900 | &dlist->dev_id[i]); | 900 | &dlist->dev_id[i]); |
| 901 | if (!bdev) { | 901 | if (IS_ERR(bdev)) { |
| 902 | status = -ENODEV; | 902 | status = PTR_ERR(bdev); |
| 903 | goto out_error; | 903 | goto out_error; |
| 904 | } | 904 | } |
| 905 | spin_lock(&b_mt_id->bm_lock); | 905 | spin_lock(&b_mt_id->bm_lock); |
| @@ -960,7 +960,7 @@ static struct pnfs_layoutdriver_type blocklayout_type = { | |||
| 960 | }; | 960 | }; |
| 961 | 961 | ||
| 962 | static const struct rpc_pipe_ops bl_upcall_ops = { | 962 | static const struct rpc_pipe_ops bl_upcall_ops = { |
| 963 | .upcall = bl_pipe_upcall, | 963 | .upcall = rpc_pipe_generic_upcall, |
| 964 | .downcall = bl_pipe_downcall, | 964 | .downcall = bl_pipe_downcall, |
| 965 | .destroy_msg = bl_pipe_destroy_msg, | 965 | .destroy_msg = bl_pipe_destroy_msg, |
| 966 | }; | 966 | }; |
| @@ -989,17 +989,20 @@ static int __init nfs4blocklayout_init(void) | |||
| 989 | mnt, | 989 | mnt, |
| 990 | NFS_PIPE_DIRNAME, 0, &path); | 990 | NFS_PIPE_DIRNAME, 0, &path); |
| 991 | if (ret) | 991 | if (ret) |
| 992 | goto out_remove; | 992 | goto out_putrpc; |
| 993 | 993 | ||
| 994 | bl_device_pipe = rpc_mkpipe(path.dentry, "blocklayout", NULL, | 994 | bl_device_pipe = rpc_mkpipe(path.dentry, "blocklayout", NULL, |
| 995 | &bl_upcall_ops, 0); | 995 | &bl_upcall_ops, 0); |
| 996 | path_put(&path); | ||
| 996 | if (IS_ERR(bl_device_pipe)) { | 997 | if (IS_ERR(bl_device_pipe)) { |
| 997 | ret = PTR_ERR(bl_device_pipe); | 998 | ret = PTR_ERR(bl_device_pipe); |
| 998 | goto out_remove; | 999 | goto out_putrpc; |
| 999 | } | 1000 | } |
| 1000 | out: | 1001 | out: |
| 1001 | return ret; | 1002 | return ret; |
| 1002 | 1003 | ||
| 1004 | out_putrpc: | ||
| 1005 | rpc_put_mount(); | ||
| 1003 | out_remove: | 1006 | out_remove: |
| 1004 | pnfs_unregister_layoutdriver(&blocklayout_type); | 1007 | pnfs_unregister_layoutdriver(&blocklayout_type); |
| 1005 | return ret; | 1008 | return ret; |
| @@ -1012,6 +1015,7 @@ static void __exit nfs4blocklayout_exit(void) | |||
| 1012 | 1015 | ||
| 1013 | pnfs_unregister_layoutdriver(&blocklayout_type); | 1016 | pnfs_unregister_layoutdriver(&blocklayout_type); |
| 1014 | rpc_unlink(bl_device_pipe); | 1017 | rpc_unlink(bl_device_pipe); |
| 1018 | rpc_put_mount(); | ||
| 1015 | } | 1019 | } |
| 1016 | 1020 | ||
| 1017 | MODULE_ALIAS("nfs-layouttype4-3"); | 1021 | MODULE_ALIAS("nfs-layouttype4-3"); |
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index f27d827960a3..42acf7ef5992 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h | |||
| @@ -150,7 +150,7 @@ BLK_LSEG2EXT(struct pnfs_layout_segment *lseg) | |||
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | struct bl_dev_msg { | 152 | struct bl_dev_msg { |
| 153 | int status; | 153 | int32_t status; |
| 154 | uint32_t major, minor; | 154 | uint32_t major, minor; |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| @@ -169,8 +169,6 @@ extern wait_queue_head_t bl_wq; | |||
| 169 | #define BL_DEVICE_REQUEST_ERR 0x2 /* User level process fails */ | 169 | #define BL_DEVICE_REQUEST_ERR 0x2 /* User level process fails */ |
| 170 | 170 | ||
| 171 | /* blocklayoutdev.c */ | 171 | /* blocklayoutdev.c */ |
| 172 | ssize_t bl_pipe_upcall(struct file *, struct rpc_pipe_msg *, | ||
| 173 | char __user *, size_t); | ||
| 174 | ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); | 172 | ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); |
| 175 | void bl_pipe_destroy_msg(struct rpc_pipe_msg *); | 173 | void bl_pipe_destroy_msg(struct rpc_pipe_msg *); |
| 176 | struct block_device *nfs4_blkdev_get(dev_t dev); | 174 | struct block_device *nfs4_blkdev_get(dev_t dev); |
diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c index a83b393fb01c..d08ba9107fde 100644 --- a/fs/nfs/blocklayout/blocklayoutdev.c +++ b/fs/nfs/blocklayout/blocklayoutdev.c | |||
| @@ -79,28 +79,6 @@ int nfs4_blkdev_put(struct block_device *bdev) | |||
| 79 | return blkdev_put(bdev, FMODE_READ); | 79 | return blkdev_put(bdev, FMODE_READ); |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | /* | ||
| 83 | * Shouldn't there be a rpc_generic_upcall() to do this for us? | ||
| 84 | */ | ||
| 85 | ssize_t bl_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, | ||
| 86 | char __user *dst, size_t buflen) | ||
| 87 | { | ||
| 88 | char *data = (char *)msg->data + msg->copied; | ||
| 89 | size_t mlen = min(msg->len - msg->copied, buflen); | ||
| 90 | unsigned long left; | ||
| 91 | |||
| 92 | left = copy_to_user(dst, data, mlen); | ||
| 93 | if (left == mlen) { | ||
| 94 | msg->errno = -EFAULT; | ||
| 95 | return -EFAULT; | ||
| 96 | } | ||
| 97 | |||
| 98 | mlen -= left; | ||
| 99 | msg->copied += mlen; | ||
| 100 | msg->errno = 0; | ||
| 101 | return mlen; | ||
| 102 | } | ||
| 103 | |||
| 104 | static struct bl_dev_msg bl_mount_reply; | 82 | static struct bl_dev_msg bl_mount_reply; |
| 105 | 83 | ||
| 106 | ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, | 84 | ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, |
| @@ -131,7 +109,7 @@ struct pnfs_block_dev * | |||
| 131 | nfs4_blk_decode_device(struct nfs_server *server, | 109 | nfs4_blk_decode_device(struct nfs_server *server, |
| 132 | struct pnfs_device *dev) | 110 | struct pnfs_device *dev) |
| 133 | { | 111 | { |
| 134 | struct pnfs_block_dev *rv = NULL; | 112 | struct pnfs_block_dev *rv; |
| 135 | struct block_device *bd = NULL; | 113 | struct block_device *bd = NULL; |
| 136 | struct rpc_pipe_msg msg; | 114 | struct rpc_pipe_msg msg; |
| 137 | struct bl_msg_hdr bl_msg = { | 115 | struct bl_msg_hdr bl_msg = { |
| @@ -141,7 +119,7 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
| 141 | uint8_t *dataptr; | 119 | uint8_t *dataptr; |
| 142 | DECLARE_WAITQUEUE(wq, current); | 120 | DECLARE_WAITQUEUE(wq, current); |
| 143 | struct bl_dev_msg *reply = &bl_mount_reply; | 121 | struct bl_dev_msg *reply = &bl_mount_reply; |
| 144 | int offset, len, i; | 122 | int offset, len, i, rc; |
| 145 | 123 | ||
| 146 | dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); | 124 | dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); |
| 147 | dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data, | 125 | dprintk("%s: deviceid: %s, mincount: %d\n", __func__, dev->dev_id.data, |
| @@ -168,8 +146,10 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
| 168 | 146 | ||
| 169 | dprintk("%s CALLING USERSPACE DAEMON\n", __func__); | 147 | dprintk("%s CALLING USERSPACE DAEMON\n", __func__); |
| 170 | add_wait_queue(&bl_wq, &wq); | 148 | add_wait_queue(&bl_wq, &wq); |
| 171 | if (rpc_queue_upcall(bl_device_pipe->d_inode, &msg) < 0) { | 149 | rc = rpc_queue_upcall(bl_device_pipe->d_inode, &msg); |
| 150 | if (rc < 0) { | ||
| 172 | remove_wait_queue(&bl_wq, &wq); | 151 | remove_wait_queue(&bl_wq, &wq); |
| 152 | rv = ERR_PTR(rc); | ||
| 173 | goto out; | 153 | goto out; |
| 174 | } | 154 | } |
| 175 | 155 | ||
| @@ -187,8 +167,9 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
| 187 | 167 | ||
| 188 | bd = nfs4_blkdev_get(MKDEV(reply->major, reply->minor)); | 168 | bd = nfs4_blkdev_get(MKDEV(reply->major, reply->minor)); |
| 189 | if (IS_ERR(bd)) { | 169 | if (IS_ERR(bd)) { |
| 190 | dprintk("%s failed to open device : %ld\n", | 170 | rc = PTR_ERR(bd); |
| 191 | __func__, PTR_ERR(bd)); | 171 | dprintk("%s failed to open device : %d\n", __func__, rc); |
| 172 | rv = ERR_PTR(rc); | ||
| 192 | goto out; | 173 | goto out; |
| 193 | } | 174 | } |
| 194 | 175 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index b4e41dd4d0f6..873bf00d51a2 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -1868,6 +1868,10 @@ static int nfs_server_list_show(struct seq_file *m, void *v) | |||
| 1868 | /* display one transport per line on subsequent lines */ | 1868 | /* display one transport per line on subsequent lines */ |
| 1869 | clp = list_entry(v, struct nfs_client, cl_share_link); | 1869 | clp = list_entry(v, struct nfs_client, cl_share_link); |
| 1870 | 1870 | ||
| 1871 | /* Check if the client is initialized */ | ||
| 1872 | if (clp->cl_cons_state != NFS_CS_READY) | ||
| 1873 | return 0; | ||
| 1874 | |||
| 1871 | seq_printf(m, "v%u %s %s %3d %s\n", | 1875 | seq_printf(m, "v%u %s %s %3d %s\n", |
| 1872 | clp->rpc_ops->version, | 1876 | clp->rpc_ops->version, |
| 1873 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), | 1877 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 321a66bc3846..7f2654069806 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -240,7 +240,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
| 240 | sizeof(delegation->stateid.data)); | 240 | sizeof(delegation->stateid.data)); |
| 241 | delegation->type = res->delegation_type; | 241 | delegation->type = res->delegation_type; |
| 242 | delegation->maxsize = res->maxsize; | 242 | delegation->maxsize = res->maxsize; |
| 243 | delegation->change_attr = nfsi->change_attr; | 243 | delegation->change_attr = inode->i_version; |
| 244 | delegation->cred = get_rpccred(cred); | 244 | delegation->cred = get_rpccred(cred); |
| 245 | delegation->inode = inode; | 245 | delegation->inode = inode; |
| 246 | delegation->flags = 1<<NFS_DELEGATION_REFERENCED; | 246 | delegation->flags = 1<<NFS_DELEGATION_REFERENCED; |
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c index 5b1006480bc2..7cf2c4699b08 100644 --- a/fs/nfs/fscache-index.c +++ b/fs/nfs/fscache-index.c | |||
| @@ -212,7 +212,7 @@ static uint16_t nfs_fscache_inode_get_aux(const void *cookie_netfs_data, | |||
| 212 | auxdata.ctime = nfsi->vfs_inode.i_ctime; | 212 | auxdata.ctime = nfsi->vfs_inode.i_ctime; |
| 213 | 213 | ||
| 214 | if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) | 214 | if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) |
| 215 | auxdata.change_attr = nfsi->change_attr; | 215 | auxdata.change_attr = nfsi->vfs_inode.i_version; |
| 216 | 216 | ||
| 217 | if (bufmax > sizeof(auxdata)) | 217 | if (bufmax > sizeof(auxdata)) |
| 218 | bufmax = sizeof(auxdata); | 218 | bufmax = sizeof(auxdata); |
| @@ -244,7 +244,7 @@ enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data, | |||
| 244 | auxdata.ctime = nfsi->vfs_inode.i_ctime; | 244 | auxdata.ctime = nfsi->vfs_inode.i_ctime; |
| 245 | 245 | ||
| 246 | if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) | 246 | if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) |
| 247 | auxdata.change_attr = nfsi->change_attr; | 247 | auxdata.change_attr = nfsi->vfs_inode.i_version; |
| 248 | 248 | ||
| 249 | if (memcmp(data, &auxdata, datalen) != 0) | 249 | if (memcmp(data, &auxdata, datalen) != 0) |
| 250 | return FSCACHE_CHECKAUX_OBSOLETE; | 250 | return FSCACHE_CHECKAUX_OBSOLETE; |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index f20801ae0a16..47d1c6ff2d8e 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
| @@ -336,8 +336,6 @@ struct idmap { | |||
| 336 | struct idmap_hashtable idmap_group_hash; | 336 | struct idmap_hashtable idmap_group_hash; |
| 337 | }; | 337 | }; |
| 338 | 338 | ||
| 339 | static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, | ||
| 340 | char __user *, size_t); | ||
| 341 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, | 339 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, |
| 342 | size_t); | 340 | size_t); |
| 343 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); | 341 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); |
| @@ -345,7 +343,7 @@ static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); | |||
| 345 | static unsigned int fnvhash32(const void *, size_t); | 343 | static unsigned int fnvhash32(const void *, size_t); |
| 346 | 344 | ||
| 347 | static const struct rpc_pipe_ops idmap_upcall_ops = { | 345 | static const struct rpc_pipe_ops idmap_upcall_ops = { |
| 348 | .upcall = idmap_pipe_upcall, | 346 | .upcall = rpc_pipe_generic_upcall, |
| 349 | .downcall = idmap_pipe_downcall, | 347 | .downcall = idmap_pipe_downcall, |
| 350 | .destroy_msg = idmap_pipe_destroy_msg, | 348 | .destroy_msg = idmap_pipe_destroy_msg, |
| 351 | }; | 349 | }; |
| @@ -595,27 +593,6 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h, | |||
| 595 | return ret; | 593 | return ret; |
| 596 | } | 594 | } |
| 597 | 595 | ||
| 598 | /* RPC pipefs upcall/downcall routines */ | ||
| 599 | static ssize_t | ||
| 600 | idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, | ||
| 601 | char __user *dst, size_t buflen) | ||
| 602 | { | ||
| 603 | char *data = (char *)msg->data + msg->copied; | ||
| 604 | size_t mlen = min(msg->len, buflen); | ||
| 605 | unsigned long left; | ||
| 606 | |||
| 607 | left = copy_to_user(dst, data, mlen); | ||
| 608 | if (left == mlen) { | ||
| 609 | msg->errno = -EFAULT; | ||
| 610 | return -EFAULT; | ||
| 611 | } | ||
| 612 | |||
| 613 | mlen -= left; | ||
| 614 | msg->copied += mlen; | ||
| 615 | msg->errno = 0; | ||
| 616 | return mlen; | ||
| 617 | } | ||
| 618 | |||
| 619 | static ssize_t | 596 | static ssize_t |
| 620 | idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | 597 | idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) |
| 621 | { | 598 | { |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index fe1203797b2b..4dc6d078f108 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -318,7 +318,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 318 | memset(&inode->i_atime, 0, sizeof(inode->i_atime)); | 318 | memset(&inode->i_atime, 0, sizeof(inode->i_atime)); |
| 319 | memset(&inode->i_mtime, 0, sizeof(inode->i_mtime)); | 319 | memset(&inode->i_mtime, 0, sizeof(inode->i_mtime)); |
| 320 | memset(&inode->i_ctime, 0, sizeof(inode->i_ctime)); | 320 | memset(&inode->i_ctime, 0, sizeof(inode->i_ctime)); |
| 321 | nfsi->change_attr = 0; | 321 | inode->i_version = 0; |
| 322 | inode->i_size = 0; | 322 | inode->i_size = 0; |
| 323 | inode->i_nlink = 0; | 323 | inode->i_nlink = 0; |
| 324 | inode->i_uid = -2; | 324 | inode->i_uid = -2; |
| @@ -344,7 +344,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 344 | | NFS_INO_INVALID_ACCESS | 344 | | NFS_INO_INVALID_ACCESS |
| 345 | | NFS_INO_INVALID_ACL; | 345 | | NFS_INO_INVALID_ACL; |
| 346 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | 346 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
| 347 | nfsi->change_attr = fattr->change_attr; | 347 | inode->i_version = fattr->change_attr; |
| 348 | else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR)) | 348 | else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR)) |
| 349 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 349 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
| 350 | | NFS_INO_INVALID_DATA; | 350 | | NFS_INO_INVALID_DATA; |
| @@ -897,8 +897,8 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr | |||
| 897 | 897 | ||
| 898 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) | 898 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) |
| 899 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) | 899 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
| 900 | && nfsi->change_attr == fattr->pre_change_attr) { | 900 | && inode->i_version == fattr->pre_change_attr) { |
| 901 | nfsi->change_attr = fattr->change_attr; | 901 | inode->i_version = fattr->change_attr; |
| 902 | if (S_ISDIR(inode->i_mode)) | 902 | if (S_ISDIR(inode->i_mode)) |
| 903 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 903 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
| 904 | ret |= NFS_INO_INVALID_ATTR; | 904 | ret |= NFS_INO_INVALID_ATTR; |
| @@ -952,7 +952,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
| 952 | return -EIO; | 952 | return -EIO; |
| 953 | 953 | ||
| 954 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && | 954 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
| 955 | nfsi->change_attr != fattr->change_attr) | 955 | inode->i_version != fattr->change_attr) |
| 956 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 956 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
| 957 | 957 | ||
| 958 | /* Verify a few of the more important attributes */ | 958 | /* Verify a few of the more important attributes */ |
| @@ -1163,7 +1163,7 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
| 1163 | } | 1163 | } |
| 1164 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && | 1164 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
| 1165 | (fattr->valid & NFS_ATTR_FATTR_PRECHANGE) == 0) { | 1165 | (fattr->valid & NFS_ATTR_FATTR_PRECHANGE) == 0) { |
| 1166 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1166 | fattr->pre_change_attr = inode->i_version; |
| 1167 | fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; | 1167 | fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; |
| 1168 | } | 1168 | } |
| 1169 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 && | 1169 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 && |
| @@ -1244,13 +1244,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1244 | 1244 | ||
| 1245 | /* More cache consistency checks */ | 1245 | /* More cache consistency checks */ |
| 1246 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { | 1246 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { |
| 1247 | if (nfsi->change_attr != fattr->change_attr) { | 1247 | if (inode->i_version != fattr->change_attr) { |
| 1248 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1248 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
| 1249 | inode->i_sb->s_id, inode->i_ino); | 1249 | inode->i_sb->s_id, inode->i_ino); |
| 1250 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1250 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 1251 | if (S_ISDIR(inode->i_mode)) | 1251 | if (S_ISDIR(inode->i_mode)) |
| 1252 | nfs_force_lookup_revalidate(inode); | 1252 | nfs_force_lookup_revalidate(inode); |
| 1253 | nfsi->change_attr = fattr->change_attr; | 1253 | inode->i_version = fattr->change_attr; |
| 1254 | } | 1254 | } |
| 1255 | } else if (server->caps & NFS_CAP_CHANGE_ATTR) | 1255 | } else if (server->caps & NFS_CAP_CHANGE_ATTR) |
| 1256 | invalid |= save_cache_validity; | 1256 | invalid |= save_cache_validity; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index ab12913dd473..c1a1bd8ddf1c 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -457,13 +457,3 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len) | |||
| 457 | PAGE_SIZE - 1) >> PAGE_SHIFT; | 457 | PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | /* | ||
| 461 | * Helper for restarting RPC calls in the possible presence of NFSv4.1 | ||
| 462 | * sessions. | ||
| 463 | */ | ||
| 464 | static inline int nfs_restart_rpc(struct rpc_task *task, const struct nfs_client *clp) | ||
| 465 | { | ||
| 466 | if (nfs4_has_session(clp)) | ||
| 467 | return rpc_restart_call_prepare(task); | ||
| 468 | return rpc_restart_call(task); | ||
| 469 | } | ||
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index e8915d4840ad..09119418402f 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -77,19 +77,6 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset) | |||
| 77 | BUG(); | 77 | BUG(); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | /* For data server errors we don't recover from */ | ||
| 81 | static void | ||
| 82 | filelayout_set_lo_fail(struct pnfs_layout_segment *lseg) | ||
| 83 | { | ||
| 84 | if (lseg->pls_range.iomode == IOMODE_RW) { | ||
| 85 | dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__); | ||
| 86 | set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); | ||
| 87 | } else { | ||
| 88 | dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__); | ||
| 89 | set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | static int filelayout_async_handle_error(struct rpc_task *task, | 80 | static int filelayout_async_handle_error(struct rpc_task *task, |
| 94 | struct nfs4_state *state, | 81 | struct nfs4_state *state, |
| 95 | struct nfs_client *clp, | 82 | struct nfs_client *clp, |
| @@ -135,7 +122,6 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
| 135 | static int filelayout_read_done_cb(struct rpc_task *task, | 122 | static int filelayout_read_done_cb(struct rpc_task *task, |
| 136 | struct nfs_read_data *data) | 123 | struct nfs_read_data *data) |
| 137 | { | 124 | { |
| 138 | struct nfs_client *clp = data->ds_clp; | ||
| 139 | int reset = 0; | 125 | int reset = 0; |
| 140 | 126 | ||
| 141 | dprintk("%s DS read\n", __func__); | 127 | dprintk("%s DS read\n", __func__); |
| @@ -145,11 +131,10 @@ static int filelayout_read_done_cb(struct rpc_task *task, | |||
| 145 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", | 131 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", |
| 146 | __func__, data->ds_clp, data->ds_clp->cl_session); | 132 | __func__, data->ds_clp, data->ds_clp->cl_session); |
| 147 | if (reset) { | 133 | if (reset) { |
| 148 | filelayout_set_lo_fail(data->lseg); | 134 | pnfs_set_lo_fail(data->lseg); |
| 149 | nfs4_reset_read(task, data); | 135 | nfs4_reset_read(task, data); |
| 150 | clp = NFS_SERVER(data->inode)->nfs_client; | ||
| 151 | } | 136 | } |
| 152 | nfs_restart_rpc(task, clp); | 137 | rpc_restart_call_prepare(task); |
| 153 | return -EAGAIN; | 138 | return -EAGAIN; |
| 154 | } | 139 | } |
| 155 | 140 | ||
| @@ -216,17 +201,13 @@ static int filelayout_write_done_cb(struct rpc_task *task, | |||
| 216 | 201 | ||
| 217 | if (filelayout_async_handle_error(task, data->args.context->state, | 202 | if (filelayout_async_handle_error(task, data->args.context->state, |
| 218 | data->ds_clp, &reset) == -EAGAIN) { | 203 | data->ds_clp, &reset) == -EAGAIN) { |
| 219 | struct nfs_client *clp; | ||
| 220 | |||
| 221 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", | 204 | dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", |
| 222 | __func__, data->ds_clp, data->ds_clp->cl_session); | 205 | __func__, data->ds_clp, data->ds_clp->cl_session); |
| 223 | if (reset) { | 206 | if (reset) { |
| 224 | filelayout_set_lo_fail(data->lseg); | 207 | pnfs_set_lo_fail(data->lseg); |
| 225 | nfs4_reset_write(task, data); | 208 | nfs4_reset_write(task, data); |
| 226 | clp = NFS_SERVER(data->inode)->nfs_client; | 209 | } |
| 227 | } else | 210 | rpc_restart_call_prepare(task); |
| 228 | clp = data->ds_clp; | ||
| 229 | nfs_restart_rpc(task, clp); | ||
| 230 | return -EAGAIN; | 211 | return -EAGAIN; |
| 231 | } | 212 | } |
| 232 | 213 | ||
| @@ -256,9 +237,9 @@ static int filelayout_commit_done_cb(struct rpc_task *task, | |||
| 256 | __func__, data->ds_clp, data->ds_clp->cl_session); | 237 | __func__, data->ds_clp, data->ds_clp->cl_session); |
| 257 | if (reset) { | 238 | if (reset) { |
| 258 | prepare_to_resend_writes(data); | 239 | prepare_to_resend_writes(data); |
| 259 | filelayout_set_lo_fail(data->lseg); | 240 | pnfs_set_lo_fail(data->lseg); |
| 260 | } else | 241 | } else |
| 261 | nfs_restart_rpc(task, data->ds_clp); | 242 | rpc_restart_call_prepare(task); |
| 262 | return -EAGAIN; | 243 | return -EAGAIN; |
| 263 | } | 244 | } |
| 264 | 245 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4700fae1ada0..d2ae413c986a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -73,9 +73,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data); | |||
| 73 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 73 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
| 74 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 74 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
| 75 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 75 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
| 76 | static int _nfs4_proc_lookup(struct rpc_clnt *client, struct inode *dir, | ||
| 77 | const struct qstr *name, struct nfs_fh *fhandle, | ||
| 78 | struct nfs_fattr *fattr); | ||
| 79 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 76 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
| 80 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 77 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
| 81 | struct nfs_fattr *fattr, struct iattr *sattr, | 78 | struct nfs_fattr *fattr, struct iattr *sattr, |
| @@ -753,9 +750,9 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
| 753 | 750 | ||
| 754 | spin_lock(&dir->i_lock); | 751 | spin_lock(&dir->i_lock); |
| 755 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; | 752 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; |
| 756 | if (!cinfo->atomic || cinfo->before != nfsi->change_attr) | 753 | if (!cinfo->atomic || cinfo->before != dir->i_version) |
| 757 | nfs_force_lookup_revalidate(dir); | 754 | nfs_force_lookup_revalidate(dir); |
| 758 | nfsi->change_attr = cinfo->after; | 755 | dir->i_version = cinfo->after; |
| 759 | spin_unlock(&dir->i_lock); | 756 | spin_unlock(&dir->i_lock); |
| 760 | } | 757 | } |
| 761 | 758 | ||
| @@ -1596,8 +1593,14 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 1596 | int status; | 1593 | int status; |
| 1597 | 1594 | ||
| 1598 | status = nfs4_run_open_task(data, 0); | 1595 | status = nfs4_run_open_task(data, 0); |
| 1599 | if (status != 0 || !data->rpc_done) | 1596 | if (!data->rpc_done) |
| 1597 | return status; | ||
| 1598 | if (status != 0) { | ||
| 1599 | if (status == -NFS4ERR_BADNAME && | ||
| 1600 | !(o_arg->open_flags & O_CREAT)) | ||
| 1601 | return -ENOENT; | ||
| 1600 | return status; | 1602 | return status; |
| 1603 | } | ||
| 1601 | 1604 | ||
| 1602 | if (o_arg->open_flags & O_CREAT) { | 1605 | if (o_arg->open_flags & O_CREAT) { |
| 1603 | update_changeattr(dir, &o_res->cinfo); | 1606 | update_changeattr(dir, &o_res->cinfo); |
| @@ -2408,14 +2411,15 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 2408 | return status; | 2411 | return status; |
| 2409 | } | 2412 | } |
| 2410 | 2413 | ||
| 2411 | static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, | 2414 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, |
| 2412 | const struct nfs_fh *dirfh, const struct qstr *name, | 2415 | const struct qstr *name, struct nfs_fh *fhandle, |
| 2413 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2416 | struct nfs_fattr *fattr) |
| 2414 | { | 2417 | { |
| 2418 | struct nfs_server *server = NFS_SERVER(dir); | ||
| 2415 | int status; | 2419 | int status; |
| 2416 | struct nfs4_lookup_arg args = { | 2420 | struct nfs4_lookup_arg args = { |
| 2417 | .bitmask = server->attr_bitmask, | 2421 | .bitmask = server->attr_bitmask, |
| 2418 | .dir_fh = dirfh, | 2422 | .dir_fh = NFS_FH(dir), |
| 2419 | .name = name, | 2423 | .name = name, |
| 2420 | }; | 2424 | }; |
| 2421 | struct nfs4_lookup_res res = { | 2425 | struct nfs4_lookup_res res = { |
| @@ -2431,40 +2435,8 @@ static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, | |||
| 2431 | 2435 | ||
| 2432 | nfs_fattr_init(fattr); | 2436 | nfs_fattr_init(fattr); |
| 2433 | 2437 | ||
| 2434 | dprintk("NFS call lookupfh %s\n", name->name); | ||
| 2435 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); | ||
| 2436 | dprintk("NFS reply lookupfh: %d\n", status); | ||
| 2437 | return status; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | ||
| 2441 | struct qstr *name, struct nfs_fh *fhandle, | ||
| 2442 | struct nfs_fattr *fattr) | ||
| 2443 | { | ||
| 2444 | struct nfs4_exception exception = { }; | ||
| 2445 | int err; | ||
| 2446 | do { | ||
| 2447 | err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr); | ||
| 2448 | /* FIXME: !!!! */ | ||
| 2449 | if (err == -NFS4ERR_MOVED) { | ||
| 2450 | err = -EREMOTE; | ||
| 2451 | break; | ||
| 2452 | } | ||
| 2453 | err = nfs4_handle_exception(server, err, &exception); | ||
| 2454 | } while (exception.retry); | ||
| 2455 | return err; | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | ||
| 2459 | const struct qstr *name, struct nfs_fh *fhandle, | ||
| 2460 | struct nfs_fattr *fattr) | ||
| 2461 | { | ||
| 2462 | int status; | ||
| 2463 | |||
| 2464 | dprintk("NFS call lookup %s\n", name->name); | 2438 | dprintk("NFS call lookup %s\n", name->name); |
| 2465 | status = _nfs4_proc_lookupfh(clnt, NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); | 2439 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); |
| 2466 | if (status == -NFS4ERR_MOVED) | ||
| 2467 | status = nfs4_get_referral(dir, name, fattr, fhandle); | ||
| 2468 | dprintk("NFS reply lookup: %d\n", status); | 2440 | dprintk("NFS reply lookup: %d\n", status); |
| 2469 | return status; | 2441 | return status; |
| 2470 | } | 2442 | } |
| @@ -2485,11 +2457,20 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst | |||
| 2485 | struct nfs4_exception exception = { }; | 2457 | struct nfs4_exception exception = { }; |
| 2486 | int err; | 2458 | int err; |
| 2487 | do { | 2459 | do { |
| 2488 | err = nfs4_handle_exception(NFS_SERVER(dir), | 2460 | int status; |
| 2489 | _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), | 2461 | |
| 2490 | &exception); | 2462 | status = _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr); |
| 2491 | if (err == -EPERM) | 2463 | switch (status) { |
| 2464 | case -NFS4ERR_BADNAME: | ||
| 2465 | return -ENOENT; | ||
| 2466 | case -NFS4ERR_MOVED: | ||
| 2467 | err = nfs4_get_referral(dir, name, fattr, fhandle); | ||
| 2468 | break; | ||
| 2469 | case -NFS4ERR_WRONGSEC: | ||
| 2492 | nfs_fixup_secinfo_attributes(fattr, fhandle); | 2470 | nfs_fixup_secinfo_attributes(fattr, fhandle); |
| 2471 | } | ||
| 2472 | err = nfs4_handle_exception(NFS_SERVER(dir), | ||
| 2473 | status, &exception); | ||
| 2493 | } while (exception.retry); | 2474 | } while (exception.retry); |
| 2494 | return err; | 2475 | return err; |
| 2495 | } | 2476 | } |
| @@ -3210,7 +3191,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) | |||
| 3210 | struct nfs_server *server = NFS_SERVER(data->inode); | 3191 | struct nfs_server *server = NFS_SERVER(data->inode); |
| 3211 | 3192 | ||
| 3212 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3193 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
| 3213 | nfs_restart_rpc(task, server->nfs_client); | 3194 | rpc_restart_call_prepare(task); |
| 3214 | return -EAGAIN; | 3195 | return -EAGAIN; |
| 3215 | } | 3196 | } |
| 3216 | 3197 | ||
| @@ -3260,7 +3241,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data | |||
| 3260 | struct inode *inode = data->inode; | 3241 | struct inode *inode = data->inode; |
| 3261 | 3242 | ||
| 3262 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 3243 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
| 3263 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3244 | rpc_restart_call_prepare(task); |
| 3264 | return -EAGAIN; | 3245 | return -EAGAIN; |
| 3265 | } | 3246 | } |
| 3266 | if (task->tk_status >= 0) { | 3247 | if (task->tk_status >= 0) { |
| @@ -3317,7 +3298,7 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *dat | |||
| 3317 | struct inode *inode = data->inode; | 3298 | struct inode *inode = data->inode; |
| 3318 | 3299 | ||
| 3319 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 3300 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
| 3320 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3301 | rpc_restart_call_prepare(task); |
| 3321 | return -EAGAIN; | 3302 | return -EAGAIN; |
| 3322 | } | 3303 | } |
| 3323 | nfs_refresh_inode(inode, data->res.fattr); | 3304 | nfs_refresh_inode(inode, data->res.fattr); |
| @@ -3857,7 +3838,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
| 3857 | default: | 3838 | default: |
| 3858 | if (nfs4_async_handle_error(task, data->res.server, NULL) == | 3839 | if (nfs4_async_handle_error(task, data->res.server, NULL) == |
| 3859 | -EAGAIN) { | 3840 | -EAGAIN) { |
| 3860 | nfs_restart_rpc(task, data->res.server->nfs_client); | 3841 | rpc_restart_call_prepare(task); |
| 3861 | return; | 3842 | return; |
| 3862 | } | 3843 | } |
| 3863 | } | 3844 | } |
| @@ -4111,8 +4092,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
| 4111 | break; | 4092 | break; |
| 4112 | default: | 4093 | default: |
| 4113 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) | 4094 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) |
| 4114 | nfs_restart_rpc(task, | 4095 | rpc_restart_call_prepare(task); |
| 4115 | calldata->server->nfs_client); | ||
| 4116 | } | 4096 | } |
| 4117 | } | 4097 | } |
| 4118 | 4098 | ||
| @@ -4945,7 +4925,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
| 4945 | task->tk_status = 0; | 4925 | task->tk_status = 0; |
| 4946 | /* fall through */ | 4926 | /* fall through */ |
| 4947 | case -NFS4ERR_RETRY_UNCACHED_REP: | 4927 | case -NFS4ERR_RETRY_UNCACHED_REP: |
| 4948 | nfs_restart_rpc(task, data->clp); | 4928 | rpc_restart_call_prepare(task); |
| 4949 | return; | 4929 | return; |
| 4950 | } | 4930 | } |
| 4951 | dprintk("<-- %s\n", __func__); | 4931 | dprintk("<-- %s\n", __func__); |
| @@ -5786,7 +5766,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
| 5786 | 5766 | ||
| 5787 | server = NFS_SERVER(lrp->args.inode); | 5767 | server = NFS_SERVER(lrp->args.inode); |
| 5788 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 5768 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { |
| 5789 | nfs_restart_rpc(task, lrp->clp); | 5769 | rpc_restart_call_prepare(task); |
| 5790 | return; | 5770 | return; |
| 5791 | } | 5771 | } |
| 5792 | spin_lock(&lo->plh_inode->i_lock); | 5772 | spin_lock(&lo->plh_inode->i_lock); |
| @@ -5957,7 +5937,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
| 5957 | } | 5937 | } |
| 5958 | 5938 | ||
| 5959 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 5939 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { |
| 5960 | nfs_restart_rpc(task, server->nfs_client); | 5940 | rpc_restart_call_prepare(task); |
| 5961 | return; | 5941 | return; |
| 5962 | } | 5942 | } |
| 5963 | 5943 | ||
| @@ -6270,7 +6250,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
| 6270 | .getroot = nfs4_proc_get_root, | 6250 | .getroot = nfs4_proc_get_root, |
| 6271 | .getattr = nfs4_proc_getattr, | 6251 | .getattr = nfs4_proc_getattr, |
| 6272 | .setattr = nfs4_proc_setattr, | 6252 | .setattr = nfs4_proc_setattr, |
| 6273 | .lookupfh = nfs4_proc_lookupfh, | ||
| 6274 | .lookup = nfs4_proc_lookup, | 6253 | .lookup = nfs4_proc_lookup, |
| 6275 | .access = nfs4_proc_access, | 6254 | .access = nfs4_proc_access, |
| 6276 | .readlink = nfs4_proc_readlink, | 6255 | .readlink = nfs4_proc_readlink, |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index e550e8836c37..ee73d9a4f700 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -1168,23 +1168,17 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | |||
| 1168 | /* | 1168 | /* |
| 1169 | * Called by non rpc-based layout drivers | 1169 | * Called by non rpc-based layout drivers |
| 1170 | */ | 1170 | */ |
| 1171 | int | 1171 | void pnfs_ld_write_done(struct nfs_write_data *data) |
| 1172 | pnfs_ld_write_done(struct nfs_write_data *data) | ||
| 1173 | { | 1172 | { |
| 1174 | int status; | 1173 | if (likely(!data->pnfs_error)) { |
| 1175 | |||
| 1176 | if (!data->pnfs_error) { | ||
| 1177 | pnfs_set_layoutcommit(data); | 1174 | pnfs_set_layoutcommit(data); |
| 1178 | data->mds_ops->rpc_call_done(&data->task, data); | 1175 | data->mds_ops->rpc_call_done(&data->task, data); |
| 1179 | data->mds_ops->rpc_release(data); | 1176 | } else { |
| 1180 | return 0; | 1177 | put_lseg(data->lseg); |
| 1178 | data->lseg = NULL; | ||
| 1179 | dprintk("pnfs write error = %d\n", data->pnfs_error); | ||
| 1181 | } | 1180 | } |
| 1182 | 1181 | data->mds_ops->rpc_release(data); | |
| 1183 | dprintk("%s: pnfs_error=%d, retry via MDS\n", __func__, | ||
| 1184 | data->pnfs_error); | ||
| 1185 | status = nfs_initiate_write(data, NFS_CLIENT(data->inode), | ||
| 1186 | data->mds_ops, NFS_FILE_SYNC); | ||
| 1187 | return status ? : -EAGAIN; | ||
| 1188 | } | 1182 | } |
| 1189 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); | 1183 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); |
| 1190 | 1184 | ||
| @@ -1268,23 +1262,17 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); | |||
| 1268 | /* | 1262 | /* |
| 1269 | * Called by non rpc-based layout drivers | 1263 | * Called by non rpc-based layout drivers |
| 1270 | */ | 1264 | */ |
| 1271 | int | 1265 | void pnfs_ld_read_done(struct nfs_read_data *data) |
| 1272 | pnfs_ld_read_done(struct nfs_read_data *data) | ||
| 1273 | { | 1266 | { |
| 1274 | int status; | 1267 | if (likely(!data->pnfs_error)) { |
| 1275 | |||
| 1276 | if (!data->pnfs_error) { | ||
| 1277 | __nfs4_read_done_cb(data); | 1268 | __nfs4_read_done_cb(data); |
| 1278 | data->mds_ops->rpc_call_done(&data->task, data); | 1269 | data->mds_ops->rpc_call_done(&data->task, data); |
| 1279 | data->mds_ops->rpc_release(data); | 1270 | } else { |
| 1280 | return 0; | 1271 | put_lseg(data->lseg); |
| 1272 | data->lseg = NULL; | ||
| 1273 | dprintk("pnfs write error = %d\n", data->pnfs_error); | ||
| 1281 | } | 1274 | } |
| 1282 | 1275 | data->mds_ops->rpc_release(data); | |
| 1283 | dprintk("%s: pnfs_error=%d, retry via MDS\n", __func__, | ||
| 1284 | data->pnfs_error); | ||
| 1285 | status = nfs_initiate_read(data, NFS_CLIENT(data->inode), | ||
| 1286 | data->mds_ops); | ||
| 1287 | return status ? : -EAGAIN; | ||
| 1288 | } | 1276 | } |
| 1289 | EXPORT_SYMBOL_GPL(pnfs_ld_read_done); | 1277 | EXPORT_SYMBOL_GPL(pnfs_ld_read_done); |
| 1290 | 1278 | ||
| @@ -1381,6 +1369,18 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp) | |||
| 1381 | } | 1369 | } |
| 1382 | } | 1370 | } |
| 1383 | 1371 | ||
| 1372 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) | ||
| 1373 | { | ||
| 1374 | if (lseg->pls_range.iomode == IOMODE_RW) { | ||
| 1375 | dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__); | ||
| 1376 | set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); | ||
| 1377 | } else { | ||
| 1378 | dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__); | ||
| 1379 | set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); | ||
| 1380 | } | ||
| 1381 | } | ||
| 1382 | EXPORT_SYMBOL_GPL(pnfs_set_lo_fail); | ||
| 1383 | |||
| 1384 | void | 1384 | void |
| 1385 | pnfs_set_layoutcommit(struct nfs_write_data *wdata) | 1385 | pnfs_set_layoutcommit(struct nfs_write_data *wdata) |
| 1386 | { | 1386 | { |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 01cbfd54f3cb..1509530cb111 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -178,6 +178,7 @@ int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); | |||
| 178 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); | 178 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); |
| 179 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); | 179 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); |
| 180 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); | 180 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); |
| 181 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg); | ||
| 181 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 182 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
| 182 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 183 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
| 183 | void pnfs_destroy_layout(struct nfs_inode *); | 184 | void pnfs_destroy_layout(struct nfs_inode *); |
| @@ -200,8 +201,8 @@ void pnfs_set_layoutcommit(struct nfs_write_data *wdata); | |||
| 200 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); | 201 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); |
| 201 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); | 202 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); |
| 202 | int _pnfs_return_layout(struct inode *); | 203 | int _pnfs_return_layout(struct inode *); |
| 203 | int pnfs_ld_write_done(struct nfs_write_data *); | 204 | void pnfs_ld_write_done(struct nfs_write_data *); |
| 204 | int pnfs_ld_read_done(struct nfs_read_data *); | 205 | void pnfs_ld_read_done(struct nfs_read_data *); |
| 205 | struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, | 206 | struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, |
| 206 | struct nfs_open_context *ctx, | 207 | struct nfs_open_context *ctx, |
| 207 | loff_t pos, | 208 | loff_t pos, |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 2171c043ab08..8b48ec63f722 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -35,16 +35,13 @@ static const struct rpc_call_ops nfs_read_partial_ops; | |||
| 35 | static const struct rpc_call_ops nfs_read_full_ops; | 35 | static const struct rpc_call_ops nfs_read_full_ops; |
| 36 | 36 | ||
| 37 | static struct kmem_cache *nfs_rdata_cachep; | 37 | static struct kmem_cache *nfs_rdata_cachep; |
| 38 | static mempool_t *nfs_rdata_mempool; | ||
| 39 | |||
| 40 | #define MIN_POOL_READ (32) | ||
| 41 | 38 | ||
| 42 | struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | 39 | struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) |
| 43 | { | 40 | { |
| 44 | struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_KERNEL); | 41 | struct nfs_read_data *p; |
| 45 | 42 | ||
| 43 | p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL); | ||
| 46 | if (p) { | 44 | if (p) { |
| 47 | memset(p, 0, sizeof(*p)); | ||
| 48 | INIT_LIST_HEAD(&p->pages); | 45 | INIT_LIST_HEAD(&p->pages); |
| 49 | p->npages = pagecount; | 46 | p->npages = pagecount; |
| 50 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 47 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
| @@ -52,7 +49,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | |||
| 52 | else { | 49 | else { |
| 53 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); | 50 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); |
| 54 | if (!p->pagevec) { | 51 | if (!p->pagevec) { |
| 55 | mempool_free(p, nfs_rdata_mempool); | 52 | kmem_cache_free(nfs_rdata_cachep, p); |
| 56 | p = NULL; | 53 | p = NULL; |
| 57 | } | 54 | } |
| 58 | } | 55 | } |
| @@ -64,7 +61,7 @@ void nfs_readdata_free(struct nfs_read_data *p) | |||
| 64 | { | 61 | { |
| 65 | if (p && (p->pagevec != &p->page_array[0])) | 62 | if (p && (p->pagevec != &p->page_array[0])) |
| 66 | kfree(p->pagevec); | 63 | kfree(p->pagevec); |
| 67 | mempool_free(p, nfs_rdata_mempool); | 64 | kmem_cache_free(nfs_rdata_cachep, p); |
| 68 | } | 65 | } |
| 69 | 66 | ||
| 70 | void nfs_readdata_release(struct nfs_read_data *rdata) | 67 | void nfs_readdata_release(struct nfs_read_data *rdata) |
| @@ -276,7 +273,6 @@ nfs_async_read_error(struct list_head *head) | |||
| 276 | while (!list_empty(head)) { | 273 | while (!list_empty(head)) { |
| 277 | req = nfs_list_entry(head->next); | 274 | req = nfs_list_entry(head->next); |
| 278 | nfs_list_remove_request(req); | 275 | nfs_list_remove_request(req); |
| 279 | SetPageError(req->wb_page); | ||
| 280 | nfs_readpage_release(req); | 276 | nfs_readpage_release(req); |
| 281 | } | 277 | } |
| 282 | } | 278 | } |
| @@ -322,7 +318,6 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, struct list_head | |||
| 322 | offset += len; | 318 | offset += len; |
| 323 | } while(nbytes != 0); | 319 | } while(nbytes != 0); |
| 324 | atomic_set(&req->wb_complete, requests); | 320 | atomic_set(&req->wb_complete, requests); |
| 325 | ClearPageError(page); | ||
| 326 | desc->pg_rpc_callops = &nfs_read_partial_ops; | 321 | desc->pg_rpc_callops = &nfs_read_partial_ops; |
| 327 | return ret; | 322 | return ret; |
| 328 | out_bad: | 323 | out_bad: |
| @@ -331,7 +326,6 @@ out_bad: | |||
| 331 | list_del(&data->list); | 326 | list_del(&data->list); |
| 332 | nfs_readdata_free(data); | 327 | nfs_readdata_free(data); |
| 333 | } | 328 | } |
| 334 | SetPageError(page); | ||
| 335 | nfs_readpage_release(req); | 329 | nfs_readpage_release(req); |
| 336 | return -ENOMEM; | 330 | return -ENOMEM; |
| 337 | } | 331 | } |
| @@ -357,7 +351,6 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, struct list_head * | |||
| 357 | req = nfs_list_entry(head->next); | 351 | req = nfs_list_entry(head->next); |
| 358 | nfs_list_remove_request(req); | 352 | nfs_list_remove_request(req); |
| 359 | nfs_list_add_request(req, &data->pages); | 353 | nfs_list_add_request(req, &data->pages); |
| 360 | ClearPageError(req->wb_page); | ||
| 361 | *pages++ = req->wb_page; | 354 | *pages++ = req->wb_page; |
| 362 | } | 355 | } |
| 363 | req = nfs_list_entry(data->pages.next); | 356 | req = nfs_list_entry(data->pages.next); |
| @@ -435,7 +428,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data | |||
| 435 | argp->offset += resp->count; | 428 | argp->offset += resp->count; |
| 436 | argp->pgbase += resp->count; | 429 | argp->pgbase += resp->count; |
| 437 | argp->count -= resp->count; | 430 | argp->count -= resp->count; |
| 438 | nfs_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client); | 431 | rpc_restart_call_prepare(task); |
| 439 | } | 432 | } |
| 440 | 433 | ||
| 441 | /* | 434 | /* |
| @@ -462,10 +455,10 @@ static void nfs_readpage_release_partial(void *calldata) | |||
| 462 | int status = data->task.tk_status; | 455 | int status = data->task.tk_status; |
| 463 | 456 | ||
| 464 | if (status < 0) | 457 | if (status < 0) |
| 465 | SetPageError(page); | 458 | set_bit(PG_PARTIAL_READ_FAILED, &req->wb_flags); |
| 466 | 459 | ||
| 467 | if (atomic_dec_and_test(&req->wb_complete)) { | 460 | if (atomic_dec_and_test(&req->wb_complete)) { |
| 468 | if (!PageError(page)) | 461 | if (!test_bit(PG_PARTIAL_READ_FAILED, &req->wb_flags)) |
| 469 | SetPageUptodate(page); | 462 | SetPageUptodate(page); |
| 470 | nfs_readpage_release(req); | 463 | nfs_readpage_release(req); |
| 471 | } | 464 | } |
| @@ -541,13 +534,23 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata) | |||
| 541 | static void nfs_readpage_release_full(void *calldata) | 534 | static void nfs_readpage_release_full(void *calldata) |
| 542 | { | 535 | { |
| 543 | struct nfs_read_data *data = calldata; | 536 | struct nfs_read_data *data = calldata; |
| 537 | struct nfs_pageio_descriptor pgio; | ||
| 544 | 538 | ||
| 539 | if (data->pnfs_error) { | ||
| 540 | nfs_pageio_init_read_mds(&pgio, data->inode); | ||
| 541 | pgio.pg_recoalesce = 1; | ||
| 542 | } | ||
| 545 | while (!list_empty(&data->pages)) { | 543 | while (!list_empty(&data->pages)) { |
| 546 | struct nfs_page *req = nfs_list_entry(data->pages.next); | 544 | struct nfs_page *req = nfs_list_entry(data->pages.next); |
| 547 | 545 | ||
| 548 | nfs_list_remove_request(req); | 546 | nfs_list_remove_request(req); |
| 549 | nfs_readpage_release(req); | 547 | if (!data->pnfs_error) |
| 548 | nfs_readpage_release(req); | ||
| 549 | else | ||
| 550 | nfs_pageio_add_request(&pgio, req); | ||
| 550 | } | 551 | } |
| 552 | if (data->pnfs_error) | ||
| 553 | nfs_pageio_complete(&pgio); | ||
| 551 | nfs_readdata_release(calldata); | 554 | nfs_readdata_release(calldata); |
| 552 | } | 555 | } |
| 553 | 556 | ||
| @@ -648,7 +651,6 @@ readpage_async_filler(void *data, struct page *page) | |||
| 648 | return 0; | 651 | return 0; |
| 649 | out_error: | 652 | out_error: |
| 650 | error = PTR_ERR(new); | 653 | error = PTR_ERR(new); |
| 651 | SetPageError(page); | ||
| 652 | out_unlock: | 654 | out_unlock: |
| 653 | unlock_page(page); | 655 | unlock_page(page); |
| 654 | return error; | 656 | return error; |
| @@ -711,16 +713,10 @@ int __init nfs_init_readpagecache(void) | |||
| 711 | if (nfs_rdata_cachep == NULL) | 713 | if (nfs_rdata_cachep == NULL) |
| 712 | return -ENOMEM; | 714 | return -ENOMEM; |
| 713 | 715 | ||
| 714 | nfs_rdata_mempool = mempool_create_slab_pool(MIN_POOL_READ, | ||
| 715 | nfs_rdata_cachep); | ||
| 716 | if (nfs_rdata_mempool == NULL) | ||
| 717 | return -ENOMEM; | ||
| 718 | |||
| 719 | return 0; | 716 | return 0; |
| 720 | } | 717 | } |
| 721 | 718 | ||
| 722 | void nfs_destroy_readpagecache(void) | 719 | void nfs_destroy_readpagecache(void) |
| 723 | { | 720 | { |
| 724 | mempool_destroy(nfs_rdata_mempool); | ||
| 725 | kmem_cache_destroy(nfs_rdata_cachep); | 721 | kmem_cache_destroy(nfs_rdata_cachep); |
| 726 | } | 722 | } |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 5b19b6aabe18..480b3b6bf71e 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -733,18 +733,22 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 733 | 733 | ||
| 734 | return 0; | 734 | return 0; |
| 735 | } | 735 | } |
| 736 | |||
| 737 | #ifdef CONFIG_NFS_V4 | ||
| 736 | #ifdef CONFIG_NFS_V4_1 | 738 | #ifdef CONFIG_NFS_V4_1 |
| 737 | void show_sessions(struct seq_file *m, struct nfs_server *server) | 739 | static void show_sessions(struct seq_file *m, struct nfs_server *server) |
| 738 | { | 740 | { |
| 739 | if (nfs4_has_session(server->nfs_client)) | 741 | if (nfs4_has_session(server->nfs_client)) |
| 740 | seq_printf(m, ",sessions"); | 742 | seq_printf(m, ",sessions"); |
| 741 | } | 743 | } |
| 742 | #else | 744 | #else |
| 743 | void show_sessions(struct seq_file *m, struct nfs_server *server) {} | 745 | static void show_sessions(struct seq_file *m, struct nfs_server *server) {} |
| 746 | #endif | ||
| 744 | #endif | 747 | #endif |
| 745 | 748 | ||
| 749 | #ifdef CONFIG_NFS_V4 | ||
| 746 | #ifdef CONFIG_NFS_V4_1 | 750 | #ifdef CONFIG_NFS_V4_1 |
| 747 | void show_pnfs(struct seq_file *m, struct nfs_server *server) | 751 | static void show_pnfs(struct seq_file *m, struct nfs_server *server) |
| 748 | { | 752 | { |
| 749 | seq_printf(m, ",pnfs="); | 753 | seq_printf(m, ",pnfs="); |
| 750 | if (server->pnfs_curr_ld) | 754 | if (server->pnfs_curr_ld) |
| @@ -752,9 +756,10 @@ void show_pnfs(struct seq_file *m, struct nfs_server *server) | |||
| 752 | else | 756 | else |
| 753 | seq_printf(m, "not configured"); | 757 | seq_printf(m, "not configured"); |
| 754 | } | 758 | } |
| 755 | #else /* CONFIG_NFS_V4_1 */ | 759 | #else |
| 756 | void show_pnfs(struct seq_file *m, struct nfs_server *server) {} | 760 | static void show_pnfs(struct seq_file *m, struct nfs_server *server) {} |
| 757 | #endif /* CONFIG_NFS_V4_1 */ | 761 | #endif |
| 762 | #endif | ||
| 758 | 763 | ||
| 759 | static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt) | 764 | static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt) |
| 760 | { | 765 | { |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index b2fbbde58e44..4f9319a2e567 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
| @@ -87,7 +87,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) | |||
| 87 | struct inode *dir = data->dir; | 87 | struct inode *dir = data->dir; |
| 88 | 88 | ||
| 89 | if (!NFS_PROTO(dir)->unlink_done(task, dir)) | 89 | if (!NFS_PROTO(dir)->unlink_done(task, dir)) |
| 90 | nfs_restart_rpc(task, NFS_SERVER(dir)->nfs_client); | 90 | rpc_restart_call_prepare(task); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /** | 93 | /** |
| @@ -369,7 +369,7 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata) | |||
| 369 | struct dentry *new_dentry = data->new_dentry; | 369 | struct dentry *new_dentry = data->new_dentry; |
| 370 | 370 | ||
| 371 | if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) { | 371 | if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) { |
| 372 | nfs_restart_rpc(task, NFS_SERVER(old_dir)->nfs_client); | 372 | rpc_restart_call_prepare(task); |
| 373 | return; | 373 | return; |
| 374 | } | 374 | } |
| 375 | 375 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c9bd2a6b7d4b..2219c88d96b2 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -390,7 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
| 390 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); | 390 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); |
| 391 | BUG_ON(error); | 391 | BUG_ON(error); |
| 392 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) | 392 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) |
| 393 | nfsi->change_attr++; | 393 | inode->i_version++; |
| 394 | set_bit(PG_MAPPED, &req->wb_flags); | 394 | set_bit(PG_MAPPED, &req->wb_flags); |
| 395 | SetPagePrivate(req->wb_page); | 395 | SetPagePrivate(req->wb_page); |
| 396 | set_page_private(req->wb_page, (unsigned long)req); | 396 | set_page_private(req->wb_page, (unsigned long)req); |
| @@ -428,7 +428,6 @@ static void | |||
| 428 | nfs_mark_request_dirty(struct nfs_page *req) | 428 | nfs_mark_request_dirty(struct nfs_page *req) |
| 429 | { | 429 | { |
| 430 | __set_page_dirty_nobuffers(req->wb_page); | 430 | __set_page_dirty_nobuffers(req->wb_page); |
| 431 | __mark_inode_dirty(req->wb_page->mapping->host, I_DIRTY_DATASYNC); | ||
| 432 | } | 431 | } |
| 433 | 432 | ||
| 434 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 433 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
| @@ -762,6 +761,8 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 762 | status = nfs_writepage_setup(ctx, page, offset, count); | 761 | status = nfs_writepage_setup(ctx, page, offset, count); |
| 763 | if (status < 0) | 762 | if (status < 0) |
| 764 | nfs_set_pageerror(page); | 763 | nfs_set_pageerror(page); |
| 764 | else | ||
| 765 | __set_page_dirty_nobuffers(page); | ||
| 765 | 766 | ||
| 766 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", | 767 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", |
| 767 | status, (long long)i_size_read(inode)); | 768 | status, (long long)i_size_read(inode)); |
| @@ -1010,7 +1011,6 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *r | |||
| 1010 | req = nfs_list_entry(head->next); | 1011 | req = nfs_list_entry(head->next); |
| 1011 | nfs_list_remove_request(req); | 1012 | nfs_list_remove_request(req); |
| 1012 | nfs_list_add_request(req, &data->pages); | 1013 | nfs_list_add_request(req, &data->pages); |
| 1013 | ClearPageError(req->wb_page); | ||
| 1014 | *pages++ = req->wb_page; | 1014 | *pages++ = req->wb_page; |
| 1015 | } | 1015 | } |
| 1016 | req = nfs_list_entry(data->pages.next); | 1016 | req = nfs_list_entry(data->pages.next); |
| @@ -1165,7 +1165,13 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
| 1165 | static void nfs_writeback_release_full(void *calldata) | 1165 | static void nfs_writeback_release_full(void *calldata) |
| 1166 | { | 1166 | { |
| 1167 | struct nfs_write_data *data = calldata; | 1167 | struct nfs_write_data *data = calldata; |
| 1168 | int status = data->task.tk_status; | 1168 | int ret, status = data->task.tk_status; |
| 1169 | struct nfs_pageio_descriptor pgio; | ||
| 1170 | |||
| 1171 | if (data->pnfs_error) { | ||
| 1172 | nfs_pageio_init_write_mds(&pgio, data->inode, FLUSH_STABLE); | ||
| 1173 | pgio.pg_recoalesce = 1; | ||
| 1174 | } | ||
| 1169 | 1175 | ||
| 1170 | /* Update attributes as result of writeback. */ | 1176 | /* Update attributes as result of writeback. */ |
| 1171 | while (!list_empty(&data->pages)) { | 1177 | while (!list_empty(&data->pages)) { |
| @@ -1181,6 +1187,11 @@ static void nfs_writeback_release_full(void *calldata) | |||
| 1181 | req->wb_bytes, | 1187 | req->wb_bytes, |
| 1182 | (long long)req_offset(req)); | 1188 | (long long)req_offset(req)); |
| 1183 | 1189 | ||
| 1190 | if (data->pnfs_error) { | ||
| 1191 | dprintk(", pnfs error = %d\n", data->pnfs_error); | ||
| 1192 | goto next; | ||
| 1193 | } | ||
| 1194 | |||
| 1184 | if (status < 0) { | 1195 | if (status < 0) { |
| 1185 | nfs_set_pageerror(page); | 1196 | nfs_set_pageerror(page); |
| 1186 | nfs_context_set_write_error(req->wb_context, status); | 1197 | nfs_context_set_write_error(req->wb_context, status); |
| @@ -1200,7 +1211,19 @@ remove_request: | |||
| 1200 | next: | 1211 | next: |
| 1201 | nfs_clear_page_tag_locked(req); | 1212 | nfs_clear_page_tag_locked(req); |
| 1202 | nfs_end_page_writeback(page); | 1213 | nfs_end_page_writeback(page); |
| 1214 | if (data->pnfs_error) { | ||
| 1215 | lock_page(page); | ||
| 1216 | nfs_pageio_cond_complete(&pgio, page->index); | ||
| 1217 | ret = nfs_page_async_flush(&pgio, page, 0); | ||
| 1218 | if (ret) { | ||
| 1219 | nfs_set_pageerror(page); | ||
| 1220 | dprintk("rewrite to MDS error = %d\n", ret); | ||
| 1221 | } | ||
| 1222 | unlock_page(page); | ||
| 1223 | } | ||
| 1203 | } | 1224 | } |
| 1225 | if (data->pnfs_error) | ||
| 1226 | nfs_pageio_complete(&pgio); | ||
| 1204 | nfs_writedata_release(calldata); | 1227 | nfs_writedata_release(calldata); |
| 1205 | } | 1228 | } |
| 1206 | 1229 | ||
| @@ -1281,7 +1304,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 1281 | */ | 1304 | */ |
| 1282 | argp->stable = NFS_FILE_SYNC; | 1305 | argp->stable = NFS_FILE_SYNC; |
| 1283 | } | 1306 | } |
| 1284 | nfs_restart_rpc(task, server->nfs_client); | 1307 | rpc_restart_call_prepare(task); |
| 1285 | return; | 1308 | return; |
| 1286 | } | 1309 | } |
| 1287 | if (time_before(complain, jiffies)) { | 1310 | if (time_before(complain, jiffies)) { |
| @@ -1553,6 +1576,10 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
| 1553 | int flags = FLUSH_SYNC; | 1576 | int flags = FLUSH_SYNC; |
| 1554 | int ret = 0; | 1577 | int ret = 0; |
| 1555 | 1578 | ||
| 1579 | /* no commits means nothing needs to be done */ | ||
| 1580 | if (!nfsi->ncommit) | ||
| 1581 | return ret; | ||
| 1582 | |||
| 1556 | if (wbc->sync_mode == WB_SYNC_NONE) { | 1583 | if (wbc->sync_mode == WB_SYNC_NONE) { |
| 1557 | /* Don't commit yet if this is a non-blocking flush and there | 1584 | /* Don't commit yet if this is a non-blocking flush and there |
| 1558 | * are a lot of outstanding writes for this mapping. | 1585 | * are a lot of outstanding writes for this mapping. |
| @@ -1686,34 +1713,20 @@ out_error: | |||
| 1686 | int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | 1713 | int nfs_migrate_page(struct address_space *mapping, struct page *newpage, |
| 1687 | struct page *page) | 1714 | struct page *page) |
| 1688 | { | 1715 | { |
| 1689 | struct nfs_page *req; | 1716 | /* |
| 1690 | int ret; | 1717 | * If PagePrivate is set, then the page is currently associated with |
| 1718 | * an in-progress read or write request. Don't try to migrate it. | ||
| 1719 | * | ||
| 1720 | * FIXME: we could do this in principle, but we'll need a way to ensure | ||
| 1721 | * that we can safely release the inode reference while holding | ||
| 1722 | * the page lock. | ||
| 1723 | */ | ||
| 1724 | if (PagePrivate(page)) | ||
| 1725 | return -EBUSY; | ||
| 1691 | 1726 | ||
| 1692 | nfs_fscache_release_page(page, GFP_KERNEL); | 1727 | nfs_fscache_release_page(page, GFP_KERNEL); |
| 1693 | 1728 | ||
| 1694 | req = nfs_find_and_lock_request(page, false); | 1729 | return migrate_page(mapping, newpage, page); |
| 1695 | ret = PTR_ERR(req); | ||
| 1696 | if (IS_ERR(req)) | ||
| 1697 | goto out; | ||
| 1698 | |||
| 1699 | ret = migrate_page(mapping, newpage, page); | ||
| 1700 | if (!req) | ||
| 1701 | goto out; | ||
| 1702 | if (ret) | ||
| 1703 | goto out_unlock; | ||
| 1704 | page_cache_get(newpage); | ||
| 1705 | spin_lock(&mapping->host->i_lock); | ||
| 1706 | req->wb_page = newpage; | ||
| 1707 | SetPagePrivate(newpage); | ||
| 1708 | set_page_private(newpage, (unsigned long)req); | ||
| 1709 | ClearPagePrivate(page); | ||
| 1710 | set_page_private(page, 0); | ||
| 1711 | spin_unlock(&mapping->host->i_lock); | ||
| 1712 | page_cache_release(page); | ||
| 1713 | out_unlock: | ||
| 1714 | nfs_clear_page_tag_locked(req); | ||
| 1715 | out: | ||
| 1716 | return ret; | ||
| 1717 | } | 1730 | } |
| 1718 | #endif | 1731 | #endif |
| 1719 | 1732 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index eaac770f886e..60a137b7f171 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -149,7 +149,6 @@ struct nfs_inode { | |||
| 149 | unsigned long read_cache_jiffies; | 149 | unsigned long read_cache_jiffies; |
| 150 | unsigned long attrtimeo; | 150 | unsigned long attrtimeo; |
| 151 | unsigned long attrtimeo_timestamp; | 151 | unsigned long attrtimeo_timestamp; |
| 152 | __u64 change_attr; /* v4 only */ | ||
| 153 | 152 | ||
| 154 | unsigned long attr_gencount; | 153 | unsigned long attr_gencount; |
| 155 | /* "Generation counter" for the attribute cache. This is | 154 | /* "Generation counter" for the attribute cache. This is |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index e2791a27a901..ab465fe8c3d6 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
| @@ -34,6 +34,7 @@ enum { | |||
| 34 | PG_NEED_COMMIT, | 34 | PG_NEED_COMMIT, |
| 35 | PG_NEED_RESCHED, | 35 | PG_NEED_RESCHED, |
| 36 | PG_PNFS_COMMIT, | 36 | PG_PNFS_COMMIT, |
| 37 | PG_PARTIAL_READ_FAILED, | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | struct nfs_inode; | 40 | struct nfs_inode; |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index abd615d74a29..c74595ba7094 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
| @@ -1133,7 +1133,6 @@ struct nfs_page; | |||
| 1133 | #define NFS_PAGEVEC_SIZE (8U) | 1133 | #define NFS_PAGEVEC_SIZE (8U) |
| 1134 | 1134 | ||
| 1135 | struct nfs_read_data { | 1135 | struct nfs_read_data { |
| 1136 | int flags; | ||
| 1137 | struct rpc_task task; | 1136 | struct rpc_task task; |
| 1138 | struct inode *inode; | 1137 | struct inode *inode; |
| 1139 | struct rpc_cred *cred; | 1138 | struct rpc_cred *cred; |
| @@ -1156,7 +1155,6 @@ struct nfs_read_data { | |||
| 1156 | }; | 1155 | }; |
| 1157 | 1156 | ||
| 1158 | struct nfs_write_data { | 1157 | struct nfs_write_data { |
| 1159 | int flags; | ||
| 1160 | struct rpc_task task; | 1158 | struct rpc_task task; |
| 1161 | struct inode *inode; | 1159 | struct inode *inode; |
| 1162 | struct rpc_cred *cred; | 1160 | struct rpc_cred *cred; |
| @@ -1197,9 +1195,6 @@ struct nfs_rpc_ops { | |||
| 1197 | 1195 | ||
| 1198 | int (*getroot) (struct nfs_server *, struct nfs_fh *, | 1196 | int (*getroot) (struct nfs_server *, struct nfs_fh *, |
| 1199 | struct nfs_fsinfo *); | 1197 | struct nfs_fsinfo *); |
| 1200 | int (*lookupfh)(struct nfs_server *, struct nfs_fh *, | ||
| 1201 | struct qstr *, struct nfs_fh *, | ||
| 1202 | struct nfs_fattr *); | ||
| 1203 | int (*getattr) (struct nfs_server *, struct nfs_fh *, | 1198 | int (*getattr) (struct nfs_server *, struct nfs_fh *, |
| 1204 | struct nfs_fattr *); | 1199 | struct nfs_fattr *); |
| 1205 | int (*setattr) (struct dentry *, struct nfs_fattr *, | 1200 | int (*setattr) (struct dentry *, struct nfs_fattr *, |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index ee1bb67f525e..492486a74484 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #ifndef _LINUX_SUNRPC_CLNT_H | 9 | #ifndef _LINUX_SUNRPC_CLNT_H |
| 10 | #define _LINUX_SUNRPC_CLNT_H | 10 | #define _LINUX_SUNRPC_CLNT_H |
| 11 | 11 | ||
| 12 | #include <linux/types.h> | ||
| 12 | #include <linux/socket.h> | 13 | #include <linux/socket.h> |
| 13 | #include <linux/in.h> | 14 | #include <linux/in.h> |
| 14 | #include <linux/in6.h> | 15 | #include <linux/in6.h> |
| @@ -161,7 +162,7 @@ const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); | |||
| 161 | size_t rpc_ntop(const struct sockaddr *, char *, const size_t); | 162 | size_t rpc_ntop(const struct sockaddr *, char *, const size_t); |
| 162 | size_t rpc_pton(const char *, const size_t, | 163 | size_t rpc_pton(const char *, const size_t, |
| 163 | struct sockaddr *, const size_t); | 164 | struct sockaddr *, const size_t); |
| 164 | char * rpc_sockaddr2uaddr(const struct sockaddr *); | 165 | char * rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t); |
| 165 | size_t rpc_uaddr2sockaddr(const char *, const size_t, | 166 | size_t rpc_uaddr2sockaddr(const char *, const size_t, |
| 166 | struct sockaddr *, const size_t); | 167 | struct sockaddr *, const size_t); |
| 167 | 168 | ||
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index cf14db975da0..e4ea43058d8f 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h | |||
| @@ -44,6 +44,8 @@ RPC_I(struct inode *inode) | |||
| 44 | return container_of(inode, struct rpc_inode, vfs_inode); | 44 | return container_of(inode, struct rpc_inode, vfs_inode); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *, | ||
| 48 | char __user *, size_t); | ||
| 47 | extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); | 49 | extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); |
| 48 | 50 | ||
| 49 | struct rpc_clnt; | 51 | struct rpc_clnt; |
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index 4195233c4914..4548757c9871 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
| @@ -255,12 +255,13 @@ EXPORT_SYMBOL_GPL(rpc_pton); | |||
| 255 | /** | 255 | /** |
| 256 | * rpc_sockaddr2uaddr - Construct a universal address string from @sap. | 256 | * rpc_sockaddr2uaddr - Construct a universal address string from @sap. |
| 257 | * @sap: socket address | 257 | * @sap: socket address |
| 258 | * @gfp_flags: allocation mode | ||
| 258 | * | 259 | * |
| 259 | * Returns a %NUL-terminated string in dynamically allocated memory; | 260 | * Returns a %NUL-terminated string in dynamically allocated memory; |
| 260 | * otherwise NULL is returned if an error occurred. Caller must | 261 | * otherwise NULL is returned if an error occurred. Caller must |
| 261 | * free the returned string. | 262 | * free the returned string. |
| 262 | */ | 263 | */ |
| 263 | char *rpc_sockaddr2uaddr(const struct sockaddr *sap) | 264 | char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) |
| 264 | { | 265 | { |
| 265 | char portbuf[RPCBIND_MAXUADDRPLEN]; | 266 | char portbuf[RPCBIND_MAXUADDRPLEN]; |
| 266 | char addrbuf[RPCBIND_MAXUADDRLEN]; | 267 | char addrbuf[RPCBIND_MAXUADDRLEN]; |
| @@ -288,9 +289,8 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap) | |||
| 288 | if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf)) | 289 | if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf)) |
| 289 | return NULL; | 290 | return NULL; |
| 290 | 291 | ||
| 291 | return kstrdup(addrbuf, GFP_KERNEL); | 292 | return kstrdup(addrbuf, gfp_flags); |
| 292 | } | 293 | } |
| 293 | EXPORT_SYMBOL_GPL(rpc_sockaddr2uaddr); | ||
| 294 | 294 | ||
| 295 | /** | 295 | /** |
| 296 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. | 296 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d4132754cbe1..afb56553dfe7 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -603,26 +603,6 @@ out: | |||
| 603 | return err; | 603 | return err; |
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | static ssize_t | ||
| 607 | gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, | ||
| 608 | char __user *dst, size_t buflen) | ||
| 609 | { | ||
| 610 | char *data = (char *)msg->data + msg->copied; | ||
| 611 | size_t mlen = min(msg->len, buflen); | ||
| 612 | unsigned long left; | ||
| 613 | |||
| 614 | left = copy_to_user(dst, data, mlen); | ||
| 615 | if (left == mlen) { | ||
| 616 | msg->errno = -EFAULT; | ||
| 617 | return -EFAULT; | ||
| 618 | } | ||
| 619 | |||
| 620 | mlen -= left; | ||
| 621 | msg->copied += mlen; | ||
| 622 | msg->errno = 0; | ||
| 623 | return mlen; | ||
| 624 | } | ||
| 625 | |||
| 626 | #define MSG_BUF_MAXSIZE 1024 | 606 | #define MSG_BUF_MAXSIZE 1024 |
| 627 | 607 | ||
| 628 | static ssize_t | 608 | static ssize_t |
| @@ -1590,7 +1570,7 @@ static const struct rpc_credops gss_nullops = { | |||
| 1590 | }; | 1570 | }; |
| 1591 | 1571 | ||
| 1592 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { | 1572 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { |
| 1593 | .upcall = gss_pipe_upcall, | 1573 | .upcall = rpc_pipe_generic_upcall, |
| 1594 | .downcall = gss_pipe_downcall, | 1574 | .downcall = gss_pipe_downcall, |
| 1595 | .destroy_msg = gss_pipe_destroy_msg, | 1575 | .destroy_msg = gss_pipe_destroy_msg, |
| 1596 | .open_pipe = gss_pipe_open_v0, | 1576 | .open_pipe = gss_pipe_open_v0, |
| @@ -1598,7 +1578,7 @@ static const struct rpc_pipe_ops gss_upcall_ops_v0 = { | |||
| 1598 | }; | 1578 | }; |
| 1599 | 1579 | ||
| 1600 | static const struct rpc_pipe_ops gss_upcall_ops_v1 = { | 1580 | static const struct rpc_pipe_ops gss_upcall_ops_v1 = { |
| 1601 | .upcall = gss_pipe_upcall, | 1581 | .upcall = rpc_pipe_generic_upcall, |
| 1602 | .downcall = gss_pipe_downcall, | 1582 | .downcall = gss_pipe_downcall, |
| 1603 | .destroy_msg = gss_pipe_destroy_msg, | 1583 | .destroy_msg = gss_pipe_destroy_msg, |
| 1604 | .open_pipe = gss_pipe_open_v1, | 1584 | .open_pipe = gss_pipe_open_v1, |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index c5347d29cfb7..f0268ea7e711 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -850,7 +850,9 @@ rpc_restart_call_prepare(struct rpc_task *task) | |||
| 850 | { | 850 | { |
| 851 | if (RPC_ASSASSINATED(task)) | 851 | if (RPC_ASSASSINATED(task)) |
| 852 | return 0; | 852 | return 0; |
| 853 | task->tk_action = rpc_prepare_task; | 853 | task->tk_action = call_start; |
| 854 | if (task->tk_ops->rpc_call_prepare != NULL) | ||
| 855 | task->tk_action = rpc_prepare_task; | ||
| 854 | return 1; | 856 | return 1; |
| 855 | } | 857 | } |
| 856 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 858 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 3156ba864519..bfddd68b31d3 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -77,6 +77,26 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
| 77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | 77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, | ||
| 81 | char __user *dst, size_t buflen) | ||
| 82 | { | ||
| 83 | char *data = (char *)msg->data + msg->copied; | ||
| 84 | size_t mlen = min(msg->len - msg->copied, buflen); | ||
| 85 | unsigned long left; | ||
| 86 | |||
| 87 | left = copy_to_user(dst, data, mlen); | ||
| 88 | if (left == mlen) { | ||
| 89 | msg->errno = -EFAULT; | ||
| 90 | return -EFAULT; | ||
| 91 | } | ||
| 92 | |||
| 93 | mlen -= left; | ||
| 94 | msg->copied += mlen; | ||
| 95 | msg->errno = 0; | ||
| 96 | return mlen; | ||
| 97 | } | ||
| 98 | EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); | ||
| 99 | |||
| 80 | /** | 100 | /** |
| 81 | * rpc_queue_upcall - queue an upcall message to userspace | 101 | * rpc_queue_upcall - queue an upcall message to userspace |
| 82 | * @inode: inode of upcall pipe on which to queue given message | 102 | * @inode: inode of upcall pipe on which to queue given message |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index e45d2fbbe5a8..f588b852d41c 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
| @@ -410,7 +410,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
| 410 | unsigned short port = ntohs(sin->sin_port); | 410 | unsigned short port = ntohs(sin->sin_port); |
| 411 | int result; | 411 | int result; |
| 412 | 412 | ||
| 413 | map->r_addr = rpc_sockaddr2uaddr(sap); | 413 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
| 414 | 414 | ||
| 415 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 415 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
| 416 | "local rpcbind\n", (port ? "" : "un"), | 416 | "local rpcbind\n", (port ? "" : "un"), |
| @@ -437,7 +437,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap, | |||
| 437 | unsigned short port = ntohs(sin6->sin6_port); | 437 | unsigned short port = ntohs(sin6->sin6_port); |
| 438 | int result; | 438 | int result; |
| 439 | 439 | ||
| 440 | map->r_addr = rpc_sockaddr2uaddr(sap); | 440 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
| 441 | 441 | ||
| 442 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 442 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
| 443 | "local rpcbind\n", (port ? "" : "un"), | 443 | "local rpcbind\n", (port ? "" : "un"), |
| @@ -686,7 +686,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
| 686 | case RPCBVERS_4: | 686 | case RPCBVERS_4: |
| 687 | case RPCBVERS_3: | 687 | case RPCBVERS_3: |
| 688 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 688 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
| 689 | map->r_addr = rpc_sockaddr2uaddr(sap); | 689 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); |
| 690 | map->r_owner = ""; | 690 | map->r_owner = ""; |
| 691 | break; | 691 | break; |
| 692 | case RPCBVERS_2: | 692 | case RPCBVERS_2: |
