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 /fs/nfs | |
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
...
Diffstat (limited to 'fs/nfs')
-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 |
17 files changed, 202 insertions, 273 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 9561c8fc8bd..281ae95932c 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 f27d827960a..42acf7ef599 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 a83b393fb01..d08ba9107fd 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 b4e41dd4d0f..873bf00d51a 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 321a66bc384..7f265406980 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 5b1006480bc..7cf2c4699b0 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 f20801ae0a1..47d1c6ff2d8 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 fe1203797b2..4dc6d078f10 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 ab12913dd47..c1a1bd8ddf1 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 e8915d4840a..09119418402 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 4700fae1ada..d2ae413c986 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 e550e8836c3..ee73d9a4f70 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 01cbfd54f3c..1509530cb11 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 2171c043ab0..8b48ec63f72 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 5b19b6aabe1..480b3b6bf71 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 b2fbbde58e4..4f9319a2e56 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 c9bd2a6b7d4..2219c88d96b 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 | ||