diff options
43 files changed, 294 insertions, 219 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 1e987acf20c9..8664417955a2 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -22,7 +22,7 @@ nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | |||
22 | obj-$(CONFIG_NFS_V4) += nfsv4.o | 22 | obj-$(CONFIG_NFS_V4) += nfsv4.o |
23 | CFLAGS_nfs4trace.o += -I$(src) | 23 | CFLAGS_nfs4trace.o += -I$(src) |
24 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ | 24 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ |
25 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 25 | delegation.o nfs4idmap.o callback.o callback_xdr.o callback_proc.o \ |
26 | nfs4namespace.o nfs4getroot.o nfs4client.o nfs4session.o \ | 26 | nfs4namespace.o nfs4getroot.o nfs4client.o nfs4session.o \ |
27 | dns_resolve.o nfs4trace.o | 27 | dns_resolve.o nfs4trace.o |
28 | nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o | 28 | nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o |
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 1cac3c175d18..d2554fe140a3 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -890,6 +890,7 @@ static struct pnfs_layoutdriver_type blocklayout_type = { | |||
890 | .free_deviceid_node = bl_free_deviceid_node, | 890 | .free_deviceid_node = bl_free_deviceid_node, |
891 | .pg_read_ops = &bl_pg_read_ops, | 891 | .pg_read_ops = &bl_pg_read_ops, |
892 | .pg_write_ops = &bl_pg_write_ops, | 892 | .pg_write_ops = &bl_pg_write_ops, |
893 | .sync = pnfs_generic_sync, | ||
893 | }; | 894 | }; |
894 | 895 | ||
895 | static int __init nfs4blocklayout_init(void) | 896 | static int __init nfs4blocklayout_init(void) |
diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c index 5aed4f98df41..e535599a0719 100644 --- a/fs/nfs/blocklayout/dev.c +++ b/fs/nfs/blocklayout/dev.c | |||
@@ -33,7 +33,7 @@ bl_free_deviceid_node(struct nfs4_deviceid_node *d) | |||
33 | container_of(d, struct pnfs_block_dev, node); | 33 | container_of(d, struct pnfs_block_dev, node); |
34 | 34 | ||
35 | bl_free_device(dev); | 35 | bl_free_device(dev); |
36 | kfree(dev); | 36 | kfree_rcu(dev, node.rcu); |
37 | } | 37 | } |
38 | 38 | ||
39 | static int | 39 | static int |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 351be9205bf8..8d129bb7355a 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -128,7 +128,7 @@ nfs41_callback_svc(void *vrqstp) | |||
128 | if (try_to_freeze()) | 128 | if (try_to_freeze()) |
129 | continue; | 129 | continue; |
130 | 130 | ||
131 | prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_UNINTERRUPTIBLE); | 131 | prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); |
132 | spin_lock_bh(&serv->sv_cb_lock); | 132 | spin_lock_bh(&serv->sv_cb_lock); |
133 | if (!list_empty(&serv->sv_cb_list)) { | 133 | if (!list_empty(&serv->sv_cb_list)) { |
134 | req = list_first_entry(&serv->sv_cb_list, | 134 | req = list_first_entry(&serv->sv_cb_list, |
@@ -142,10 +142,10 @@ nfs41_callback_svc(void *vrqstp) | |||
142 | error); | 142 | error); |
143 | } else { | 143 | } else { |
144 | spin_unlock_bh(&serv->sv_cb_lock); | 144 | spin_unlock_bh(&serv->sv_cb_lock); |
145 | /* schedule_timeout to game the hung task watchdog */ | 145 | schedule(); |
146 | schedule_timeout(60 * HZ); | ||
147 | finish_wait(&serv->sv_cb_waitq, &wq); | 146 | finish_wait(&serv->sv_cb_waitq, &wq); |
148 | } | 147 | } |
148 | flush_signals(current); | ||
149 | } | 149 | } |
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 19874151e95c..892aefff3630 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/lockd/bind.h> | 31 | #include <linux/lockd/bind.h> |
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include <linux/mount.h> | 33 | #include <linux/mount.h> |
34 | #include <linux/nfs_idmap.h> | ||
35 | #include <linux/vfs.h> | 34 | #include <linux/vfs.h> |
36 | #include <linux/inet.h> | 35 | #include <linux/inet.h> |
37 | #include <linux/in6.h> | 36 | #include <linux/in6.h> |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 08c624448750..029d688a969f 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -378,7 +378,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
378 | if (freeme == NULL) | 378 | if (freeme == NULL) |
379 | goto out; | 379 | goto out; |
380 | } | 380 | } |
381 | list_add_rcu(&delegation->super_list, &server->delegations); | 381 | list_add_tail_rcu(&delegation->super_list, &server->delegations); |
382 | rcu_assign_pointer(nfsi->delegation, delegation); | 382 | rcu_assign_pointer(nfsi->delegation, delegation); |
383 | delegation = NULL; | 383 | delegation = NULL; |
384 | 384 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c19e16f0b2d0..a00ba92acccc 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -544,6 +544,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
544 | if (scratch == NULL) | 544 | if (scratch == NULL) |
545 | return -ENOMEM; | 545 | return -ENOMEM; |
546 | 546 | ||
547 | if (buflen == 0) | ||
548 | goto out_nopages; | ||
549 | |||
547 | xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen); | 550 | xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen); |
548 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); | 551 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); |
549 | 552 | ||
@@ -565,6 +568,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
565 | break; | 568 | break; |
566 | } while (!entry->eof); | 569 | } while (!entry->eof); |
567 | 570 | ||
571 | out_nopages: | ||
568 | if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { | 572 | if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { |
569 | array = nfs_readdir_get_array(page); | 573 | array = nfs_readdir_get_array(page); |
570 | if (!IS_ERR(array)) { | 574 | if (!IS_ERR(array)) { |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index e907c8cf732e..eeb52b434e6f 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -129,22 +129,25 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr) | |||
129 | int i; | 129 | int i; |
130 | ssize_t count; | 130 | ssize_t count; |
131 | 131 | ||
132 | WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count); | 132 | if (dreq->mirror_count == 1) { |
133 | 133 | dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes; | |
134 | count = dreq->mirrors[hdr->pgio_mirror_idx].count; | 134 | dreq->count += hdr->good_bytes; |
135 | if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) { | 135 | } else { |
136 | count = hdr->io_start + hdr->good_bytes - dreq->io_start; | 136 | /* mirrored writes */ |
137 | dreq->mirrors[hdr->pgio_mirror_idx].count = count; | 137 | count = dreq->mirrors[hdr->pgio_mirror_idx].count; |
138 | } | 138 | if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) { |
139 | 139 | count = hdr->io_start + hdr->good_bytes - dreq->io_start; | |
140 | /* update the dreq->count by finding the minimum agreed count from all | 140 | dreq->mirrors[hdr->pgio_mirror_idx].count = count; |
141 | * mirrors */ | 141 | } |
142 | count = dreq->mirrors[0].count; | 142 | /* update the dreq->count by finding the minimum agreed count from all |
143 | * mirrors */ | ||
144 | count = dreq->mirrors[0].count; | ||
143 | 145 | ||
144 | for (i = 1; i < dreq->mirror_count; i++) | 146 | for (i = 1; i < dreq->mirror_count; i++) |
145 | count = min(count, dreq->mirrors[i].count); | 147 | count = min(count, dreq->mirrors[i].count); |
146 | 148 | ||
147 | dreq->count = count; | 149 | dreq->count = count; |
150 | } | ||
148 | } | 151 | } |
149 | 152 | ||
150 | /* | 153 | /* |
@@ -259,18 +262,11 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t | |||
259 | if (!IS_SWAPFILE(inode)) | 262 | if (!IS_SWAPFILE(inode)) |
260 | return 0; | 263 | return 0; |
261 | 264 | ||
262 | #ifndef CONFIG_NFS_SWAP | ||
263 | dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n", | ||
264 | iocb->ki_filp, (long long) pos, iter->nr_segs); | ||
265 | |||
266 | return -EINVAL; | ||
267 | #else | ||
268 | VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE); | 265 | VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE); |
269 | 266 | ||
270 | if (rw == READ) | 267 | if (rw == READ) |
271 | return nfs_file_direct_read(iocb, iter, pos); | 268 | return nfs_file_direct_read(iocb, iter, pos); |
272 | return nfs_file_direct_write(iocb, iter, pos); | 269 | return nfs_file_direct_write(iocb, iter, pos); |
273 | #endif /* CONFIG_NFS_SWAP */ | ||
274 | } | 270 | } |
275 | 271 | ||
276 | static void nfs_direct_release_pages(struct page **pages, unsigned int npages) | 272 | static void nfs_direct_release_pages(struct page **pages, unsigned int npages) |
@@ -1041,6 +1037,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, | |||
1041 | if (i_size_read(inode) < iocb->ki_pos) | 1037 | if (i_size_read(inode) < iocb->ki_pos) |
1042 | i_size_write(inode, iocb->ki_pos); | 1038 | i_size_write(inode, iocb->ki_pos); |
1043 | spin_unlock(&inode->i_lock); | 1039 | spin_unlock(&inode->i_lock); |
1040 | generic_write_sync(file, pos, result); | ||
1044 | } | 1041 | } |
1045 | } | 1042 | } |
1046 | nfs_direct_req_release(dreq); | 1043 | nfs_direct_req_release(dreq); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index e679d24c39d3..28228f381266 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -281,6 +281,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
281 | 281 | ||
282 | trace_nfs_fsync_enter(inode); | 282 | trace_nfs_fsync_enter(inode); |
283 | 283 | ||
284 | nfs_inode_dio_wait(inode); | ||
284 | do { | 285 | do { |
285 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 286 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
286 | if (ret != 0) | 287 | if (ret != 0) |
@@ -780,7 +781,7 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | |||
780 | * Flush all pending writes before doing anything | 781 | * Flush all pending writes before doing anything |
781 | * with locks.. | 782 | * with locks.. |
782 | */ | 783 | */ |
783 | nfs_sync_mapping(filp->f_mapping); | 784 | vfs_fsync(filp, 0); |
784 | 785 | ||
785 | l_ctx = nfs_get_lock_context(nfs_file_open_context(filp)); | 786 | l_ctx = nfs_get_lock_context(nfs_file_open_context(filp)); |
786 | if (!IS_ERR(l_ctx)) { | 787 | if (!IS_ERR(l_ctx)) { |
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 91e88a7ecef0..a46bf6de9ce4 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -258,7 +258,8 @@ filelayout_set_layoutcommit(struct nfs_pgio_header *hdr) | |||
258 | hdr->res.verf->committed != NFS_DATA_SYNC) | 258 | hdr->res.verf->committed != NFS_DATA_SYNC) |
259 | return; | 259 | return; |
260 | 260 | ||
261 | pnfs_set_layoutcommit(hdr); | 261 | pnfs_set_layoutcommit(hdr->inode, hdr->lseg, |
262 | hdr->mds_offset + hdr->res.count); | ||
262 | dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, | 263 | dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, |
263 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); | 264 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); |
264 | } | 265 | } |
@@ -373,7 +374,7 @@ static int filelayout_commit_done_cb(struct rpc_task *task, | |||
373 | } | 374 | } |
374 | 375 | ||
375 | if (data->verf.committed == NFS_UNSTABLE) | 376 | if (data->verf.committed == NFS_UNSTABLE) |
376 | pnfs_commit_set_layoutcommit(data); | 377 | pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb); |
377 | 378 | ||
378 | return 0; | 379 | return 0; |
379 | } | 380 | } |
@@ -1086,7 +1087,7 @@ filelayout_alloc_deviceid_node(struct nfs_server *server, | |||
1086 | } | 1087 | } |
1087 | 1088 | ||
1088 | static void | 1089 | static void |
1089 | filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d) | 1090 | filelayout_free_deviceid_node(struct nfs4_deviceid_node *d) |
1090 | { | 1091 | { |
1091 | nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node)); | 1092 | nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node)); |
1092 | } | 1093 | } |
@@ -1137,7 +1138,8 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
1137 | .read_pagelist = filelayout_read_pagelist, | 1138 | .read_pagelist = filelayout_read_pagelist, |
1138 | .write_pagelist = filelayout_write_pagelist, | 1139 | .write_pagelist = filelayout_write_pagelist, |
1139 | .alloc_deviceid_node = filelayout_alloc_deviceid_node, | 1140 | .alloc_deviceid_node = filelayout_alloc_deviceid_node, |
1140 | .free_deviceid_node = filelayout_free_deveiceid_node, | 1141 | .free_deviceid_node = filelayout_free_deviceid_node, |
1142 | .sync = pnfs_nfs_generic_sync, | ||
1141 | }; | 1143 | }; |
1142 | 1144 | ||
1143 | static int __init nfs4filelayout_init(void) | 1145 | static int __init nfs4filelayout_init(void) |
diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c index 4f372e224603..4946ef40ba87 100644 --- a/fs/nfs/filelayout/filelayoutdev.c +++ b/fs/nfs/filelayout/filelayoutdev.c | |||
@@ -55,7 +55,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | |||
55 | nfs4_pnfs_ds_put(ds); | 55 | nfs4_pnfs_ds_put(ds); |
56 | } | 56 | } |
57 | kfree(dsaddr->stripe_indices); | 57 | kfree(dsaddr->stripe_indices); |
58 | kfree(dsaddr); | 58 | kfree_rcu(dsaddr, id_node.rcu); |
59 | } | 59 | } |
60 | 60 | ||
61 | /* Decode opaque device data and return the result */ | 61 | /* Decode opaque device data and return the result */ |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 315cc68945b9..7d05089e52d6 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -11,10 +11,10 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | 12 | ||
13 | #include <linux/sunrpc/metrics.h> | 13 | #include <linux/sunrpc/metrics.h> |
14 | #include <linux/nfs_idmap.h> | ||
15 | 14 | ||
16 | #include "flexfilelayout.h" | 15 | #include "flexfilelayout.h" |
17 | #include "../nfs4session.h" | 16 | #include "../nfs4session.h" |
17 | #include "../nfs4idmap.h" | ||
18 | #include "../internal.h" | 18 | #include "../internal.h" |
19 | #include "../delegation.h" | 19 | #include "../delegation.h" |
20 | #include "../nfs4trace.h" | 20 | #include "../nfs4trace.h" |
@@ -891,7 +891,8 @@ static int ff_layout_read_done_cb(struct rpc_task *task, | |||
891 | static void | 891 | static void |
892 | ff_layout_set_layoutcommit(struct nfs_pgio_header *hdr) | 892 | ff_layout_set_layoutcommit(struct nfs_pgio_header *hdr) |
893 | { | 893 | { |
894 | pnfs_set_layoutcommit(hdr); | 894 | pnfs_set_layoutcommit(hdr->inode, hdr->lseg, |
895 | hdr->mds_offset + hdr->res.count); | ||
895 | dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, | 896 | dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino, |
896 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); | 897 | (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb); |
897 | } | 898 | } |
@@ -1074,7 +1075,7 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, | |||
1074 | } | 1075 | } |
1075 | 1076 | ||
1076 | if (data->verf.committed == NFS_UNSTABLE) | 1077 | if (data->verf.committed == NFS_UNSTABLE) |
1077 | pnfs_commit_set_layoutcommit(data); | 1078 | pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb); |
1078 | 1079 | ||
1079 | return 0; | 1080 | return 0; |
1080 | } | 1081 | } |
@@ -1414,7 +1415,7 @@ ff_layout_get_ds_info(struct inode *inode) | |||
1414 | } | 1415 | } |
1415 | 1416 | ||
1416 | static void | 1417 | static void |
1417 | ff_layout_free_deveiceid_node(struct nfs4_deviceid_node *d) | 1418 | ff_layout_free_deviceid_node(struct nfs4_deviceid_node *d) |
1418 | { | 1419 | { |
1419 | nfs4_ff_layout_free_deviceid(container_of(d, struct nfs4_ff_layout_ds, | 1420 | nfs4_ff_layout_free_deviceid(container_of(d, struct nfs4_ff_layout_ds, |
1420 | id_node)); | 1421 | id_node)); |
@@ -1498,7 +1499,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = { | |||
1498 | .pg_read_ops = &ff_layout_pg_read_ops, | 1499 | .pg_read_ops = &ff_layout_pg_read_ops, |
1499 | .pg_write_ops = &ff_layout_pg_write_ops, | 1500 | .pg_write_ops = &ff_layout_pg_write_ops, |
1500 | .get_ds_info = ff_layout_get_ds_info, | 1501 | .get_ds_info = ff_layout_get_ds_info, |
1501 | .free_deviceid_node = ff_layout_free_deveiceid_node, | 1502 | .free_deviceid_node = ff_layout_free_deviceid_node, |
1502 | .mark_request_commit = pnfs_layout_mark_request_commit, | 1503 | .mark_request_commit = pnfs_layout_mark_request_commit, |
1503 | .clear_request_commit = pnfs_generic_clear_request_commit, | 1504 | .clear_request_commit = pnfs_generic_clear_request_commit, |
1504 | .scan_commit_lists = pnfs_generic_scan_commit_lists, | 1505 | .scan_commit_lists = pnfs_generic_scan_commit_lists, |
@@ -1508,6 +1509,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = { | |||
1508 | .write_pagelist = ff_layout_write_pagelist, | 1509 | .write_pagelist = ff_layout_write_pagelist, |
1509 | .alloc_deviceid_node = ff_layout_alloc_deviceid_node, | 1510 | .alloc_deviceid_node = ff_layout_alloc_deviceid_node, |
1510 | .encode_layoutreturn = ff_layout_encode_layoutreturn, | 1511 | .encode_layoutreturn = ff_layout_encode_layoutreturn, |
1512 | .sync = pnfs_nfs_generic_sync, | ||
1511 | }; | 1513 | }; |
1512 | 1514 | ||
1513 | static int __init nfs4flexfilelayout_init(void) | 1515 | static int __init nfs4flexfilelayout_init(void) |
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index e2c01f204a95..77a2d026aa12 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c | |||
@@ -30,7 +30,7 @@ void nfs4_ff_layout_free_deviceid(struct nfs4_ff_layout_ds *mirror_ds) | |||
30 | { | 30 | { |
31 | nfs4_print_deviceid(&mirror_ds->id_node.deviceid); | 31 | nfs4_print_deviceid(&mirror_ds->id_node.deviceid); |
32 | nfs4_pnfs_ds_put(mirror_ds->ds); | 32 | nfs4_pnfs_ds_put(mirror_ds->ds); |
33 | kfree(mirror_ds); | 33 | kfree_rcu(mirror_ds, id_node.rcu); |
34 | } | 34 | } |
35 | 35 | ||
36 | /* Decode opaque device data and construct new_ds using it */ | 36 | /* Decode opaque device data and construct new_ds using it */ |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d42dff6d5e98..8a464684e8c8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -133,6 +133,13 @@ void nfs_evict_inode(struct inode *inode) | |||
133 | nfs_clear_inode(inode); | 133 | nfs_clear_inode(inode); |
134 | } | 134 | } |
135 | 135 | ||
136 | int nfs_sync_inode(struct inode *inode) | ||
137 | { | ||
138 | nfs_inode_dio_wait(inode); | ||
139 | return nfs_wb_all(inode); | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(nfs_sync_inode); | ||
142 | |||
136 | /** | 143 | /** |
137 | * nfs_sync_mapping - helper to flush all mmapped dirty data to disk | 144 | * nfs_sync_mapping - helper to flush all mmapped dirty data to disk |
138 | */ | 145 | */ |
@@ -192,7 +199,6 @@ void nfs_zap_caches(struct inode *inode) | |||
192 | nfs_zap_caches_locked(inode); | 199 | nfs_zap_caches_locked(inode); |
193 | spin_unlock(&inode->i_lock); | 200 | spin_unlock(&inode->i_lock); |
194 | } | 201 | } |
195 | EXPORT_SYMBOL_GPL(nfs_zap_caches); | ||
196 | 202 | ||
197 | void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) | 203 | void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) |
198 | { | 204 | { |
@@ -525,10 +531,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
525 | trace_nfs_setattr_enter(inode); | 531 | trace_nfs_setattr_enter(inode); |
526 | 532 | ||
527 | /* Write all dirty data */ | 533 | /* Write all dirty data */ |
528 | if (S_ISREG(inode->i_mode)) { | 534 | if (S_ISREG(inode->i_mode)) |
529 | nfs_inode_dio_wait(inode); | 535 | nfs_sync_inode(inode); |
530 | nfs_wb_all(inode); | ||
531 | } | ||
532 | 536 | ||
533 | fattr = nfs_alloc_fattr(); | 537 | fattr = nfs_alloc_fattr(); |
534 | if (fattr == NULL) | 538 | if (fattr == NULL) |
@@ -644,8 +648,9 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
644 | trace_nfs_getattr_enter(inode); | 648 | trace_nfs_getattr_enter(inode); |
645 | /* Flush out writes to the server in order to update c/mtime. */ | 649 | /* Flush out writes to the server in order to update c/mtime. */ |
646 | if (S_ISREG(inode->i_mode)) { | 650 | if (S_ISREG(inode->i_mode)) { |
647 | nfs_inode_dio_wait(inode); | 651 | mutex_lock(&inode->i_mutex); |
648 | err = filemap_write_and_wait(inode->i_mapping); | 652 | err = nfs_sync_inode(inode); |
653 | mutex_unlock(&inode->i_mutex); | ||
649 | if (err) | 654 | if (err) |
650 | goto out; | 655 | goto out; |
651 | } | 656 | } |
@@ -1588,6 +1593,19 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1588 | } | 1593 | } |
1589 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc); | 1594 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc); |
1590 | 1595 | ||
1596 | |||
1597 | static inline bool nfs_fileid_valid(struct nfs_inode *nfsi, | ||
1598 | struct nfs_fattr *fattr) | ||
1599 | { | ||
1600 | bool ret1 = true, ret2 = true; | ||
1601 | |||
1602 | if (fattr->valid & NFS_ATTR_FATTR_FILEID) | ||
1603 | ret1 = (nfsi->fileid == fattr->fileid); | ||
1604 | if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | ||
1605 | ret2 = (nfsi->fileid == fattr->mounted_on_fileid); | ||
1606 | return ret1 || ret2; | ||
1607 | } | ||
1608 | |||
1591 | /* | 1609 | /* |
1592 | * Many nfs protocol calls return the new file attributes after | 1610 | * Many nfs protocol calls return the new file attributes after |
1593 | * an operation. Here we update the inode to reflect the state | 1611 | * an operation. Here we update the inode to reflect the state |
@@ -1614,7 +1632,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1614 | nfs_display_fhandle_hash(NFS_FH(inode)), | 1632 | nfs_display_fhandle_hash(NFS_FH(inode)), |
1615 | atomic_read(&inode->i_count), fattr->valid); | 1633 | atomic_read(&inode->i_count), fattr->valid); |
1616 | 1634 | ||
1617 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) { | 1635 | if (!nfs_fileid_valid(nfsi, fattr)) { |
1618 | printk(KERN_ERR "NFS: server %s error: fileid changed\n" | 1636 | printk(KERN_ERR "NFS: server %s error: fileid changed\n" |
1619 | "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", | 1637 | "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", |
1620 | NFS_SERVER(inode)->nfs_client->cl_hostname, | 1638 | NFS_SERVER(inode)->nfs_client->cl_hostname, |
@@ -1819,7 +1837,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1819 | struct inode *nfs_alloc_inode(struct super_block *sb) | 1837 | struct inode *nfs_alloc_inode(struct super_block *sb) |
1820 | { | 1838 | { |
1821 | struct nfs_inode *nfsi; | 1839 | struct nfs_inode *nfsi; |
1822 | nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, GFP_KERNEL); | 1840 | nfsi = kmem_cache_alloc(nfs_inode_cachep, GFP_KERNEL); |
1823 | if (!nfsi) | 1841 | if (!nfsi) |
1824 | return NULL; | 1842 | return NULL; |
1825 | nfsi->flags = 0UL; | 1843 | nfsi->flags = 0UL; |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index cb170722769c..3a9e75235f30 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -36,13 +36,16 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, | |||
36 | loff_t offset, loff_t len) | 36 | loff_t offset, loff_t len) |
37 | { | 37 | { |
38 | struct inode *inode = file_inode(filep); | 38 | struct inode *inode = file_inode(filep); |
39 | struct nfs_server *server = NFS_SERVER(inode); | ||
39 | struct nfs42_falloc_args args = { | 40 | struct nfs42_falloc_args args = { |
40 | .falloc_fh = NFS_FH(inode), | 41 | .falloc_fh = NFS_FH(inode), |
41 | .falloc_offset = offset, | 42 | .falloc_offset = offset, |
42 | .falloc_length = len, | 43 | .falloc_length = len, |
44 | .falloc_bitmask = server->cache_consistency_bitmask, | ||
45 | }; | ||
46 | struct nfs42_falloc_res res = { | ||
47 | .falloc_server = server, | ||
43 | }; | 48 | }; |
44 | struct nfs42_falloc_res res; | ||
45 | struct nfs_server *server = NFS_SERVER(inode); | ||
46 | int status; | 49 | int status; |
47 | 50 | ||
48 | msg->rpc_argp = &args; | 51 | msg->rpc_argp = &args; |
@@ -52,8 +55,17 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, | |||
52 | if (status) | 55 | if (status) |
53 | return status; | 56 | return status; |
54 | 57 | ||
55 | return nfs4_call_sync(server->client, server, msg, | 58 | res.falloc_fattr = nfs_alloc_fattr(); |
56 | &args.seq_args, &res.seq_res, 0); | 59 | if (!res.falloc_fattr) |
60 | return -ENOMEM; | ||
61 | |||
62 | status = nfs4_call_sync(server->client, server, msg, | ||
63 | &args.seq_args, &res.seq_res, 0); | ||
64 | if (status == 0) | ||
65 | status = nfs_post_op_update_inode(inode, res.falloc_fattr); | ||
66 | |||
67 | kfree(res.falloc_fattr); | ||
68 | return status; | ||
57 | } | 69 | } |
58 | 70 | ||
59 | static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, | 71 | static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, |
@@ -84,9 +96,13 @@ int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len) | |||
84 | if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE)) | 96 | if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE)) |
85 | return -EOPNOTSUPP; | 97 | return -EOPNOTSUPP; |
86 | 98 | ||
99 | mutex_lock(&inode->i_mutex); | ||
100 | |||
87 | err = nfs42_proc_fallocate(&msg, filep, offset, len); | 101 | err = nfs42_proc_fallocate(&msg, filep, offset, len); |
88 | if (err == -EOPNOTSUPP) | 102 | if (err == -EOPNOTSUPP) |
89 | NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE; | 103 | NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE; |
104 | |||
105 | mutex_unlock(&inode->i_mutex); | ||
90 | return err; | 106 | return err; |
91 | } | 107 | } |
92 | 108 | ||
@@ -101,9 +117,16 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) | |||
101 | if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE)) | 117 | if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE)) |
102 | return -EOPNOTSUPP; | 118 | return -EOPNOTSUPP; |
103 | 119 | ||
120 | nfs_wb_all(inode); | ||
121 | mutex_lock(&inode->i_mutex); | ||
122 | |||
104 | err = nfs42_proc_fallocate(&msg, filep, offset, len); | 123 | err = nfs42_proc_fallocate(&msg, filep, offset, len); |
124 | if (err == 0) | ||
125 | truncate_pagecache_range(inode, offset, (offset + len) -1); | ||
105 | if (err == -EOPNOTSUPP) | 126 | if (err == -EOPNOTSUPP) |
106 | NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; | 127 | NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; |
128 | |||
129 | mutex_unlock(&inode->i_mutex); | ||
107 | return err; | 130 | return err; |
108 | } | 131 | } |
109 | 132 | ||
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index 038a7e1521fa..1a25b27248f2 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c | |||
@@ -25,16 +25,20 @@ | |||
25 | 25 | ||
26 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ | 26 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ |
27 | encode_putfh_maxsz + \ | 27 | encode_putfh_maxsz + \ |
28 | encode_allocate_maxsz) | 28 | encode_allocate_maxsz + \ |
29 | encode_getattr_maxsz) | ||
29 | #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ | 30 | #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ |
30 | decode_putfh_maxsz + \ | 31 | decode_putfh_maxsz + \ |
31 | decode_allocate_maxsz) | 32 | decode_allocate_maxsz + \ |
33 | decode_getattr_maxsz) | ||
32 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ | 34 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ |
33 | encode_putfh_maxsz + \ | 35 | encode_putfh_maxsz + \ |
34 | encode_deallocate_maxsz) | 36 | encode_deallocate_maxsz + \ |
37 | encode_getattr_maxsz) | ||
35 | #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ | 38 | #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ |
36 | decode_putfh_maxsz + \ | 39 | decode_putfh_maxsz + \ |
37 | decode_deallocate_maxsz) | 40 | decode_deallocate_maxsz + \ |
41 | decode_getattr_maxsz) | ||
38 | #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ | 42 | #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ |
39 | encode_putfh_maxsz + \ | 43 | encode_putfh_maxsz + \ |
40 | encode_seek_maxsz) | 44 | encode_seek_maxsz) |
@@ -92,6 +96,7 @@ static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, | |||
92 | encode_sequence(xdr, &args->seq_args, &hdr); | 96 | encode_sequence(xdr, &args->seq_args, &hdr); |
93 | encode_putfh(xdr, args->falloc_fh, &hdr); | 97 | encode_putfh(xdr, args->falloc_fh, &hdr); |
94 | encode_allocate(xdr, args, &hdr); | 98 | encode_allocate(xdr, args, &hdr); |
99 | encode_getfattr(xdr, args->falloc_bitmask, &hdr); | ||
95 | encode_nops(&hdr); | 100 | encode_nops(&hdr); |
96 | } | 101 | } |
97 | 102 | ||
@@ -110,6 +115,7 @@ static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, | |||
110 | encode_sequence(xdr, &args->seq_args, &hdr); | 115 | encode_sequence(xdr, &args->seq_args, &hdr); |
111 | encode_putfh(xdr, args->falloc_fh, &hdr); | 116 | encode_putfh(xdr, args->falloc_fh, &hdr); |
112 | encode_deallocate(xdr, args, &hdr); | 117 | encode_deallocate(xdr, args, &hdr); |
118 | encode_getfattr(xdr, args->falloc_bitmask, &hdr); | ||
113 | encode_nops(&hdr); | 119 | encode_nops(&hdr); |
114 | } | 120 | } |
115 | 121 | ||
@@ -183,6 +189,9 @@ static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, | |||
183 | if (status) | 189 | if (status) |
184 | goto out; | 190 | goto out; |
185 | status = decode_allocate(xdr, res); | 191 | status = decode_allocate(xdr, res); |
192 | if (status) | ||
193 | goto out; | ||
194 | decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); | ||
186 | out: | 195 | out: |
187 | return status; | 196 | return status; |
188 | } | 197 | } |
@@ -207,6 +216,9 @@ static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, | |||
207 | if (status) | 216 | if (status) |
208 | goto out; | 217 | goto out; |
209 | status = decode_deallocate(xdr, res); | 218 | status = decode_deallocate(xdr, res); |
219 | if (status) | ||
220 | goto out; | ||
221 | decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); | ||
210 | out: | 222 | out: |
211 | return status; | 223 | return status; |
212 | } | 224 | } |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 86d6214ea022..43ca5a7ac1da 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -4,7 +4,6 @@ | |||
4 | */ | 4 | */ |
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/nfs_fs.h> | 6 | #include <linux/nfs_fs.h> |
7 | #include <linux/nfs_idmap.h> | ||
8 | #include <linux/nfs_mount.h> | 7 | #include <linux/nfs_mount.h> |
9 | #include <linux/sunrpc/addr.h> | 8 | #include <linux/sunrpc/addr.h> |
10 | #include <linux/sunrpc/auth.h> | 9 | #include <linux/sunrpc/auth.h> |
@@ -15,6 +14,7 @@ | |||
15 | #include "callback.h" | 14 | #include "callback.h" |
16 | #include "delegation.h" | 15 | #include "delegation.h" |
17 | #include "nfs4session.h" | 16 | #include "nfs4session.h" |
17 | #include "nfs4idmap.h" | ||
18 | #include "pnfs.h" | 18 | #include "pnfs.h" |
19 | #include "netns.h" | 19 | #include "netns.h" |
20 | 20 | ||
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 8b46389c4c5b..cb3c7879e59f 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include "fscache.h" | 10 | #include "fscache.h" |
11 | #include "pnfs.h" | 11 | #include "pnfs.h" |
12 | 12 | ||
13 | #include "nfstrace.h" | ||
14 | |||
13 | #ifdef CONFIG_NFS_V4_2 | 15 | #ifdef CONFIG_NFS_V4_2 |
14 | #include "nfs42.h" | 16 | #include "nfs42.h" |
15 | #endif | 17 | #endif |
@@ -57,7 +59,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) | |||
57 | if (openflags & O_TRUNC) { | 59 | if (openflags & O_TRUNC) { |
58 | attr.ia_valid |= ATTR_SIZE; | 60 | attr.ia_valid |= ATTR_SIZE; |
59 | attr.ia_size = 0; | 61 | attr.ia_size = 0; |
60 | nfs_wb_all(inode); | 62 | nfs_sync_inode(inode); |
61 | } | 63 | } |
62 | 64 | ||
63 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened); | 65 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened); |
@@ -100,6 +102,9 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
100 | int ret; | 102 | int ret; |
101 | struct inode *inode = file_inode(file); | 103 | struct inode *inode = file_inode(file); |
102 | 104 | ||
105 | trace_nfs_fsync_enter(inode); | ||
106 | |||
107 | nfs_inode_dio_wait(inode); | ||
103 | do { | 108 | do { |
104 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 109 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
105 | if (ret != 0) | 110 | if (ret != 0) |
@@ -107,7 +112,7 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
107 | mutex_lock(&inode->i_mutex); | 112 | mutex_lock(&inode->i_mutex); |
108 | ret = nfs_file_fsync_commit(file, start, end, datasync); | 113 | ret = nfs_file_fsync_commit(file, start, end, datasync); |
109 | if (!ret) | 114 | if (!ret) |
110 | ret = pnfs_layoutcommit_inode(inode, true); | 115 | ret = pnfs_sync_inode(inode, !!datasync); |
111 | mutex_unlock(&inode->i_mutex); | 116 | mutex_unlock(&inode->i_mutex); |
112 | /* | 117 | /* |
113 | * If nfs_file_fsync_commit detected a server reboot, then | 118 | * If nfs_file_fsync_commit detected a server reboot, then |
@@ -118,6 +123,7 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
118 | end = LLONG_MAX; | 123 | end = LLONG_MAX; |
119 | } while (ret == -EAGAIN); | 124 | } while (ret == -EAGAIN); |
120 | 125 | ||
126 | trace_nfs_fsync_exit(inode, ret); | ||
121 | return ret; | 127 | return ret; |
122 | } | 128 | } |
123 | 129 | ||
@@ -152,15 +158,9 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t | |||
152 | if (ret < 0) | 158 | if (ret < 0) |
153 | return ret; | 159 | return ret; |
154 | 160 | ||
155 | mutex_lock(&inode->i_mutex); | ||
156 | if (mode & FALLOC_FL_PUNCH_HOLE) | 161 | if (mode & FALLOC_FL_PUNCH_HOLE) |
157 | ret = nfs42_proc_deallocate(filep, offset, len); | 162 | return nfs42_proc_deallocate(filep, offset, len); |
158 | else | 163 | return nfs42_proc_allocate(filep, offset, len); |
159 | ret = nfs42_proc_allocate(filep, offset, len); | ||
160 | mutex_unlock(&inode->i_mutex); | ||
161 | |||
162 | nfs_zap_caches(inode); | ||
163 | return ret; | ||
164 | } | 164 | } |
165 | #endif /* CONFIG_NFS_V4_2 */ | 165 | #endif /* CONFIG_NFS_V4_2 */ |
166 | 166 | ||
diff --git a/fs/nfs/idmap.c b/fs/nfs/nfs4idmap.c index 857e2a99acc8..2e1737c40a29 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/nfs4idmap.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/parser.h> | 37 | #include <linux/parser.h> |
38 | #include <linux/fs.h> | 38 | #include <linux/fs.h> |
39 | #include <linux/nfs_idmap.h> | ||
40 | #include <net/net_namespace.h> | 39 | #include <net/net_namespace.h> |
41 | #include <linux/sunrpc/rpc_pipe_fs.h> | 40 | #include <linux/sunrpc/rpc_pipe_fs.h> |
42 | #include <linux/nfs_fs.h> | 41 | #include <linux/nfs_fs.h> |
@@ -49,6 +48,7 @@ | |||
49 | 48 | ||
50 | #include "internal.h" | 49 | #include "internal.h" |
51 | #include "netns.h" | 50 | #include "netns.h" |
51 | #include "nfs4idmap.h" | ||
52 | #include "nfs4trace.h" | 52 | #include "nfs4trace.h" |
53 | 53 | ||
54 | #define NFS_UINT_MAXLEN 11 | 54 | #define NFS_UINT_MAXLEN 11 |
diff --git a/include/linux/nfs_idmap.h b/fs/nfs/nfs4idmap.h index 333844e38f66..de44d7330ab3 100644 --- a/include/linux/nfs_idmap.h +++ b/fs/nfs/nfs4idmap.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * include/linux/nfs_idmap.h | 2 | * fs/nfs/nfs4idmap.h |
3 | * | 3 | * |
4 | * UID and GID to name mapping for clients. | 4 | * UID and GID to name mapping for clients. |
5 | * | 5 | * |
@@ -46,19 +46,8 @@ struct nfs_server; | |||
46 | struct nfs_fattr; | 46 | struct nfs_fattr; |
47 | struct nfs4_string; | 47 | struct nfs4_string; |
48 | 48 | ||
49 | #if IS_ENABLED(CONFIG_NFS_V4) | ||
50 | int nfs_idmap_init(void); | 49 | int nfs_idmap_init(void); |
51 | void nfs_idmap_quit(void); | 50 | void nfs_idmap_quit(void); |
52 | #else | ||
53 | static inline int nfs_idmap_init(void) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static inline void nfs_idmap_quit(void) | ||
59 | {} | ||
60 | #endif | ||
61 | |||
62 | int nfs_idmap_new(struct nfs_client *); | 51 | int nfs_idmap_new(struct nfs_client *); |
63 | void nfs_idmap_delete(struct nfs_client *); | 52 | void nfs_idmap_delete(struct nfs_client *); |
64 | 53 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 627f37c44456..addf17d25bea 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <linux/namei.h> | 51 | #include <linux/namei.h> |
52 | #include <linux/mount.h> | 52 | #include <linux/mount.h> |
53 | #include <linux/module.h> | 53 | #include <linux/module.h> |
54 | #include <linux/nfs_idmap.h> | ||
55 | #include <linux/xattr.h> | 54 | #include <linux/xattr.h> |
56 | #include <linux/utsname.h> | 55 | #include <linux/utsname.h> |
57 | #include <linux/freezer.h> | 56 | #include <linux/freezer.h> |
@@ -63,6 +62,7 @@ | |||
63 | #include "callback.h" | 62 | #include "callback.h" |
64 | #include "pnfs.h" | 63 | #include "pnfs.h" |
65 | #include "netns.h" | 64 | #include "netns.h" |
65 | #include "nfs4idmap.h" | ||
66 | #include "nfs4session.h" | 66 | #include "nfs4session.h" |
67 | #include "fscache.h" | 67 | #include "fscache.h" |
68 | 68 | ||
@@ -185,7 +185,8 @@ const u32 nfs4_fattr_bitmap[3] = { | |||
185 | | FATTR4_WORD1_SPACE_USED | 185 | | FATTR4_WORD1_SPACE_USED |
186 | | FATTR4_WORD1_TIME_ACCESS | 186 | | FATTR4_WORD1_TIME_ACCESS |
187 | | FATTR4_WORD1_TIME_METADATA | 187 | | FATTR4_WORD1_TIME_METADATA |
188 | | FATTR4_WORD1_TIME_MODIFY, | 188 | | FATTR4_WORD1_TIME_MODIFY |
189 | | FATTR4_WORD1_MOUNTED_ON_FILEID, | ||
189 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 190 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
190 | FATTR4_WORD2_SECURITY_LABEL | 191 | FATTR4_WORD2_SECURITY_LABEL |
191 | #endif | 192 | #endif |
@@ -3095,16 +3096,13 @@ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3095 | struct nfs_fsinfo *info, | 3096 | struct nfs_fsinfo *info, |
3096 | bool auth_probe) | 3097 | bool auth_probe) |
3097 | { | 3098 | { |
3098 | int status; | 3099 | int status = 0; |
3099 | 3100 | ||
3100 | switch (auth_probe) { | 3101 | if (!auth_probe) |
3101 | case false: | ||
3102 | status = nfs4_lookup_root(server, fhandle, info); | 3102 | status = nfs4_lookup_root(server, fhandle, info); |
3103 | if (status != -NFS4ERR_WRONGSEC) | 3103 | |
3104 | break; | 3104 | if (auth_probe || status == NFS4ERR_WRONGSEC) |
3105 | default: | ||
3106 | status = nfs4_do_find_root_sec(server, fhandle, info); | 3105 | status = nfs4_do_find_root_sec(server, fhandle, info); |
3107 | } | ||
3108 | 3106 | ||
3109 | if (status == 0) | 3107 | if (status == 0) |
3110 | status = nfs4_server_capabilities(server, fhandle); | 3108 | status = nfs4_server_capabilities(server, fhandle); |
@@ -7944,6 +7942,8 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, | |||
7944 | { | 7942 | { |
7945 | struct nfs4_getdeviceinfo_args args = { | 7943 | struct nfs4_getdeviceinfo_args args = { |
7946 | .pdev = pdev, | 7944 | .pdev = pdev, |
7945 | .notify_types = NOTIFY_DEVICEID4_CHANGE | | ||
7946 | NOTIFY_DEVICEID4_DELETE, | ||
7947 | }; | 7947 | }; |
7948 | struct nfs4_getdeviceinfo_res res = { | 7948 | struct nfs4_getdeviceinfo_res res = { |
7949 | .pdev = pdev, | 7949 | .pdev = pdev, |
@@ -7958,6 +7958,11 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, | |||
7958 | 7958 | ||
7959 | dprintk("--> %s\n", __func__); | 7959 | dprintk("--> %s\n", __func__); |
7960 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 7960 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
7961 | if (res.notification & ~args.notify_types) | ||
7962 | dprintk("%s: unsupported notification\n", __func__); | ||
7963 | if (res.notification != args.notify_types) | ||
7964 | pdev->nocache = 1; | ||
7965 | |||
7961 | dprintk("<-- %s status=%d\n", __func__, status); | 7966 | dprintk("<-- %s status=%d\n", __func__, status); |
7962 | 7967 | ||
7963 | return status; | 7968 | return status; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f95e3b58bbc3..935a6ffe8643 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/fs.h> | 43 | #include <linux/fs.h> |
44 | #include <linux/nfs_fs.h> | 44 | #include <linux/nfs_fs.h> |
45 | #include <linux/nfs_idmap.h> | ||
46 | #include <linux/kthread.h> | 45 | #include <linux/kthread.h> |
47 | #include <linux/module.h> | 46 | #include <linux/module.h> |
48 | #include <linux/random.h> | 47 | #include <linux/random.h> |
@@ -57,6 +56,7 @@ | |||
57 | #include "callback.h" | 56 | #include "callback.h" |
58 | #include "delegation.h" | 57 | #include "delegation.h" |
59 | #include "internal.h" | 58 | #include "internal.h" |
59 | #include "nfs4idmap.h" | ||
60 | #include "nfs4session.h" | 60 | #include "nfs4session.h" |
61 | #include "pnfs.h" | 61 | #include "pnfs.h" |
62 | #include "netns.h" | 62 | #include "netns.h" |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 75090feeafad..6fb7cb6b3f4b 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -3,12 +3,12 @@ | |||
3 | */ | 3 | */ |
4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/nfs_idmap.h> | ||
7 | #include <linux/nfs4_mount.h> | 6 | #include <linux/nfs4_mount.h> |
8 | #include <linux/nfs_fs.h> | 7 | #include <linux/nfs_fs.h> |
9 | #include "delegation.h" | 8 | #include "delegation.h" |
10 | #include "internal.h" | 9 | #include "internal.h" |
11 | #include "nfs4_fs.h" | 10 | #include "nfs4_fs.h" |
11 | #include "nfs4idmap.h" | ||
12 | #include "dns_resolve.h" | 12 | #include "dns_resolve.h" |
13 | #include "pnfs.h" | 13 | #include "pnfs.h" |
14 | #include "nfs.h" | 14 | #include "nfs.h" |
@@ -91,10 +91,11 @@ static void nfs4_evict_inode(struct inode *inode) | |||
91 | { | 91 | { |
92 | truncate_inode_pages_final(&inode->i_data); | 92 | truncate_inode_pages_final(&inode->i_data); |
93 | clear_inode(inode); | 93 | clear_inode(inode); |
94 | pnfs_return_layout(inode); | ||
95 | pnfs_destroy_layout(NFS_I(inode)); | ||
96 | /* If we are holding a delegation, return it! */ | 94 | /* If we are holding a delegation, return it! */ |
97 | nfs_inode_return_delegation_noreclaim(inode); | 95 | nfs_inode_return_delegation_noreclaim(inode); |
96 | /* Note that above delegreturn would trigger pnfs return-on-close */ | ||
97 | pnfs_return_layout(inode); | ||
98 | pnfs_destroy_layout(NFS_I(inode)); | ||
98 | /* First call standard NFS clear_inode() code */ | 99 | /* First call standard NFS clear_inode() code */ |
99 | nfs_clear_inode(inode); | 100 | nfs_clear_inode(inode); |
100 | } | 101 | } |
diff --git a/fs/nfs/nfs4sysctl.c b/fs/nfs/nfs4sysctl.c index b6ebe7e445f6..0fbd3ab1be22 100644 --- a/fs/nfs/nfs4sysctl.c +++ b/fs/nfs/nfs4sysctl.c | |||
@@ -6,10 +6,10 @@ | |||
6 | * Copyright (c) 2006 Trond Myklebust <Trond.Myklebust@netapp.com> | 6 | * Copyright (c) 2006 Trond Myklebust <Trond.Myklebust@netapp.com> |
7 | */ | 7 | */ |
8 | #include <linux/sysctl.h> | 8 | #include <linux/sysctl.h> |
9 | #include <linux/nfs_idmap.h> | ||
10 | #include <linux/nfs_fs.h> | 9 | #include <linux/nfs_fs.h> |
11 | 10 | ||
12 | #include "nfs4_fs.h" | 11 | #include "nfs4_fs.h" |
12 | #include "nfs4idmap.h" | ||
13 | #include "callback.h" | 13 | #include "callback.h" |
14 | 14 | ||
15 | static const int nfs_set_port_min = 0; | 15 | static const int nfs_set_port_min = 0; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5c399ec41079..0aea97841d30 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -52,10 +52,10 @@ | |||
52 | #include <linux/nfs.h> | 52 | #include <linux/nfs.h> |
53 | #include <linux/nfs4.h> | 53 | #include <linux/nfs4.h> |
54 | #include <linux/nfs_fs.h> | 54 | #include <linux/nfs_fs.h> |
55 | #include <linux/nfs_idmap.h> | ||
56 | 55 | ||
57 | #include "nfs4_fs.h" | 56 | #include "nfs4_fs.h" |
58 | #include "internal.h" | 57 | #include "internal.h" |
58 | #include "nfs4idmap.h" | ||
59 | #include "nfs4session.h" | 59 | #include "nfs4session.h" |
60 | #include "pnfs.h" | 60 | #include "pnfs.h" |
61 | #include "netns.h" | 61 | #include "netns.h" |
@@ -1920,7 +1920,7 @@ encode_getdeviceinfo(struct xdr_stream *xdr, | |||
1920 | 1920 | ||
1921 | p = reserve_space(xdr, 4 + 4); | 1921 | p = reserve_space(xdr, 4 + 4); |
1922 | *p++ = cpu_to_be32(1); /* bitmap length */ | 1922 | *p++ = cpu_to_be32(1); /* bitmap length */ |
1923 | *p++ = cpu_to_be32(NOTIFY_DEVICEID4_CHANGE | NOTIFY_DEVICEID4_DELETE); | 1923 | *p++ = cpu_to_be32(args->notify_types); |
1924 | } | 1924 | } |
1925 | 1925 | ||
1926 | static void | 1926 | static void |
@@ -5753,8 +5753,9 @@ out_overflow: | |||
5753 | 5753 | ||
5754 | #if defined(CONFIG_NFS_V4_1) | 5754 | #if defined(CONFIG_NFS_V4_1) |
5755 | static int decode_getdeviceinfo(struct xdr_stream *xdr, | 5755 | static int decode_getdeviceinfo(struct xdr_stream *xdr, |
5756 | struct pnfs_device *pdev) | 5756 | struct nfs4_getdeviceinfo_res *res) |
5757 | { | 5757 | { |
5758 | struct pnfs_device *pdev = res->pdev; | ||
5758 | __be32 *p; | 5759 | __be32 *p; |
5759 | uint32_t len, type; | 5760 | uint32_t len, type; |
5760 | int status; | 5761 | int status; |
@@ -5802,12 +5803,7 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr, | |||
5802 | if (unlikely(!p)) | 5803 | if (unlikely(!p)) |
5803 | goto out_overflow; | 5804 | goto out_overflow; |
5804 | 5805 | ||
5805 | if (be32_to_cpup(p++) & | 5806 | res->notification = be32_to_cpup(p++); |
5806 | ~(NOTIFY_DEVICEID4_CHANGE | NOTIFY_DEVICEID4_DELETE)) { | ||
5807 | dprintk("%s: unsupported notification\n", | ||
5808 | __func__); | ||
5809 | } | ||
5810 | |||
5811 | for (i = 1; i < len; i++) { | 5807 | for (i = 1; i < len; i++) { |
5812 | if (be32_to_cpup(p++)) { | 5808 | if (be32_to_cpup(p++)) { |
5813 | dprintk("%s: unsupported notification\n", | 5809 | dprintk("%s: unsupported notification\n", |
@@ -7061,7 +7057,7 @@ static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, | |||
7061 | status = decode_sequence(xdr, &res->seq_res, rqstp); | 7057 | status = decode_sequence(xdr, &res->seq_res, rqstp); |
7062 | if (status != 0) | 7058 | if (status != 0) |
7063 | goto out; | 7059 | goto out; |
7064 | status = decode_getdeviceinfo(xdr, res->pdev); | 7060 | status = decode_getdeviceinfo(xdr, res); |
7065 | out: | 7061 | out: |
7066 | return status; | 7062 | return status; |
7067 | } | 7063 | } |
@@ -7365,6 +7361,11 @@ nfs4_stat_to_errno(int stat) | |||
7365 | .p_name = #proc, \ | 7361 | .p_name = #proc, \ |
7366 | } | 7362 | } |
7367 | 7363 | ||
7364 | #define STUB(proc) \ | ||
7365 | [NFSPROC4_CLNT_##proc] = { \ | ||
7366 | .p_name = #proc, \ | ||
7367 | } | ||
7368 | |||
7368 | struct rpc_procinfo nfs4_procedures[] = { | 7369 | struct rpc_procinfo nfs4_procedures[] = { |
7369 | PROC(READ, enc_read, dec_read), | 7370 | PROC(READ, enc_read, dec_read), |
7370 | PROC(WRITE, enc_write, dec_write), | 7371 | PROC(WRITE, enc_write, dec_write), |
@@ -7417,6 +7418,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
7417 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), | 7418 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), |
7418 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | 7419 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), |
7419 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), | 7420 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), |
7421 | STUB(GETDEVICELIST), | ||
7420 | PROC(BIND_CONN_TO_SESSION, | 7422 | PROC(BIND_CONN_TO_SESSION, |
7421 | enc_bind_conn_to_session, dec_bind_conn_to_session), | 7423 | enc_bind_conn_to_session, dec_bind_conn_to_session), |
7422 | PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid), | 7424 | PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid), |
diff --git a/fs/nfs/nfstrace.c b/fs/nfs/nfstrace.c index 4eb0aead69b6..c74f7af23d77 100644 --- a/fs/nfs/nfstrace.c +++ b/fs/nfs/nfstrace.c | |||
@@ -7,3 +7,6 @@ | |||
7 | 7 | ||
8 | #define CREATE_TRACE_POINTS | 8 | #define CREATE_TRACE_POINTS |
9 | #include "nfstrace.h" | 9 | #include "nfstrace.h" |
10 | |||
11 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_enter); | ||
12 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_exit); | ||
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 24e1d7403c0b..5aaed363556a 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -57,7 +57,7 @@ objio_free_deviceid_node(struct nfs4_deviceid_node *d) | |||
57 | 57 | ||
58 | dprintk("%s: free od=%p\n", __func__, de->od.od); | 58 | dprintk("%s: free od=%p\n", __func__, de->od.od); |
59 | osduld_put_device(de->od.od); | 59 | osduld_put_device(de->od.od); |
60 | kfree(de); | 60 | kfree_rcu(d, rcu); |
61 | } | 61 | } |
62 | 62 | ||
63 | struct objio_segment { | 63 | struct objio_segment { |
@@ -637,6 +637,8 @@ static struct pnfs_layoutdriver_type objlayout_type = { | |||
637 | .pg_read_ops = &objio_pg_read_ops, | 637 | .pg_read_ops = &objio_pg_read_ops, |
638 | .pg_write_ops = &objio_pg_write_ops, | 638 | .pg_write_ops = &objio_pg_write_ops, |
639 | 639 | ||
640 | .sync = pnfs_generic_sync, | ||
641 | |||
640 | .free_deviceid_node = objio_free_deviceid_node, | 642 | .free_deviceid_node = objio_free_deviceid_node, |
641 | 643 | ||
642 | .encode_layoutcommit = objlayout_encode_layoutcommit, | 644 | .encode_layoutcommit = objlayout_encode_layoutcommit, |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0b2bca9ae281..230606243be6 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1090,6 +1090,7 @@ bool pnfs_roc(struct inode *ino) | |||
1090 | pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */ | 1090 | pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */ |
1091 | spin_unlock(&ino->i_lock); | 1091 | spin_unlock(&ino->i_lock); |
1092 | pnfs_free_lseg_list(&tmp_list); | 1092 | pnfs_free_lseg_list(&tmp_list); |
1093 | pnfs_layoutcommit_inode(ino, true); | ||
1093 | return true; | 1094 | return true; |
1094 | 1095 | ||
1095 | out_noroc: | 1096 | out_noroc: |
@@ -1104,8 +1105,10 @@ out_noroc: | |||
1104 | } | 1105 | } |
1105 | } | 1106 | } |
1106 | spin_unlock(&ino->i_lock); | 1107 | spin_unlock(&ino->i_lock); |
1107 | if (layoutreturn) | 1108 | if (layoutreturn) { |
1109 | pnfs_layoutcommit_inode(ino, true); | ||
1108 | pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); | 1110 | pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); |
1111 | } | ||
1109 | return false; | 1112 | return false; |
1110 | } | 1113 | } |
1111 | 1114 | ||
@@ -1841,7 +1844,8 @@ void pnfs_ld_write_done(struct nfs_pgio_header *hdr) | |||
1841 | { | 1844 | { |
1842 | trace_nfs4_pnfs_write(hdr, hdr->pnfs_error); | 1845 | trace_nfs4_pnfs_write(hdr, hdr->pnfs_error); |
1843 | if (!hdr->pnfs_error) { | 1846 | if (!hdr->pnfs_error) { |
1844 | pnfs_set_layoutcommit(hdr); | 1847 | pnfs_set_layoutcommit(hdr->inode, hdr->lseg, |
1848 | hdr->mds_offset + hdr->res.count); | ||
1845 | hdr->mds_ops->rpc_call_done(&hdr->task, hdr); | 1849 | hdr->mds_ops->rpc_call_done(&hdr->task, hdr); |
1846 | } else | 1850 | } else |
1847 | pnfs_ld_handle_write_error(hdr); | 1851 | pnfs_ld_handle_write_error(hdr); |
@@ -2097,64 +2101,34 @@ void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) | |||
2097 | EXPORT_SYMBOL_GPL(pnfs_set_lo_fail); | 2101 | EXPORT_SYMBOL_GPL(pnfs_set_lo_fail); |
2098 | 2102 | ||
2099 | void | 2103 | void |
2100 | pnfs_set_layoutcommit(struct nfs_pgio_header *hdr) | 2104 | pnfs_set_layoutcommit(struct inode *inode, struct pnfs_layout_segment *lseg, |
2105 | loff_t end_pos) | ||
2101 | { | 2106 | { |
2102 | struct inode *inode = hdr->inode; | ||
2103 | struct nfs_inode *nfsi = NFS_I(inode); | 2107 | struct nfs_inode *nfsi = NFS_I(inode); |
2104 | loff_t end_pos = hdr->mds_offset + hdr->res.count; | ||
2105 | bool mark_as_dirty = false; | 2108 | bool mark_as_dirty = false; |
2106 | 2109 | ||
2107 | spin_lock(&inode->i_lock); | 2110 | spin_lock(&inode->i_lock); |
2108 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 2111 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
2109 | mark_as_dirty = true; | ||
2110 | dprintk("%s: Set layoutcommit for inode %lu ", | ||
2111 | __func__, inode->i_ino); | ||
2112 | } | ||
2113 | if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &hdr->lseg->pls_flags)) { | ||
2114 | /* references matched in nfs4_layoutcommit_release */ | ||
2115 | pnfs_get_lseg(hdr->lseg); | ||
2116 | } | ||
2117 | if (end_pos > nfsi->layout->plh_lwb) | ||
2118 | nfsi->layout->plh_lwb = end_pos; | 2112 | nfsi->layout->plh_lwb = end_pos; |
2119 | spin_unlock(&inode->i_lock); | ||
2120 | dprintk("%s: lseg %p end_pos %llu\n", | ||
2121 | __func__, hdr->lseg, nfsi->layout->plh_lwb); | ||
2122 | |||
2123 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one | ||
2124 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ | ||
2125 | if (mark_as_dirty) | ||
2126 | mark_inode_dirty_sync(inode); | ||
2127 | } | ||
2128 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | ||
2129 | |||
2130 | void pnfs_commit_set_layoutcommit(struct nfs_commit_data *data) | ||
2131 | { | ||
2132 | struct inode *inode = data->inode; | ||
2133 | struct nfs_inode *nfsi = NFS_I(inode); | ||
2134 | bool mark_as_dirty = false; | ||
2135 | |||
2136 | spin_lock(&inode->i_lock); | ||
2137 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | ||
2138 | mark_as_dirty = true; | 2113 | mark_as_dirty = true; |
2139 | dprintk("%s: Set layoutcommit for inode %lu ", | 2114 | dprintk("%s: Set layoutcommit for inode %lu ", |
2140 | __func__, inode->i_ino); | 2115 | __func__, inode->i_ino); |
2141 | } | 2116 | } else if (end_pos > nfsi->layout->plh_lwb) |
2142 | if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &data->lseg->pls_flags)) { | 2117 | nfsi->layout->plh_lwb = end_pos; |
2118 | if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) { | ||
2143 | /* references matched in nfs4_layoutcommit_release */ | 2119 | /* references matched in nfs4_layoutcommit_release */ |
2144 | pnfs_get_lseg(data->lseg); | 2120 | pnfs_get_lseg(lseg); |
2145 | } | 2121 | } |
2146 | if (data->lwb > nfsi->layout->plh_lwb) | ||
2147 | nfsi->layout->plh_lwb = data->lwb; | ||
2148 | spin_unlock(&inode->i_lock); | 2122 | spin_unlock(&inode->i_lock); |
2149 | dprintk("%s: lseg %p end_pos %llu\n", | 2123 | dprintk("%s: lseg %p end_pos %llu\n", |
2150 | __func__, data->lseg, nfsi->layout->plh_lwb); | 2124 | __func__, lseg, nfsi->layout->plh_lwb); |
2151 | 2125 | ||
2152 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one | 2126 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one |
2153 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ | 2127 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ |
2154 | if (mark_as_dirty) | 2128 | if (mark_as_dirty) |
2155 | mark_inode_dirty_sync(inode); | 2129 | mark_inode_dirty_sync(inode); |
2156 | } | 2130 | } |
2157 | EXPORT_SYMBOL_GPL(pnfs_commit_set_layoutcommit); | 2131 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); |
2158 | 2132 | ||
2159 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data) | 2133 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data) |
2160 | { | 2134 | { |
@@ -2214,7 +2188,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
2214 | pnfs_list_write_lseg(inode, &data->lseg_list); | 2188 | pnfs_list_write_lseg(inode, &data->lseg_list); |
2215 | 2189 | ||
2216 | end_pos = nfsi->layout->plh_lwb; | 2190 | end_pos = nfsi->layout->plh_lwb; |
2217 | nfsi->layout->plh_lwb = 0; | ||
2218 | 2191 | ||
2219 | nfs4_stateid_copy(&data->args.stateid, &nfsi->layout->plh_stateid); | 2192 | nfs4_stateid_copy(&data->args.stateid, &nfsi->layout->plh_stateid); |
2220 | spin_unlock(&inode->i_lock); | 2193 | spin_unlock(&inode->i_lock); |
@@ -2231,11 +2204,11 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
2231 | status = ld->prepare_layoutcommit(&data->args); | 2204 | status = ld->prepare_layoutcommit(&data->args); |
2232 | if (status) { | 2205 | if (status) { |
2233 | spin_lock(&inode->i_lock); | 2206 | spin_lock(&inode->i_lock); |
2234 | if (end_pos < nfsi->layout->plh_lwb) | 2207 | set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); |
2208 | if (end_pos > nfsi->layout->plh_lwb) | ||
2235 | nfsi->layout->plh_lwb = end_pos; | 2209 | nfsi->layout->plh_lwb = end_pos; |
2236 | spin_unlock(&inode->i_lock); | 2210 | spin_unlock(&inode->i_lock); |
2237 | put_rpccred(data->cred); | 2211 | put_rpccred(data->cred); |
2238 | set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); | ||
2239 | goto clear_layoutcommitting; | 2212 | goto clear_layoutcommitting; |
2240 | } | 2213 | } |
2241 | } | 2214 | } |
@@ -2256,6 +2229,13 @@ clear_layoutcommitting: | |||
2256 | } | 2229 | } |
2257 | EXPORT_SYMBOL_GPL(pnfs_layoutcommit_inode); | 2230 | EXPORT_SYMBOL_GPL(pnfs_layoutcommit_inode); |
2258 | 2231 | ||
2232 | int | ||
2233 | pnfs_generic_sync(struct inode *inode, bool datasync) | ||
2234 | { | ||
2235 | return pnfs_layoutcommit_inode(inode, true); | ||
2236 | } | ||
2237 | EXPORT_SYMBOL_GPL(pnfs_generic_sync); | ||
2238 | |||
2259 | struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | 2239 | struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) |
2260 | { | 2240 | { |
2261 | struct nfs4_threshold *thp; | 2241 | struct nfs4_threshold *thp; |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 635f0865671c..231eb23c22da 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -155,6 +155,8 @@ struct pnfs_layoutdriver_type { | |||
155 | int how, | 155 | int how, |
156 | struct nfs_commit_info *cinfo); | 156 | struct nfs_commit_info *cinfo); |
157 | 157 | ||
158 | int (*sync)(struct inode *inode, bool datasync); | ||
159 | |||
158 | /* | 160 | /* |
159 | * Return PNFS_ATTEMPTED to indicate the layout code has attempted | 161 | * Return PNFS_ATTEMPTED to indicate the layout code has attempted |
160 | * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS | 162 | * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS |
@@ -203,6 +205,7 @@ struct pnfs_device { | |||
203 | struct page **pages; | 205 | struct page **pages; |
204 | unsigned int pgbase; | 206 | unsigned int pgbase; |
205 | unsigned int pglen; /* reply buffer length */ | 207 | unsigned int pglen; /* reply buffer length */ |
208 | unsigned char nocache : 1;/* May not be cached */ | ||
206 | }; | 209 | }; |
207 | 210 | ||
208 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 | 211 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 |
@@ -263,10 +266,11 @@ bool pnfs_roc(struct inode *ino); | |||
263 | void pnfs_roc_release(struct inode *ino); | 266 | void pnfs_roc_release(struct inode *ino); |
264 | void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); | 267 | void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); |
265 | bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task); | 268 | bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task); |
266 | void pnfs_set_layoutcommit(struct nfs_pgio_header *); | 269 | void pnfs_set_layoutcommit(struct inode *, struct pnfs_layout_segment *, loff_t); |
267 | void pnfs_commit_set_layoutcommit(struct nfs_commit_data *data); | ||
268 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); | 270 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); |
269 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); | 271 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); |
272 | int pnfs_generic_sync(struct inode *inode, bool datasync); | ||
273 | int pnfs_nfs_generic_sync(struct inode *inode, bool datasync); | ||
270 | int _pnfs_return_layout(struct inode *); | 274 | int _pnfs_return_layout(struct inode *); |
271 | int pnfs_commit_and_return_layout(struct inode *); | 275 | int pnfs_commit_and_return_layout(struct inode *); |
272 | void pnfs_ld_write_done(struct nfs_pgio_header *); | 276 | void pnfs_ld_write_done(struct nfs_pgio_header *); |
@@ -291,6 +295,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, | |||
291 | enum { | 295 | enum { |
292 | NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */ | 296 | NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */ |
293 | NFS_DEVICEID_UNAVAILABLE, /* device temporarily unavailable */ | 297 | NFS_DEVICEID_UNAVAILABLE, /* device temporarily unavailable */ |
298 | NFS_DEVICEID_NOCACHE, /* device may not be cached */ | ||
294 | }; | 299 | }; |
295 | 300 | ||
296 | /* pnfs_dev.c */ | 301 | /* pnfs_dev.c */ |
@@ -302,6 +307,7 @@ struct nfs4_deviceid_node { | |||
302 | unsigned long flags; | 307 | unsigned long flags; |
303 | unsigned long timestamp_unavailable; | 308 | unsigned long timestamp_unavailable; |
304 | struct nfs4_deviceid deviceid; | 309 | struct nfs4_deviceid deviceid; |
310 | struct rcu_head rcu; | ||
305 | atomic_t ref; | 311 | atomic_t ref; |
306 | }; | 312 | }; |
307 | 313 | ||
@@ -486,6 +492,14 @@ pnfs_ld_read_whole_page(struct inode *inode) | |||
486 | return NFS_SERVER(inode)->pnfs_curr_ld->flags & PNFS_READ_WHOLE_PAGE; | 492 | return NFS_SERVER(inode)->pnfs_curr_ld->flags & PNFS_READ_WHOLE_PAGE; |
487 | } | 493 | } |
488 | 494 | ||
495 | static inline int | ||
496 | pnfs_sync_inode(struct inode *inode, bool datasync) | ||
497 | { | ||
498 | if (!pnfs_enabled_sb(NFS_SERVER(inode))) | ||
499 | return 0; | ||
500 | return NFS_SERVER(inode)->pnfs_curr_ld->sync(inode, datasync); | ||
501 | } | ||
502 | |||
489 | static inline bool | 503 | static inline bool |
490 | pnfs_layoutcommit_outstanding(struct inode *inode) | 504 | pnfs_layoutcommit_outstanding(struct inode *inode) |
491 | { | 505 | { |
@@ -568,6 +582,12 @@ pnfs_ld_read_whole_page(struct inode *inode) | |||
568 | return false; | 582 | return false; |
569 | } | 583 | } |
570 | 584 | ||
585 | static inline int | ||
586 | pnfs_sync_inode(struct inode *inode, bool datasync) | ||
587 | { | ||
588 | return 0; | ||
589 | } | ||
590 | |||
571 | static inline bool | 591 | static inline bool |
572 | pnfs_roc(struct inode *ino) | 592 | pnfs_roc(struct inode *ino) |
573 | { | 593 | { |
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index aa2ec0015183..2961fcd7a2df 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
@@ -149,6 +149,8 @@ nfs4_get_device_info(struct nfs_server *server, | |||
149 | */ | 149 | */ |
150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, | 150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, |
151 | gfp_flags); | 151 | gfp_flags); |
152 | if (d && pdev->nocache) | ||
153 | set_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
152 | 154 | ||
153 | out_free_pages: | 155 | out_free_pages: |
154 | for (i = 0; i < max_pages; i++) | 156 | for (i = 0; i < max_pages; i++) |
@@ -175,8 +177,8 @@ __nfs4_find_get_deviceid(struct nfs_server *server, | |||
175 | rcu_read_lock(); | 177 | rcu_read_lock(); |
176 | d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id, | 178 | d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id, |
177 | hash); | 179 | hash); |
178 | if (d != NULL) | 180 | if (d != NULL && !atomic_inc_not_zero(&d->ref)) |
179 | atomic_inc(&d->ref); | 181 | d = NULL; |
180 | rcu_read_unlock(); | 182 | rcu_read_unlock(); |
181 | return d; | 183 | return d; |
182 | } | 184 | } |
@@ -235,12 +237,11 @@ nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
235 | return; | 237 | return; |
236 | } | 238 | } |
237 | hlist_del_init_rcu(&d->node); | 239 | hlist_del_init_rcu(&d->node); |
240 | clear_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
238 | spin_unlock(&nfs4_deviceid_lock); | 241 | spin_unlock(&nfs4_deviceid_lock); |
239 | synchronize_rcu(); | ||
240 | 242 | ||
241 | /* balance the initial ref set in pnfs_insert_deviceid */ | 243 | /* balance the initial ref set in pnfs_insert_deviceid */ |
242 | if (atomic_dec_and_test(&d->ref)) | 244 | nfs4_put_deviceid_node(d); |
243 | d->ld->free_deviceid_node(d); | ||
244 | } | 245 | } |
245 | EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); | 246 | EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); |
246 | 247 | ||
@@ -271,6 +272,11 @@ EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); | |||
271 | bool | 272 | bool |
272 | nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) | 273 | nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) |
273 | { | 274 | { |
275 | if (test_bit(NFS_DEVICEID_NOCACHE, &d->flags)) { | ||
276 | if (atomic_add_unless(&d->ref, -1, 2)) | ||
277 | return false; | ||
278 | nfs4_delete_deviceid(d->ld, d->nfs_client, &d->deviceid); | ||
279 | } | ||
274 | if (!atomic_dec_and_test(&d->ref)) | 280 | if (!atomic_dec_and_test(&d->ref)) |
275 | return false; | 281 | return false; |
276 | d->ld->free_deviceid_node(d); | 282 | d->ld->free_deviceid_node(d); |
@@ -314,6 +320,7 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash) | |||
314 | if (d->nfs_client == clp && atomic_read(&d->ref)) { | 320 | if (d->nfs_client == clp && atomic_read(&d->ref)) { |
315 | hlist_del_init_rcu(&d->node); | 321 | hlist_del_init_rcu(&d->node); |
316 | hlist_add_head(&d->tmpnode, &tmp); | 322 | hlist_add_head(&d->tmpnode, &tmp); |
323 | clear_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
317 | } | 324 | } |
318 | rcu_read_unlock(); | 325 | rcu_read_unlock(); |
319 | spin_unlock(&nfs4_deviceid_lock); | 326 | spin_unlock(&nfs4_deviceid_lock); |
@@ -321,12 +328,10 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash) | |||
321 | if (hlist_empty(&tmp)) | 328 | if (hlist_empty(&tmp)) |
322 | return; | 329 | return; |
323 | 330 | ||
324 | synchronize_rcu(); | ||
325 | while (!hlist_empty(&tmp)) { | 331 | while (!hlist_empty(&tmp)) { |
326 | d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); | 332 | d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); |
327 | hlist_del(&d->tmpnode); | 333 | hlist_del(&d->tmpnode); |
328 | if (atomic_dec_and_test(&d->ref)) | 334 | nfs4_put_deviceid_node(d); |
329 | d->ld->free_deviceid_node(d); | ||
330 | } | 335 | } |
331 | } | 336 | } |
332 | 337 | ||
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index 8582dae5ae99..f37e25b6311c 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -868,3 +868,13 @@ pnfs_layout_mark_request_commit(struct nfs_page *req, | |||
868 | nfs_request_add_commit_list(req, list, cinfo); | 868 | nfs_request_add_commit_list(req, list, cinfo); |
869 | } | 869 | } |
870 | EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit); | 870 | EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit); |
871 | |||
872 | int | ||
873 | pnfs_nfs_generic_sync(struct inode *inode, bool datasync) | ||
874 | { | ||
875 | if (datasync) | ||
876 | return 0; | ||
877 | return pnfs_layoutcommit_inode(inode, true); | ||
878 | } | ||
879 | EXPORT_SYMBOL_GPL(pnfs_nfs_generic_sync); | ||
880 | |||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 568ecf0a880f..848d8b1db4ce 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -284,7 +284,7 @@ int nfs_readpage(struct file *file, struct page *page) | |||
284 | dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", | 284 | dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", |
285 | page, PAGE_CACHE_SIZE, page_file_index(page)); | 285 | page, PAGE_CACHE_SIZE, page_file_index(page)); |
286 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); | 286 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); |
287 | nfs_inc_stats(inode, NFSIOS_READPAGES); | 287 | nfs_add_stats(inode, NFSIOS_READPAGES, 1); |
288 | 288 | ||
289 | /* | 289 | /* |
290 | * Try to flush any pending writes to the file.. | 290 | * Try to flush any pending writes to the file.. |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 54a079a465e1..e8620938a4f5 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/mount.h> | 44 | #include <linux/mount.h> |
45 | #include <linux/namei.h> | 45 | #include <linux/namei.h> |
46 | #include <linux/nfs_idmap.h> | ||
47 | #include <linux/vfs.h> | 46 | #include <linux/vfs.h> |
48 | #include <linux/inet.h> | 47 | #include <linux/inet.h> |
49 | #include <linux/in6.h> | 48 | #include <linux/in6.h> |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 849ed784d6ac..36d0c0a6e68a 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -580,7 +580,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st | |||
580 | int ret; | 580 | int ret; |
581 | 581 | ||
582 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); | 582 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); |
583 | nfs_inc_stats(inode, NFSIOS_WRITEPAGES); | 583 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); |
584 | 584 | ||
585 | nfs_pageio_cond_complete(pgio, page_file_index(page)); | 585 | nfs_pageio_cond_complete(pgio, page_file_index(page)); |
586 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); | 586 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); |
@@ -1840,17 +1840,16 @@ EXPORT_SYMBOL_GPL(nfs_write_inode); | |||
1840 | */ | 1840 | */ |
1841 | int nfs_wb_all(struct inode *inode) | 1841 | int nfs_wb_all(struct inode *inode) |
1842 | { | 1842 | { |
1843 | struct writeback_control wbc = { | ||
1844 | .sync_mode = WB_SYNC_ALL, | ||
1845 | .nr_to_write = LONG_MAX, | ||
1846 | .range_start = 0, | ||
1847 | .range_end = LLONG_MAX, | ||
1848 | }; | ||
1849 | int ret; | 1843 | int ret; |
1850 | 1844 | ||
1851 | trace_nfs_writeback_inode_enter(inode); | 1845 | trace_nfs_writeback_inode_enter(inode); |
1852 | 1846 | ||
1853 | ret = sync_inode(inode, &wbc); | 1847 | ret = filemap_write_and_wait(inode->i_mapping); |
1848 | if (!ret) { | ||
1849 | ret = nfs_commit_inode(inode, FLUSH_SYNC); | ||
1850 | if (!ret) | ||
1851 | pnfs_sync_inode(inode, true); | ||
1852 | } | ||
1854 | 1853 | ||
1855 | trace_nfs_writeback_inode_exit(inode, ret); | 1854 | trace_nfs_writeback_inode_exit(inode, ret); |
1856 | return ret; | 1855 | return ret; |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index b01ccf371fdc..b638eb6727c6 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -512,6 +512,7 @@ extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned | |||
512 | * Try to write back everything synchronously (but check the | 512 | * Try to write back everything synchronously (but check the |
513 | * return value!) | 513 | * return value!) |
514 | */ | 514 | */ |
515 | extern int nfs_sync_inode(struct inode *inode); | ||
515 | extern int nfs_wb_all(struct inode *inode); | 516 | extern int nfs_wb_all(struct inode *inode); |
516 | extern int nfs_wb_page(struct inode *inode, struct page* page); | 517 | extern int nfs_wb_page(struct inode *inode, struct page* page); |
517 | extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); | 518 | extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 4cb3eaa89cf7..93ab6071bbe9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -255,11 +255,13 @@ struct nfs4_layoutget { | |||
255 | struct nfs4_getdeviceinfo_args { | 255 | struct nfs4_getdeviceinfo_args { |
256 | struct nfs4_sequence_args seq_args; | 256 | struct nfs4_sequence_args seq_args; |
257 | struct pnfs_device *pdev; | 257 | struct pnfs_device *pdev; |
258 | __u32 notify_types; | ||
258 | }; | 259 | }; |
259 | 260 | ||
260 | struct nfs4_getdeviceinfo_res { | 261 | struct nfs4_getdeviceinfo_res { |
261 | struct nfs4_sequence_res seq_res; | 262 | struct nfs4_sequence_res seq_res; |
262 | struct pnfs_device *pdev; | 263 | struct pnfs_device *pdev; |
264 | __u32 notification; | ||
263 | }; | 265 | }; |
264 | 266 | ||
265 | struct nfs4_layoutcommit_args { | 267 | struct nfs4_layoutcommit_args { |
@@ -1271,11 +1273,15 @@ struct nfs42_falloc_args { | |||
1271 | nfs4_stateid falloc_stateid; | 1273 | nfs4_stateid falloc_stateid; |
1272 | u64 falloc_offset; | 1274 | u64 falloc_offset; |
1273 | u64 falloc_length; | 1275 | u64 falloc_length; |
1276 | const u32 *falloc_bitmask; | ||
1274 | }; | 1277 | }; |
1275 | 1278 | ||
1276 | struct nfs42_falloc_res { | 1279 | struct nfs42_falloc_res { |
1277 | struct nfs4_sequence_res seq_res; | 1280 | struct nfs4_sequence_res seq_res; |
1278 | unsigned int status; | 1281 | unsigned int status; |
1282 | |||
1283 | struct nfs_fattr *falloc_fattr; | ||
1284 | const struct nfs_server *falloc_server; | ||
1279 | }; | 1285 | }; |
1280 | 1286 | ||
1281 | struct nfs42_seek_args { | 1287 | struct nfs42_seek_args { |
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h index c57d8ea0716c..59a7889e15db 100644 --- a/include/linux/sunrpc/debug.h +++ b/include/linux/sunrpc/debug.h | |||
@@ -60,17 +60,17 @@ struct rpc_xprt; | |||
60 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 60 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
61 | void rpc_register_sysctl(void); | 61 | void rpc_register_sysctl(void); |
62 | void rpc_unregister_sysctl(void); | 62 | void rpc_unregister_sysctl(void); |
63 | int sunrpc_debugfs_init(void); | 63 | void sunrpc_debugfs_init(void); |
64 | void sunrpc_debugfs_exit(void); | 64 | void sunrpc_debugfs_exit(void); |
65 | int rpc_clnt_debugfs_register(struct rpc_clnt *); | 65 | void rpc_clnt_debugfs_register(struct rpc_clnt *); |
66 | void rpc_clnt_debugfs_unregister(struct rpc_clnt *); | 66 | void rpc_clnt_debugfs_unregister(struct rpc_clnt *); |
67 | int rpc_xprt_debugfs_register(struct rpc_xprt *); | 67 | void rpc_xprt_debugfs_register(struct rpc_xprt *); |
68 | void rpc_xprt_debugfs_unregister(struct rpc_xprt *); | 68 | void rpc_xprt_debugfs_unregister(struct rpc_xprt *); |
69 | #else | 69 | #else |
70 | static inline int | 70 | static inline void |
71 | sunrpc_debugfs_init(void) | 71 | sunrpc_debugfs_init(void) |
72 | { | 72 | { |
73 | return 0; | 73 | return; |
74 | } | 74 | } |
75 | 75 | ||
76 | static inline void | 76 | static inline void |
@@ -79,10 +79,10 @@ sunrpc_debugfs_exit(void) | |||
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | 81 | ||
82 | static inline int | 82 | static inline void |
83 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) | 83 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) |
84 | { | 84 | { |
85 | return 0; | 85 | return; |
86 | } | 86 | } |
87 | 87 | ||
88 | static inline void | 88 | static inline void |
@@ -91,10 +91,10 @@ rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt) | |||
91 | return; | 91 | return; |
92 | } | 92 | } |
93 | 93 | ||
94 | static inline int | 94 | static inline void |
95 | rpc_xprt_debugfs_register(struct rpc_xprt *xprt) | 95 | rpc_xprt_debugfs_register(struct rpc_xprt *xprt) |
96 | { | 96 | { |
97 | return 0; | 97 | return; |
98 | } | 98 | } |
99 | 99 | ||
100 | static inline void | 100 | static inline void |
diff --git a/include/uapi/linux/nfs_idmap.h b/include/uapi/linux/nfs_idmap.h index 8d4b1c7b24d4..038e36c96669 100644 --- a/include/uapi/linux/nfs_idmap.h +++ b/include/uapi/linux/nfs_idmap.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * include/linux/nfs_idmap.h | 2 | * include/uapi/linux/nfs_idmap.h |
3 | * | 3 | * |
4 | * UID and GID to name mapping for clients. | 4 | * UID and GID to name mapping for clients. |
5 | * | 5 | * |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 612aa73bbc60..e6ce1517367f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -303,9 +303,7 @@ static int rpc_client_register(struct rpc_clnt *clnt, | |||
303 | struct super_block *pipefs_sb; | 303 | struct super_block *pipefs_sb; |
304 | int err; | 304 | int err; |
305 | 305 | ||
306 | err = rpc_clnt_debugfs_register(clnt); | 306 | rpc_clnt_debugfs_register(clnt); |
307 | if (err) | ||
308 | return err; | ||
309 | 307 | ||
310 | pipefs_sb = rpc_get_sb_net(net); | 308 | pipefs_sb = rpc_get_sb_net(net); |
311 | if (pipefs_sb) { | 309 | if (pipefs_sb) { |
diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c index e811f390f9f6..82962f7e6e88 100644 --- a/net/sunrpc/debugfs.c +++ b/net/sunrpc/debugfs.c | |||
@@ -129,48 +129,52 @@ static const struct file_operations tasks_fops = { | |||
129 | .release = tasks_release, | 129 | .release = tasks_release, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | int | 132 | void |
133 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) | 133 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) |
134 | { | 134 | { |
135 | int len, err; | 135 | int len; |
136 | char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ | 136 | char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ |
137 | struct rpc_xprt *xprt; | ||
137 | 138 | ||
138 | /* Already registered? */ | 139 | /* Already registered? */ |
139 | if (clnt->cl_debugfs) | 140 | if (clnt->cl_debugfs || !rpc_clnt_dir) |
140 | return 0; | 141 | return; |
141 | 142 | ||
142 | len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); | 143 | len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); |
143 | if (len >= sizeof(name)) | 144 | if (len >= sizeof(name)) |
144 | return -EINVAL; | 145 | return; |
145 | 146 | ||
146 | /* make the per-client dir */ | 147 | /* make the per-client dir */ |
147 | clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); | 148 | clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); |
148 | if (!clnt->cl_debugfs) | 149 | if (!clnt->cl_debugfs) |
149 | return -ENOMEM; | 150 | return; |
150 | 151 | ||
151 | /* make tasks file */ | 152 | /* make tasks file */ |
152 | err = -ENOMEM; | ||
153 | if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs, | 153 | if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs, |
154 | clnt, &tasks_fops)) | 154 | clnt, &tasks_fops)) |
155 | goto out_err; | 155 | goto out_err; |
156 | 156 | ||
157 | err = -EINVAL; | ||
158 | rcu_read_lock(); | 157 | rcu_read_lock(); |
158 | xprt = rcu_dereference(clnt->cl_xprt); | ||
159 | /* no "debugfs" dentry? Don't bother with the symlink. */ | ||
160 | if (!xprt->debugfs) { | ||
161 | rcu_read_unlock(); | ||
162 | return; | ||
163 | } | ||
159 | len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", | 164 | len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", |
160 | rcu_dereference(clnt->cl_xprt)->debugfs->d_name.name); | 165 | xprt->debugfs->d_name.name); |
161 | rcu_read_unlock(); | 166 | rcu_read_unlock(); |
167 | |||
162 | if (len >= sizeof(name)) | 168 | if (len >= sizeof(name)) |
163 | goto out_err; | 169 | goto out_err; |
164 | 170 | ||
165 | err = -ENOMEM; | ||
166 | if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) | 171 | if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) |
167 | goto out_err; | 172 | goto out_err; |
168 | 173 | ||
169 | return 0; | 174 | return; |
170 | out_err: | 175 | out_err: |
171 | debugfs_remove_recursive(clnt->cl_debugfs); | 176 | debugfs_remove_recursive(clnt->cl_debugfs); |
172 | clnt->cl_debugfs = NULL; | 177 | clnt->cl_debugfs = NULL; |
173 | return err; | ||
174 | } | 178 | } |
175 | 179 | ||
176 | void | 180 | void |
@@ -226,33 +230,33 @@ static const struct file_operations xprt_info_fops = { | |||
226 | .release = xprt_info_release, | 230 | .release = xprt_info_release, |
227 | }; | 231 | }; |
228 | 232 | ||
229 | int | 233 | void |
230 | rpc_xprt_debugfs_register(struct rpc_xprt *xprt) | 234 | rpc_xprt_debugfs_register(struct rpc_xprt *xprt) |
231 | { | 235 | { |
232 | int len, id; | 236 | int len, id; |
233 | static atomic_t cur_id; | 237 | static atomic_t cur_id; |
234 | char name[9]; /* 8 hex digits + NULL term */ | 238 | char name[9]; /* 8 hex digits + NULL term */ |
235 | 239 | ||
240 | if (!rpc_xprt_dir) | ||
241 | return; | ||
242 | |||
236 | id = (unsigned int)atomic_inc_return(&cur_id); | 243 | id = (unsigned int)atomic_inc_return(&cur_id); |
237 | 244 | ||
238 | len = snprintf(name, sizeof(name), "%x", id); | 245 | len = snprintf(name, sizeof(name), "%x", id); |
239 | if (len >= sizeof(name)) | 246 | if (len >= sizeof(name)) |
240 | return -EINVAL; | 247 | return; |
241 | 248 | ||
242 | /* make the per-client dir */ | 249 | /* make the per-client dir */ |
243 | xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); | 250 | xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); |
244 | if (!xprt->debugfs) | 251 | if (!xprt->debugfs) |
245 | return -ENOMEM; | 252 | return; |
246 | 253 | ||
247 | /* make tasks file */ | 254 | /* make tasks file */ |
248 | if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs, | 255 | if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs, |
249 | xprt, &xprt_info_fops)) { | 256 | xprt, &xprt_info_fops)) { |
250 | debugfs_remove_recursive(xprt->debugfs); | 257 | debugfs_remove_recursive(xprt->debugfs); |
251 | xprt->debugfs = NULL; | 258 | xprt->debugfs = NULL; |
252 | return -ENOMEM; | ||
253 | } | 259 | } |
254 | |||
255 | return 0; | ||
256 | } | 260 | } |
257 | 261 | ||
258 | void | 262 | void |
@@ -266,14 +270,17 @@ void __exit | |||
266 | sunrpc_debugfs_exit(void) | 270 | sunrpc_debugfs_exit(void) |
267 | { | 271 | { |
268 | debugfs_remove_recursive(topdir); | 272 | debugfs_remove_recursive(topdir); |
273 | topdir = NULL; | ||
274 | rpc_clnt_dir = NULL; | ||
275 | rpc_xprt_dir = NULL; | ||
269 | } | 276 | } |
270 | 277 | ||
271 | int __init | 278 | void __init |
272 | sunrpc_debugfs_init(void) | 279 | sunrpc_debugfs_init(void) |
273 | { | 280 | { |
274 | topdir = debugfs_create_dir("sunrpc", NULL); | 281 | topdir = debugfs_create_dir("sunrpc", NULL); |
275 | if (!topdir) | 282 | if (!topdir) |
276 | goto out; | 283 | return; |
277 | 284 | ||
278 | rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); | 285 | rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); |
279 | if (!rpc_clnt_dir) | 286 | if (!rpc_clnt_dir) |
@@ -283,10 +290,9 @@ sunrpc_debugfs_init(void) | |||
283 | if (!rpc_xprt_dir) | 290 | if (!rpc_xprt_dir) |
284 | goto out_remove; | 291 | goto out_remove; |
285 | 292 | ||
286 | return 0; | 293 | return; |
287 | out_remove: | 294 | out_remove: |
288 | debugfs_remove_recursive(topdir); | 295 | debugfs_remove_recursive(topdir); |
289 | topdir = NULL; | 296 | topdir = NULL; |
290 | out: | 297 | rpc_clnt_dir = NULL; |
291 | return -ENOMEM; | ||
292 | } | 298 | } |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index b91fd9c597b4..337ca851a350 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -89,8 +89,8 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) | |||
89 | if (!task->tk_timeout) | 89 | if (!task->tk_timeout) |
90 | return; | 90 | return; |
91 | 91 | ||
92 | dprintk("RPC: %5u setting alarm for %lu ms\n", | 92 | dprintk("RPC: %5u setting alarm for %u ms\n", |
93 | task->tk_pid, task->tk_timeout * 1000 / HZ); | 93 | task->tk_pid, jiffies_to_msecs(task->tk_timeout)); |
94 | 94 | ||
95 | task->u.tk_wait.expires = jiffies + task->tk_timeout; | 95 | task->u.tk_wait.expires = jiffies + task->tk_timeout; |
96 | if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires)) | 96 | if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires)) |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index e37fbed87956..ee5d3d253102 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -98,10 +98,7 @@ init_sunrpc(void) | |||
98 | if (err) | 98 | if (err) |
99 | goto out4; | 99 | goto out4; |
100 | 100 | ||
101 | err = sunrpc_debugfs_init(); | 101 | sunrpc_debugfs_init(); |
102 | if (err) | ||
103 | goto out5; | ||
104 | |||
105 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 102 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
106 | rpc_register_sysctl(); | 103 | rpc_register_sysctl(); |
107 | #endif | 104 | #endif |
@@ -109,8 +106,6 @@ init_sunrpc(void) | |||
109 | init_socket_xprt(); /* clnt sock transport */ | 106 | init_socket_xprt(); /* clnt sock transport */ |
110 | return 0; | 107 | return 0; |
111 | 108 | ||
112 | out5: | ||
113 | unregister_rpc_pipefs(); | ||
114 | out4: | 109 | out4: |
115 | unregister_pernet_subsys(&sunrpc_net_ops); | 110 | unregister_pernet_subsys(&sunrpc_net_ops); |
116 | out3: | 111 | out3: |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index ed4aa786c240..1d4fe24af06a 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1333,7 +1333,6 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net) | |||
1333 | */ | 1333 | */ |
1334 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) | 1334 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) |
1335 | { | 1335 | { |
1336 | int err; | ||
1337 | struct rpc_xprt *xprt; | 1336 | struct rpc_xprt *xprt; |
1338 | struct xprt_class *t; | 1337 | struct xprt_class *t; |
1339 | 1338 | ||
@@ -1374,11 +1373,7 @@ found: | |||
1374 | return ERR_PTR(-ENOMEM); | 1373 | return ERR_PTR(-ENOMEM); |
1375 | } | 1374 | } |
1376 | 1375 | ||
1377 | err = rpc_xprt_debugfs_register(xprt); | 1376 | rpc_xprt_debugfs_register(xprt); |
1378 | if (err) { | ||
1379 | xprt_destroy(xprt); | ||
1380 | return ERR_PTR(err); | ||
1381 | } | ||
1382 | 1377 | ||
1383 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1378 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1384 | xprt->max_reqs); | 1379 | xprt->max_reqs); |