diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2010-05-04 11:27:05 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2010-05-04 11:29:05 -0400 |
commit | 5306293c9cd2caf41849cc909281bda628bb989e (patch) | |
tree | 3be4e8231e2772c8a43ddbef5c6a72c20b3054bb /fs/nfs | |
parent | dbd65a7e44fff4741a0b2c84bd6bace85d22c242 (diff) | |
parent | 66f41d4c5c8a5deed66fdcc84509376c9a0bf9d8 (diff) |
Merge commit 'v2.6.34-rc6'
Conflicts:
fs/nfsd/nfs4callback.c
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/cache_lib.c | 1 | ||||
-rw-r--r-- | fs/nfs/callback_proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/callback_xdr.c | 2 | ||||
-rw-r--r-- | fs/nfs/client.c | 6 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 1 | ||||
-rw-r--r-- | fs/nfs/delegation.h | 6 | ||||
-rw-r--r-- | fs/nfs/dir.c | 8 | ||||
-rw-r--r-- | fs/nfs/direct.c | 1 | ||||
-rw-r--r-- | fs/nfs/dns_resolve.c | 1 | ||||
-rw-r--r-- | fs/nfs/file.c | 5 | ||||
-rw-r--r-- | fs/nfs/fscache.c | 1 | ||||
-rw-r--r-- | fs/nfs/inode.c | 11 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs2xdr.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 14 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 3 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 23 | ||||
-rw-r--r-- | fs/nfs/proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/super.c | 29 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 1 | ||||
-rw-r--r-- | fs/nfs/write.c | 95 |
25 files changed, 147 insertions, 69 deletions
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c index b4ffd0146ea6..84690319e625 100644 --- a/fs/nfs/cache_lib.c +++ b/fs/nfs/cache_lib.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
11 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
12 | #include <linux/namei.h> | 12 | #include <linux/namei.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/sunrpc/cache.h> | 14 | #include <linux/sunrpc/cache.h> |
14 | #include <linux/sunrpc/rpc_pipe_fs.h> | 15 | #include <linux/sunrpc/rpc_pipe_fs.h> |
15 | 16 | ||
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 84761b5bb8e2..a08770a7e857 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/nfs4.h> | 8 | #include <linux/nfs4.h> |
9 | #include <linux/nfs_fs.h> | 9 | #include <linux/nfs_fs.h> |
10 | #include <linux/slab.h> | ||
10 | #include "nfs4_fs.h" | 11 | #include "nfs4_fs.h" |
11 | #include "callback.h" | 12 | #include "callback.h" |
12 | #include "delegation.h" | 13 | #include "delegation.h" |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index db30c0b398b5..05af212f0edf 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/sunrpc/svc.h> | 9 | #include <linux/sunrpc/svc.h> |
10 | #include <linux/nfs4.h> | 10 | #include <linux/nfs4.h> |
11 | #include <linux/nfs_fs.h> | 11 | #include <linux/nfs_fs.h> |
12 | #include <linux/slab.h> | ||
12 | #include "nfs4_fs.h" | 13 | #include "nfs4_fs.h" |
13 | #include "callback.h" | 14 | #include "callback.h" |
14 | 15 | ||
@@ -782,6 +783,7 @@ struct svc_version nfs4_callback_version1 = { | |||
782 | .vs_proc = nfs4_callback_procedures1, | 783 | .vs_proc = nfs4_callback_procedures1, |
783 | .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, | 784 | .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, |
784 | .vs_dispatch = NULL, | 785 | .vs_dispatch = NULL, |
786 | .vs_hidden = 1, | ||
785 | }; | 787 | }; |
786 | 788 | ||
787 | struct svc_version nfs4_callback_version4 = { | 789 | struct svc_version nfs4_callback_version4 = { |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 2274f1737336..acc9c4943b84 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/vfs.h> | 35 | #include <linux/vfs.h> |
36 | #include <linux/inet.h> | 36 | #include <linux/inet.h> |
37 | #include <linux/in6.h> | 37 | #include <linux/in6.h> |
38 | #include <linux/slab.h> | ||
38 | #include <net/ipv6.h> | 39 | #include <net/ipv6.h> |
39 | #include <linux/nfs_xdr.h> | 40 | #include <linux/nfs_xdr.h> |
40 | #include <linux/sunrpc/bc_xprt.h> | 41 | #include <linux/sunrpc/bc_xprt.h> |
@@ -965,6 +966,8 @@ out_error: | |||
965 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) | 966 | static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) |
966 | { | 967 | { |
967 | target->flags = source->flags; | 968 | target->flags = source->flags; |
969 | target->rsize = source->rsize; | ||
970 | target->wsize = source->wsize; | ||
968 | target->acregmin = source->acregmin; | 971 | target->acregmin = source->acregmin; |
969 | target->acregmax = source->acregmax; | 972 | target->acregmax = source->acregmax; |
970 | target->acdirmin = source->acdirmin; | 973 | target->acdirmin = source->acdirmin; |
@@ -1293,7 +1296,8 @@ static int nfs4_init_server(struct nfs_server *server, | |||
1293 | 1296 | ||
1294 | /* Initialise the client representation from the mount data */ | 1297 | /* Initialise the client representation from the mount data */ |
1295 | server->flags = data->flags; | 1298 | server->flags = data->flags; |
1296 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR; | 1299 | server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR| |
1300 | NFS_CAP_POSIX_LOCK; | ||
1297 | server->options = data->options; | 1301 | server->options = data->options; |
1298 | 1302 | ||
1299 | /* Get a client record */ | 1303 | /* Get a client record */ |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 2563bebc4c67..15671245c6ee 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/kthread.h> | 10 | #include <linux/kthread.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
14 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
15 | 16 | ||
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 944b627ec6e1..69e7b8140122 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -71,4 +71,10 @@ static inline int nfs_inode_return_delegation(struct inode *inode) | |||
71 | } | 71 | } |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | static inline int nfs_have_delegated_attributes(struct inode *inode) | ||
75 | { | ||
76 | return nfs_have_delegation(inode, FMODE_READ) && | ||
77 | !(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED); | ||
78 | } | ||
79 | |||
74 | #endif | 80 | #endif |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a1f6b4438fb1..a7bb5c694aa3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -837,6 +837,8 @@ out_zap_parent: | |||
837 | /* If we have submounts, don't unhash ! */ | 837 | /* If we have submounts, don't unhash ! */ |
838 | if (have_submounts(dentry)) | 838 | if (have_submounts(dentry)) |
839 | goto out_valid; | 839 | goto out_valid; |
840 | if (dentry->d_flags & DCACHE_DISCONNECTED) | ||
841 | goto out_valid; | ||
840 | shrink_dcache_parent(dentry); | 842 | shrink_dcache_parent(dentry); |
841 | } | 843 | } |
842 | d_drop(dentry); | 844 | d_drop(dentry); |
@@ -1025,12 +1027,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1025 | res = NULL; | 1027 | res = NULL; |
1026 | goto out; | 1028 | goto out; |
1027 | /* This turned out not to be a regular file */ | 1029 | /* This turned out not to be a regular file */ |
1030 | case -EISDIR: | ||
1028 | case -ENOTDIR: | 1031 | case -ENOTDIR: |
1029 | goto no_open; | 1032 | goto no_open; |
1030 | case -ELOOP: | 1033 | case -ELOOP: |
1031 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1034 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
1032 | goto no_open; | 1035 | goto no_open; |
1033 | /* case -EISDIR: */ | ||
1034 | /* case -EINVAL: */ | 1036 | /* case -EINVAL: */ |
1035 | default: | 1037 | default: |
1036 | goto out; | 1038 | goto out; |
@@ -1050,7 +1052,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1050 | struct inode *dir; | 1052 | struct inode *dir; |
1051 | int openflags, ret = 0; | 1053 | int openflags, ret = 0; |
1052 | 1054 | ||
1053 | if (!is_atomic_open(nd)) | 1055 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) |
1054 | goto no_open; | 1056 | goto no_open; |
1055 | parent = dget_parent(dentry); | 1057 | parent = dget_parent(dentry); |
1056 | dir = parent->d_inode; | 1058 | dir = parent->d_inode; |
@@ -1789,7 +1791,7 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str | |||
1789 | cache = nfs_access_search_rbtree(inode, cred); | 1791 | cache = nfs_access_search_rbtree(inode, cred); |
1790 | if (cache == NULL) | 1792 | if (cache == NULL) |
1791 | goto out; | 1793 | goto out; |
1792 | if (!nfs_have_delegation(inode, FMODE_READ) && | 1794 | if (!nfs_have_delegated_attributes(inode) && |
1793 | !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) | 1795 | !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) |
1794 | goto out_stale; | 1796 | goto out_stale; |
1795 | res->jiffies = cache->jiffies; | 1797 | res->jiffies = cache->jiffies; |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 0d289823e856..ad4cd31d6050 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/file.h> | 44 | #include <linux/file.h> |
45 | #include <linux/pagemap.h> | 45 | #include <linux/pagemap.h> |
46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
47 | #include <linux/slab.h> | ||
47 | 48 | ||
48 | #include <linux/nfs_fs.h> | 49 | #include <linux/nfs_fs.h> |
49 | #include <linux/nfs_page.h> | 50 | #include <linux/nfs_page.h> |
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 3f0cd4dfddaf..76fd235d0024 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/hash.h> | 9 | #include <linux/hash.h> |
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/kmod.h> | 11 | #include <linux/kmod.h> |
12 | #include <linux/slab.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/socket.h> | 14 | #include <linux/socket.h> |
14 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index ae8d02294e46..8d965bddb87e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -24,9 +24,9 @@ | |||
24 | #include <linux/nfs_fs.h> | 24 | #include <linux/nfs_fs.h> |
25 | #include <linux/nfs_mount.h> | 25 | #include <linux/nfs_mount.h> |
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/slab.h> | ||
28 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
29 | #include <linux/aio.h> | 28 | #include <linux/aio.h> |
29 | #include <linux/gfp.h> | ||
30 | 30 | ||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <asm/system.h> | 32 | #include <asm/system.h> |
@@ -491,7 +491,8 @@ static int nfs_release_page(struct page *page, gfp_t gfp) | |||
491 | { | 491 | { |
492 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | 492 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); |
493 | 493 | ||
494 | if (gfp & __GFP_WAIT) | 494 | /* Only do I/O if gfp is a superset of GFP_KERNEL */ |
495 | if ((gfp & GFP_KERNEL) == GFP_KERNEL) | ||
495 | nfs_wb_page(page->mapping->host, page); | 496 | nfs_wb_page(page->mapping->host, page); |
496 | /* If PagePrivate() is set, then the page is not freeable */ | 497 | /* If PagePrivate() is set, then the page is not freeable */ |
497 | if (PagePrivate(page)) | 498 | if (PagePrivate(page)) |
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 237874f1af23..a6b16ed93229 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/nfs_fs_sb.h> | 17 | #include <linux/nfs_fs_sb.h> |
18 | #include <linux/in6.h> | 18 | #include <linux/in6.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/slab.h> | ||
20 | 21 | ||
21 | #include "internal.h" | 22 | #include "internal.h" |
22 | #include "iostat.h" | 23 | #include "iostat.h" |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 657201acda84..50a56edca0b5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/vfs.h> | 36 | #include <linux/vfs.h> |
37 | #include <linux/inet.h> | 37 | #include <linux/inet.h> |
38 | #include <linux/nfs_xdr.h> | 38 | #include <linux/nfs_xdr.h> |
39 | #include <linux/slab.h> | ||
39 | 40 | ||
40 | #include <asm/system.h> | 41 | #include <asm/system.h> |
41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
@@ -622,10 +623,10 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
622 | list_for_each_entry(pos, &nfsi->open_files, list) { | 623 | list_for_each_entry(pos, &nfsi->open_files, list) { |
623 | if (cred != NULL && pos->cred != cred) | 624 | if (cred != NULL && pos->cred != cred) |
624 | continue; | 625 | continue; |
625 | if ((pos->mode & mode) == mode) { | 626 | if ((pos->mode & (FMODE_READ|FMODE_WRITE)) != mode) |
626 | ctx = get_nfs_open_context(pos); | 627 | continue; |
627 | break; | 628 | ctx = get_nfs_open_context(pos); |
628 | } | 629 | break; |
629 | } | 630 | } |
630 | spin_unlock(&inode->i_lock); | 631 | spin_unlock(&inode->i_lock); |
631 | return ctx; | 632 | return ctx; |
@@ -729,7 +730,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
729 | { | 730 | { |
730 | struct nfs_inode *nfsi = NFS_I(inode); | 731 | struct nfs_inode *nfsi = NFS_I(inode); |
731 | 732 | ||
732 | if (nfs_have_delegation(inode, FMODE_READ)) | 733 | if (nfs_have_delegated_attributes(inode)) |
733 | return 0; | 734 | return 0; |
734 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | 735 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); |
735 | } | 736 | } |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 40c766782891..7888cf36022d 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/dcache.h> | 10 | #include <linux/dcache.h> |
11 | #include <linux/gfp.h> | ||
11 | #include <linux/mount.h> | 12 | #include <linux/mount.h> |
12 | #include <linux/namei.h> | 13 | #include <linux/namei.h> |
13 | #include <linux/nfs_fs.h> | 14 | #include <linux/nfs_fs.h> |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 7bc2da8efd4a..81cf14257916 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/param.h> | 12 | #include <linux/param.h> |
13 | #include <linux/time.h> | 13 | #include <linux/time.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
17 | #include <linux/string.h> | 16 | #include <linux/string.h> |
18 | #include <linux/in.h> | 17 | #include <linux/in.h> |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index bac60515a4b3..d150ae0c5ecd 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/fs.h> | 1 | #include <linux/fs.h> |
2 | #include <linux/gfp.h> | ||
2 | #include <linux/nfs.h> | 3 | #include <linux/nfs.h> |
3 | #include <linux/nfs3.h> | 4 | #include <linux/nfs3.h> |
4 | #include <linux/nfs_fs.h> | 5 | #include <linux/nfs_fs.h> |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 24992f0a29f2..e701002694e5 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/sunrpc/clnt.h> | 12 | #include <linux/sunrpc/clnt.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/nfs.h> | 14 | #include <linux/nfs.h> |
14 | #include <linux/nfs3.h> | 15 | #include <linux/nfs3.h> |
15 | #include <linux/nfs_fs.h> | 16 | #include <linux/nfs_fs.h> |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 5fe5492fbd29..56a86f6ac8b5 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/param.h> | 9 | #include <linux/param.h> |
10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/slab.h> | ||
13 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
14 | #include <linux/string.h> | 13 | #include <linux/string.h> |
15 | #include <linux/in.h> | 14 | #include <linux/in.h> |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index fa3408f20112..f071d12c613b 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
12 | #include <linux/namei.h> | 12 | #include <linux/namei.h> |
13 | #include <linux/nfs_fs.h> | 13 | #include <linux/nfs_fs.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/string.h> | 15 | #include <linux/string.h> |
15 | #include <linux/sunrpc/clnt.h> | 16 | #include <linux/sunrpc/clnt.h> |
16 | #include <linux/vfs.h> | 17 | #include <linux/vfs.h> |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index eda74c42d552..071fcedd517c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
40 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
42 | #include <linux/slab.h> | ||
42 | #include <linux/sunrpc/clnt.h> | 43 | #include <linux/sunrpc/clnt.h> |
43 | #include <linux/nfs.h> | 44 | #include <linux/nfs.h> |
44 | #include <linux/nfs4.h> | 45 | #include <linux/nfs4.h> |
@@ -1522,6 +1523,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1522 | nfs_post_op_update_inode(dir, o_res->dir_attr); | 1523 | nfs_post_op_update_inode(dir, o_res->dir_attr); |
1523 | } else | 1524 | } else |
1524 | nfs_refresh_inode(dir, o_res->dir_attr); | 1525 | nfs_refresh_inode(dir, o_res->dir_attr); |
1526 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) | ||
1527 | server->caps &= ~NFS_CAP_POSIX_LOCK; | ||
1525 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 1528 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
1526 | status = _nfs4_proc_open_confirm(data); | 1529 | status = _nfs4_proc_open_confirm(data); |
1527 | if (status != 0) | 1530 | if (status != 0) |
@@ -1663,7 +1666,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in | |||
1663 | status = PTR_ERR(state); | 1666 | status = PTR_ERR(state); |
1664 | if (IS_ERR(state)) | 1667 | if (IS_ERR(state)) |
1665 | goto err_opendata_put; | 1668 | goto err_opendata_put; |
1666 | if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0) | 1669 | if (server->caps & NFS_CAP_POSIX_LOCK) |
1667 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 1670 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
1668 | nfs4_opendata_put(opendata); | 1671 | nfs4_opendata_put(opendata); |
1669 | nfs4_put_state_owner(sp); | 1672 | nfs4_put_state_owner(sp); |
@@ -2067,8 +2070,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st | |||
2067 | case -EDQUOT: | 2070 | case -EDQUOT: |
2068 | case -ENOSPC: | 2071 | case -ENOSPC: |
2069 | case -EROFS: | 2072 | case -EROFS: |
2070 | lookup_instantiate_filp(nd, (struct dentry *)state, NULL); | 2073 | return PTR_ERR(state); |
2071 | return 1; | ||
2072 | default: | 2074 | default: |
2073 | goto out_drop; | 2075 | goto out_drop; |
2074 | } | 2076 | } |
@@ -5107,6 +5109,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, | |||
5107 | res = kzalloc(sizeof(*res), GFP_KERNEL); | 5109 | res = kzalloc(sizeof(*res), GFP_KERNEL); |
5108 | if (!args || !res) { | 5110 | if (!args || !res) { |
5109 | kfree(args); | 5111 | kfree(args); |
5112 | kfree(res); | ||
5110 | nfs_put_client(clp); | 5113 | nfs_put_client(clp); |
5111 | return -ENOMEM; | 5114 | return -ENOMEM; |
5112 | } | 5115 | } |
@@ -5215,9 +5218,12 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5215 | msg.rpc_resp = &calldata->res; | 5218 | msg.rpc_resp = &calldata->res; |
5216 | task_setup_data.callback_data = calldata; | 5219 | task_setup_data.callback_data = calldata; |
5217 | task = rpc_run_task(&task_setup_data); | 5220 | task = rpc_run_task(&task_setup_data); |
5218 | if (IS_ERR(task)) | 5221 | if (IS_ERR(task)) { |
5219 | status = PTR_ERR(task); | 5222 | status = PTR_ERR(task); |
5223 | goto out; | ||
5224 | } | ||
5220 | rpc_put_task(task); | 5225 | rpc_put_task(task); |
5226 | return 0; | ||
5221 | out: | 5227 | out: |
5222 | dprintk("<-- %s status=%d\n", __func__, status); | 5228 | dprintk("<-- %s status=%d\n", __func__, status); |
5223 | return status; | 5229 | return status; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4d338be492cb..38f3b582e7c2 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/param.h> | 38 | #include <linux/param.h> |
39 | #include <linux/time.h> | 39 | #include <linux/time.h> |
40 | #include <linux/mm.h> | 40 | #include <linux/mm.h> |
41 | #include <linux/slab.h> | ||
42 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
43 | #include <linux/string.h> | 42 | #include <linux/string.h> |
44 | #include <linux/in.h> | 43 | #include <linux/in.h> |
@@ -5552,6 +5551,8 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf | |||
5552 | if (status != 0) | 5551 | if (status != 0) |
5553 | goto out; | 5552 | goto out; |
5554 | status = decode_delegreturn(&xdr); | 5553 | status = decode_delegreturn(&xdr); |
5554 | if (status != 0) | ||
5555 | goto out; | ||
5555 | decode_getfattr(&xdr, res->fattr, res->server, | 5556 | decode_getfattr(&xdr, res->fattr, res->server, |
5556 | !RPC_IS_ASYNC(rqstp->rq_task)); | 5557 | !RPC_IS_ASYNC(rqstp->rq_task)); |
5557 | out: | 5558 | out: |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index a12c45b65dd4..29d9d36cd5f4 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -112,12 +112,10 @@ void nfs_unlock_request(struct nfs_page *req) | |||
112 | */ | 112 | */ |
113 | int nfs_set_page_tag_locked(struct nfs_page *req) | 113 | int nfs_set_page_tag_locked(struct nfs_page *req) |
114 | { | 114 | { |
115 | struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode); | ||
116 | |||
117 | if (!nfs_lock_request_dontget(req)) | 115 | if (!nfs_lock_request_dontget(req)) |
118 | return 0; | 116 | return 0; |
119 | if (req->wb_page != NULL) | 117 | if (req->wb_page != NULL) |
120 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 118 | radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); |
121 | return 1; | 119 | return 1; |
122 | } | 120 | } |
123 | 121 | ||
@@ -126,10 +124,10 @@ int nfs_set_page_tag_locked(struct nfs_page *req) | |||
126 | */ | 124 | */ |
127 | void nfs_clear_page_tag_locked(struct nfs_page *req) | 125 | void nfs_clear_page_tag_locked(struct nfs_page *req) |
128 | { | 126 | { |
129 | struct inode *inode = req->wb_context->path.dentry->d_inode; | ||
130 | struct nfs_inode *nfsi = NFS_I(inode); | ||
131 | |||
132 | if (req->wb_page != NULL) { | 127 | if (req->wb_page != NULL) { |
128 | struct inode *inode = req->wb_context->path.dentry->d_inode; | ||
129 | struct nfs_inode *nfsi = NFS_I(inode); | ||
130 | |||
133 | spin_lock(&inode->i_lock); | 131 | spin_lock(&inode->i_lock); |
134 | radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 132 | radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); |
135 | nfs_unlock_request(req); | 133 | nfs_unlock_request(req); |
@@ -142,16 +140,22 @@ void nfs_clear_page_tag_locked(struct nfs_page *req) | |||
142 | * nfs_clear_request - Free up all resources allocated to the request | 140 | * nfs_clear_request - Free up all resources allocated to the request |
143 | * @req: | 141 | * @req: |
144 | * | 142 | * |
145 | * Release page resources associated with a write request after it | 143 | * Release page and open context resources associated with a read/write |
146 | * has completed. | 144 | * request after it has completed. |
147 | */ | 145 | */ |
148 | void nfs_clear_request(struct nfs_page *req) | 146 | void nfs_clear_request(struct nfs_page *req) |
149 | { | 147 | { |
150 | struct page *page = req->wb_page; | 148 | struct page *page = req->wb_page; |
149 | struct nfs_open_context *ctx = req->wb_context; | ||
150 | |||
151 | if (page != NULL) { | 151 | if (page != NULL) { |
152 | page_cache_release(page); | 152 | page_cache_release(page); |
153 | req->wb_page = NULL; | 153 | req->wb_page = NULL; |
154 | } | 154 | } |
155 | if (ctx != NULL) { | ||
156 | put_nfs_open_context(ctx); | ||
157 | req->wb_context = NULL; | ||
158 | } | ||
155 | } | 159 | } |
156 | 160 | ||
157 | 161 | ||
@@ -165,9 +169,8 @@ static void nfs_free_request(struct kref *kref) | |||
165 | { | 169 | { |
166 | struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref); | 170 | struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref); |
167 | 171 | ||
168 | /* Release struct file or cached credential */ | 172 | /* Release struct file and open context */ |
169 | nfs_clear_request(req); | 173 | nfs_clear_request(req); |
170 | put_nfs_open_context(req->wb_context); | ||
171 | nfs_page_free(req); | 174 | nfs_page_free(req); |
172 | } | 175 | } |
173 | 176 | ||
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index c752d944fe9e..0288be80444f 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -29,7 +29,6 @@ | |||
29 | 29 | ||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/param.h> | 31 | #include <linux/param.h> |
32 | #include <linux/slab.h> | ||
33 | #include <linux/time.h> | 32 | #include <linux/time.h> |
34 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index f1afee4eea77..b4148fc00f9f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/vfs.h> | 48 | #include <linux/vfs.h> |
49 | #include <linux/inet.h> | 49 | #include <linux/inet.h> |
50 | #include <linux/in6.h> | 50 | #include <linux/in6.h> |
51 | #include <linux/slab.h> | ||
51 | #include <net/ipv6.h> | 52 | #include <net/ipv6.h> |
52 | #include <linux/netdevice.h> | 53 | #include <linux/netdevice.h> |
53 | #include <linux/nfs_xdr.h> | 54 | #include <linux/nfs_xdr.h> |
@@ -2186,6 +2187,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2186 | if (data->version == 4) { | 2187 | if (data->version == 4) { |
2187 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2188 | error = nfs4_try_mount(flags, dev_name, data, mnt); |
2188 | kfree(data->client_address); | 2189 | kfree(data->client_address); |
2190 | kfree(data->nfs_server.export_path); | ||
2189 | goto out; | 2191 | goto out; |
2190 | } | 2192 | } |
2191 | #endif /* CONFIG_NFS_V4 */ | 2193 | #endif /* CONFIG_NFS_V4 */ |
@@ -2214,7 +2216,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2214 | } else { | 2216 | } else { |
2215 | error = nfs_bdi_register(server); | 2217 | error = nfs_bdi_register(server); |
2216 | if (error) | 2218 | if (error) |
2217 | goto error_splat_super; | 2219 | goto error_splat_bdi; |
2218 | } | 2220 | } |
2219 | 2221 | ||
2220 | if (!s->s_root) { | 2222 | if (!s->s_root) { |
@@ -2256,6 +2258,9 @@ out_err_nosb: | |||
2256 | error_splat_root: | 2258 | error_splat_root: |
2257 | dput(mntroot); | 2259 | dput(mntroot); |
2258 | error_splat_super: | 2260 | error_splat_super: |
2261 | if (server && !s->s_root) | ||
2262 | bdi_unregister(&server->backing_dev_info); | ||
2263 | error_splat_bdi: | ||
2259 | deactivate_locked_super(s); | 2264 | deactivate_locked_super(s); |
2260 | goto out; | 2265 | goto out; |
2261 | } | 2266 | } |
@@ -2326,7 +2331,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
2326 | } else { | 2331 | } else { |
2327 | error = nfs_bdi_register(server); | 2332 | error = nfs_bdi_register(server); |
2328 | if (error) | 2333 | if (error) |
2329 | goto error_splat_super; | 2334 | goto error_splat_bdi; |
2330 | } | 2335 | } |
2331 | 2336 | ||
2332 | if (!s->s_root) { | 2337 | if (!s->s_root) { |
@@ -2363,6 +2368,9 @@ out_err_noserver: | |||
2363 | return error; | 2368 | return error; |
2364 | 2369 | ||
2365 | error_splat_super: | 2370 | error_splat_super: |
2371 | if (server && !s->s_root) | ||
2372 | bdi_unregister(&server->backing_dev_info); | ||
2373 | error_splat_bdi: | ||
2366 | deactivate_locked_super(s); | 2374 | deactivate_locked_super(s); |
2367 | dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); | 2375 | dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); |
2368 | return error; | 2376 | return error; |
@@ -2578,7 +2586,7 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type, | |||
2578 | } else { | 2586 | } else { |
2579 | error = nfs_bdi_register(server); | 2587 | error = nfs_bdi_register(server); |
2580 | if (error) | 2588 | if (error) |
2581 | goto error_splat_super; | 2589 | goto error_splat_bdi; |
2582 | } | 2590 | } |
2583 | 2591 | ||
2584 | if (!s->s_root) { | 2592 | if (!s->s_root) { |
@@ -2616,6 +2624,9 @@ out_free: | |||
2616 | error_splat_root: | 2624 | error_splat_root: |
2617 | dput(mntroot); | 2625 | dput(mntroot); |
2618 | error_splat_super: | 2626 | error_splat_super: |
2627 | if (server && !s->s_root) | ||
2628 | bdi_unregister(&server->backing_dev_info); | ||
2629 | error_splat_bdi: | ||
2619 | deactivate_locked_super(s); | 2630 | deactivate_locked_super(s); |
2620 | goto out; | 2631 | goto out; |
2621 | } | 2632 | } |
@@ -2647,7 +2658,7 @@ static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt) | |||
2647 | devname = nfs_path(path->mnt->mnt_devname, | 2658 | devname = nfs_path(path->mnt->mnt_devname, |
2648 | path->mnt->mnt_root, path->dentry, | 2659 | path->mnt->mnt_root, path->dentry, |
2649 | page, PAGE_SIZE); | 2660 | page, PAGE_SIZE); |
2650 | if (devname == NULL) | 2661 | if (IS_ERR(devname)) |
2651 | goto out_freepage; | 2662 | goto out_freepage; |
2652 | tmp = kstrdup(devname, GFP_KERNEL); | 2663 | tmp = kstrdup(devname, GFP_KERNEL); |
2653 | if (tmp == NULL) | 2664 | if (tmp == NULL) |
@@ -2811,7 +2822,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
2811 | } else { | 2822 | } else { |
2812 | error = nfs_bdi_register(server); | 2823 | error = nfs_bdi_register(server); |
2813 | if (error) | 2824 | if (error) |
2814 | goto error_splat_super; | 2825 | goto error_splat_bdi; |
2815 | } | 2826 | } |
2816 | 2827 | ||
2817 | if (!s->s_root) { | 2828 | if (!s->s_root) { |
@@ -2847,6 +2858,9 @@ out_err_noserver: | |||
2847 | return error; | 2858 | return error; |
2848 | 2859 | ||
2849 | error_splat_super: | 2860 | error_splat_super: |
2861 | if (server && !s->s_root) | ||
2862 | bdi_unregister(&server->backing_dev_info); | ||
2863 | error_splat_bdi: | ||
2850 | deactivate_locked_super(s); | 2864 | deactivate_locked_super(s); |
2851 | dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); | 2865 | dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); |
2852 | return error; | 2866 | return error; |
@@ -2893,7 +2907,7 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type, | |||
2893 | } else { | 2907 | } else { |
2894 | error = nfs_bdi_register(server); | 2908 | error = nfs_bdi_register(server); |
2895 | if (error) | 2909 | if (error) |
2896 | goto error_splat_super; | 2910 | goto error_splat_bdi; |
2897 | } | 2911 | } |
2898 | 2912 | ||
2899 | if (!s->s_root) { | 2913 | if (!s->s_root) { |
@@ -2929,6 +2943,9 @@ out_err_noserver: | |||
2929 | return error; | 2943 | return error; |
2930 | 2944 | ||
2931 | error_splat_super: | 2945 | error_splat_super: |
2946 | if (server && !s->s_root) | ||
2947 | bdi_unregister(&server->backing_dev_info); | ||
2948 | error_splat_bdi: | ||
2932 | deactivate_locked_super(s); | 2949 | deactivate_locked_super(s); |
2933 | dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); | 2950 | dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); |
2934 | return error; | 2951 | return error; |
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 2ea9e5c27e55..05c9e02f4153 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
20 | #include <linux/stat.h> | 20 | #include <linux/stat.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/slab.h> | ||
23 | #include <linux/string.h> | 22 | #include <linux/string.h> |
24 | #include <linux/namei.h> | 23 | #include <linux/namei.h> |
25 | 24 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 53ff70e23993..3aea3ca98ab7 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -201,6 +201,7 @@ static int nfs_set_page_writeback(struct page *page) | |||
201 | struct inode *inode = page->mapping->host; | 201 | struct inode *inode = page->mapping->host; |
202 | struct nfs_server *nfss = NFS_SERVER(inode); | 202 | struct nfs_server *nfss = NFS_SERVER(inode); |
203 | 203 | ||
204 | page_cache_get(page); | ||
204 | if (atomic_long_inc_return(&nfss->writeback) > | 205 | if (atomic_long_inc_return(&nfss->writeback) > |
205 | NFS_CONGESTION_ON_THRESH) { | 206 | NFS_CONGESTION_ON_THRESH) { |
206 | set_bdi_congested(&nfss->backing_dev_info, | 207 | set_bdi_congested(&nfss->backing_dev_info, |
@@ -216,6 +217,7 @@ static void nfs_end_page_writeback(struct page *page) | |||
216 | struct nfs_server *nfss = NFS_SERVER(inode); | 217 | struct nfs_server *nfss = NFS_SERVER(inode); |
217 | 218 | ||
218 | end_page_writeback(page); | 219 | end_page_writeback(page); |
220 | page_cache_release(page); | ||
219 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) | 221 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) |
220 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); | 222 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
221 | } | 223 | } |
@@ -421,6 +423,7 @@ static void | |||
421 | nfs_mark_request_dirty(struct nfs_page *req) | 423 | nfs_mark_request_dirty(struct nfs_page *req) |
422 | { | 424 | { |
423 | __set_page_dirty_nobuffers(req->wb_page); | 425 | __set_page_dirty_nobuffers(req->wb_page); |
426 | __mark_inode_dirty(req->wb_page->mapping->host, I_DIRTY_DATASYNC); | ||
424 | } | 427 | } |
425 | 428 | ||
426 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 429 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
@@ -660,9 +663,11 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
660 | req = nfs_setup_write_request(ctx, page, offset, count); | 663 | req = nfs_setup_write_request(ctx, page, offset, count); |
661 | if (IS_ERR(req)) | 664 | if (IS_ERR(req)) |
662 | return PTR_ERR(req); | 665 | return PTR_ERR(req); |
666 | nfs_mark_request_dirty(req); | ||
663 | /* Update file length */ | 667 | /* Update file length */ |
664 | nfs_grow_file(page, offset, count); | 668 | nfs_grow_file(page, offset, count); |
665 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | 669 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); |
670 | nfs_mark_request_dirty(req); | ||
666 | nfs_clear_page_tag_locked(req); | 671 | nfs_clear_page_tag_locked(req); |
667 | return 0; | 672 | return 0; |
668 | } | 673 | } |
@@ -739,8 +744,6 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
739 | status = nfs_writepage_setup(ctx, page, offset, count); | 744 | status = nfs_writepage_setup(ctx, page, offset, count); |
740 | if (status < 0) | 745 | if (status < 0) |
741 | nfs_set_pageerror(page); | 746 | nfs_set_pageerror(page); |
742 | else | ||
743 | __set_page_dirty_nobuffers(page); | ||
744 | 747 | ||
745 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", | 748 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", |
746 | status, (long long)i_size_read(inode)); | 749 | status, (long long)i_size_read(inode)); |
@@ -749,13 +752,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
749 | 752 | ||
750 | static void nfs_writepage_release(struct nfs_page *req) | 753 | static void nfs_writepage_release(struct nfs_page *req) |
751 | { | 754 | { |
755 | struct page *page = req->wb_page; | ||
752 | 756 | ||
753 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { | 757 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) |
754 | nfs_end_page_writeback(req->wb_page); | ||
755 | nfs_inode_remove_request(req); | 758 | nfs_inode_remove_request(req); |
756 | } else | ||
757 | nfs_end_page_writeback(req->wb_page); | ||
758 | nfs_clear_page_tag_locked(req); | 759 | nfs_clear_page_tag_locked(req); |
760 | nfs_end_page_writeback(page); | ||
759 | } | 761 | } |
760 | 762 | ||
761 | static int flush_task_priority(int how) | 763 | static int flush_task_priority(int how) |
@@ -779,7 +781,6 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
779 | int how) | 781 | int how) |
780 | { | 782 | { |
781 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 783 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
782 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | ||
783 | int priority = flush_task_priority(how); | 784 | int priority = flush_task_priority(how); |
784 | struct rpc_task *task; | 785 | struct rpc_task *task; |
785 | struct rpc_message msg = { | 786 | struct rpc_message msg = { |
@@ -794,9 +795,10 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
794 | .callback_ops = call_ops, | 795 | .callback_ops = call_ops, |
795 | .callback_data = data, | 796 | .callback_data = data, |
796 | .workqueue = nfsiod_workqueue, | 797 | .workqueue = nfsiod_workqueue, |
797 | .flags = flags, | 798 | .flags = RPC_TASK_ASYNC, |
798 | .priority = priority, | 799 | .priority = priority, |
799 | }; | 800 | }; |
801 | int ret = 0; | ||
800 | 802 | ||
801 | /* Set up the RPC argument and reply structs | 803 | /* Set up the RPC argument and reply structs |
802 | * NB: take care not to mess about with data->commit et al. */ | 804 | * NB: take care not to mess about with data->commit et al. */ |
@@ -835,10 +837,18 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
835 | (unsigned long long)data->args.offset); | 837 | (unsigned long long)data->args.offset); |
836 | 838 | ||
837 | task = rpc_run_task(&task_setup_data); | 839 | task = rpc_run_task(&task_setup_data); |
838 | if (IS_ERR(task)) | 840 | if (IS_ERR(task)) { |
839 | return PTR_ERR(task); | 841 | ret = PTR_ERR(task); |
842 | goto out; | ||
843 | } | ||
844 | if (how & FLUSH_SYNC) { | ||
845 | ret = rpc_wait_for_completion_task(task); | ||
846 | if (ret == 0) | ||
847 | ret = task->tk_status; | ||
848 | } | ||
840 | rpc_put_task(task); | 849 | rpc_put_task(task); |
841 | return 0; | 850 | out: |
851 | return ret; | ||
842 | } | 852 | } |
843 | 853 | ||
844 | /* If a nfs_flush_* function fails, it should remove reqs from @head and | 854 | /* If a nfs_flush_* function fails, it should remove reqs from @head and |
@@ -847,9 +857,11 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
847 | */ | 857 | */ |
848 | static void nfs_redirty_request(struct nfs_page *req) | 858 | static void nfs_redirty_request(struct nfs_page *req) |
849 | { | 859 | { |
860 | struct page *page = req->wb_page; | ||
861 | |||
850 | nfs_mark_request_dirty(req); | 862 | nfs_mark_request_dirty(req); |
851 | nfs_end_page_writeback(req->wb_page); | ||
852 | nfs_clear_page_tag_locked(req); | 863 | nfs_clear_page_tag_locked(req); |
864 | nfs_end_page_writeback(page); | ||
853 | } | 865 | } |
854 | 866 | ||
855 | /* | 867 | /* |
@@ -1084,16 +1096,15 @@ static void nfs_writeback_release_full(void *calldata) | |||
1084 | if (nfs_write_need_commit(data)) { | 1096 | if (nfs_write_need_commit(data)) { |
1085 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1097 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1086 | nfs_mark_request_commit(req); | 1098 | nfs_mark_request_commit(req); |
1087 | nfs_end_page_writeback(page); | ||
1088 | dprintk(" marked for commit\n"); | 1099 | dprintk(" marked for commit\n"); |
1089 | goto next; | 1100 | goto next; |
1090 | } | 1101 | } |
1091 | dprintk(" OK\n"); | 1102 | dprintk(" OK\n"); |
1092 | remove_request: | 1103 | remove_request: |
1093 | nfs_end_page_writeback(page); | ||
1094 | nfs_inode_remove_request(req); | 1104 | nfs_inode_remove_request(req); |
1095 | next: | 1105 | next: |
1096 | nfs_clear_page_tag_locked(req); | 1106 | nfs_clear_page_tag_locked(req); |
1107 | nfs_end_page_writeback(page); | ||
1097 | } | 1108 | } |
1098 | nfs_writedata_release(calldata); | 1109 | nfs_writedata_release(calldata); |
1099 | } | 1110 | } |
@@ -1190,6 +1201,25 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1190 | 1201 | ||
1191 | 1202 | ||
1192 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1203 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1204 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) | ||
1205 | { | ||
1206 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) | ||
1207 | return 1; | ||
1208 | if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, | ||
1209 | NFS_INO_COMMIT, nfs_wait_bit_killable, | ||
1210 | TASK_KILLABLE)) | ||
1211 | return 1; | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | static void nfs_commit_clear_lock(struct nfs_inode *nfsi) | ||
1216 | { | ||
1217 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); | ||
1218 | smp_mb__after_clear_bit(); | ||
1219 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); | ||
1220 | } | ||
1221 | |||
1222 | |||
1193 | static void nfs_commitdata_release(void *data) | 1223 | static void nfs_commitdata_release(void *data) |
1194 | { | 1224 | { |
1195 | struct nfs_write_data *wdata = data; | 1225 | struct nfs_write_data *wdata = data; |
@@ -1207,7 +1237,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1207 | { | 1237 | { |
1208 | struct nfs_page *first = nfs_list_entry(head->next); | 1238 | struct nfs_page *first = nfs_list_entry(head->next); |
1209 | struct inode *inode = first->wb_context->path.dentry->d_inode; | 1239 | struct inode *inode = first->wb_context->path.dentry->d_inode; |
1210 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | ||
1211 | int priority = flush_task_priority(how); | 1240 | int priority = flush_task_priority(how); |
1212 | struct rpc_task *task; | 1241 | struct rpc_task *task; |
1213 | struct rpc_message msg = { | 1242 | struct rpc_message msg = { |
@@ -1222,7 +1251,7 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1222 | .callback_ops = &nfs_commit_ops, | 1251 | .callback_ops = &nfs_commit_ops, |
1223 | .callback_data = data, | 1252 | .callback_data = data, |
1224 | .workqueue = nfsiod_workqueue, | 1253 | .workqueue = nfsiod_workqueue, |
1225 | .flags = flags, | 1254 | .flags = RPC_TASK_ASYNC, |
1226 | .priority = priority, | 1255 | .priority = priority, |
1227 | }; | 1256 | }; |
1228 | 1257 | ||
@@ -1282,6 +1311,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1282 | BDI_RECLAIMABLE); | 1311 | BDI_RECLAIMABLE); |
1283 | nfs_clear_page_tag_locked(req); | 1312 | nfs_clear_page_tag_locked(req); |
1284 | } | 1313 | } |
1314 | nfs_commit_clear_lock(NFS_I(inode)); | ||
1285 | return -ENOMEM; | 1315 | return -ENOMEM; |
1286 | } | 1316 | } |
1287 | 1317 | ||
@@ -1337,6 +1367,7 @@ static void nfs_commit_release(void *calldata) | |||
1337 | next: | 1367 | next: |
1338 | nfs_clear_page_tag_locked(req); | 1368 | nfs_clear_page_tag_locked(req); |
1339 | } | 1369 | } |
1370 | nfs_commit_clear_lock(NFS_I(data->inode)); | ||
1340 | nfs_commitdata_release(calldata); | 1371 | nfs_commitdata_release(calldata); |
1341 | } | 1372 | } |
1342 | 1373 | ||
@@ -1351,8 +1382,11 @@ static const struct rpc_call_ops nfs_commit_ops = { | |||
1351 | static int nfs_commit_inode(struct inode *inode, int how) | 1382 | static int nfs_commit_inode(struct inode *inode, int how) |
1352 | { | 1383 | { |
1353 | LIST_HEAD(head); | 1384 | LIST_HEAD(head); |
1354 | int res; | 1385 | int may_wait = how & FLUSH_SYNC; |
1386 | int res = 0; | ||
1355 | 1387 | ||
1388 | if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) | ||
1389 | goto out; | ||
1356 | spin_lock(&inode->i_lock); | 1390 | spin_lock(&inode->i_lock); |
1357 | res = nfs_scan_commit(inode, &head, 0, 0); | 1391 | res = nfs_scan_commit(inode, &head, 0, 0); |
1358 | spin_unlock(&inode->i_lock); | 1392 | spin_unlock(&inode->i_lock); |
@@ -1360,7 +1394,13 @@ static int nfs_commit_inode(struct inode *inode, int how) | |||
1360 | int error = nfs_commit_list(inode, &head, how); | 1394 | int error = nfs_commit_list(inode, &head, how); |
1361 | if (error < 0) | 1395 | if (error < 0) |
1362 | return error; | 1396 | return error; |
1363 | } | 1397 | if (may_wait) |
1398 | wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, | ||
1399 | nfs_wait_bit_killable, | ||
1400 | TASK_KILLABLE); | ||
1401 | } else | ||
1402 | nfs_commit_clear_lock(NFS_I(inode)); | ||
1403 | out: | ||
1364 | return res; | 1404 | return res; |
1365 | } | 1405 | } |
1366 | 1406 | ||
@@ -1432,6 +1472,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
1432 | 1472 | ||
1433 | BUG_ON(!PageLocked(page)); | 1473 | BUG_ON(!PageLocked(page)); |
1434 | for (;;) { | 1474 | for (;;) { |
1475 | wait_on_page_writeback(page); | ||
1435 | req = nfs_page_find_request(page); | 1476 | req = nfs_page_find_request(page); |
1436 | if (req == NULL) | 1477 | if (req == NULL) |
1437 | break; | 1478 | break; |
@@ -1466,30 +1507,18 @@ int nfs_wb_page(struct inode *inode, struct page *page) | |||
1466 | .range_start = range_start, | 1507 | .range_start = range_start, |
1467 | .range_end = range_end, | 1508 | .range_end = range_end, |
1468 | }; | 1509 | }; |
1469 | struct nfs_page *req; | ||
1470 | int need_commit; | ||
1471 | int ret; | 1510 | int ret; |
1472 | 1511 | ||
1473 | while(PagePrivate(page)) { | 1512 | while(PagePrivate(page)) { |
1513 | wait_on_page_writeback(page); | ||
1474 | if (clear_page_dirty_for_io(page)) { | 1514 | if (clear_page_dirty_for_io(page)) { |
1475 | ret = nfs_writepage_locked(page, &wbc); | 1515 | ret = nfs_writepage_locked(page, &wbc); |
1476 | if (ret < 0) | 1516 | if (ret < 0) |
1477 | goto out_error; | 1517 | goto out_error; |
1478 | } | 1518 | } |
1479 | req = nfs_find_and_lock_request(page); | 1519 | ret = sync_inode(inode, &wbc); |
1480 | if (!req) | 1520 | if (ret < 0) |
1481 | break; | ||
1482 | if (IS_ERR(req)) { | ||
1483 | ret = PTR_ERR(req); | ||
1484 | goto out_error; | 1521 | goto out_error; |
1485 | } | ||
1486 | need_commit = test_bit(PG_CLEAN, &req->wb_flags); | ||
1487 | nfs_clear_page_tag_locked(req); | ||
1488 | if (need_commit) { | ||
1489 | ret = nfs_commit_inode(inode, FLUSH_SYNC); | ||
1490 | if (ret < 0) | ||
1491 | goto out_error; | ||
1492 | } | ||
1493 | } | 1522 | } |
1494 | return 0; | 1523 | return 0; |
1495 | out_error: | 1524 | out_error: |