diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-12-09 11:12:26 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-12-09 11:12:26 -0500 |
commit | 2941b0e91ba68b1f77140e556307e00616a5bb46 (patch) | |
tree | 01950b6ed12d06ebe4c39d1a2122050a9a570e93 /fs | |
parent | 818f2f57f20d0e9a9294180f304f34cd4e8f6066 (diff) | |
parent | 388f0c776781fe64ce951701bfe712b2182a31f2 (diff) |
Merge tag 'nfs-for-3.19-1' into nfsd for-3.19 branch
Mainly what I need is 860a0d9e511f "sunrpc: add some tracepoints in
svc_rqst handling functions", which subsequent server rpc patches from
jlayton depend on. I'm merging this later tag on the assumption that's
more likely to be a tested and stable point.
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Makefile | 2 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 14 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 24 | ||||
-rw-r--r-- | fs/btrfs/locking.h | 2 | ||||
-rw-r--r-- | fs/dcache.c | 1 | ||||
-rw-r--r-- | fs/isofs/inode.c | 42 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 2 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/callback_proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/filelayout/filelayoutdev.c | 3 | ||||
-rw-r--r-- | fs/nfs/fscache.c | 24 | ||||
-rw-r--r-- | fs/nfs/inode.c | 9 | ||||
-rw-r--r-- | fs/nfs/iostat.h | 5 | ||||
-rw-r--r-- | fs/nfs/nfs42.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs42proc.c | 77 | ||||
-rw-r--r-- | fs/nfs/nfs42xdr.c | 139 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 46 | ||||
-rw-r--r-- | fs/nfs/nfs4file.c | 31 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 12 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 11 | ||||
-rw-r--r-- | fs/nfs/read.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 19 | ||||
-rw-r--r-- | fs/overlayfs/Kconfig | 2 | ||||
-rw-r--r-- | fs/overlayfs/Makefile | 4 | ||||
-rw-r--r-- | fs/overlayfs/dir.c | 31 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 27 | ||||
-rw-r--r-- | fs/overlayfs/readdir.c | 39 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 61 |
30 files changed, 483 insertions, 165 deletions
diff --git a/fs/Makefile b/fs/Makefile index 34a1b9dea6dd..da0bbb456d3f 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -104,7 +104,7 @@ obj-$(CONFIG_QNX6FS_FS) += qnx6/ | |||
104 | obj-$(CONFIG_AUTOFS4_FS) += autofs4/ | 104 | obj-$(CONFIG_AUTOFS4_FS) += autofs4/ |
105 | obj-$(CONFIG_ADFS_FS) += adfs/ | 105 | obj-$(CONFIG_ADFS_FS) += adfs/ |
106 | obj-$(CONFIG_FUSE_FS) += fuse/ | 106 | obj-$(CONFIG_FUSE_FS) += fuse/ |
107 | obj-$(CONFIG_OVERLAYFS_FS) += overlayfs/ | 107 | obj-$(CONFIG_OVERLAY_FS) += overlayfs/ |
108 | obj-$(CONFIG_UDF_FS) += udf/ | 108 | obj-$(CONFIG_UDF_FS) += udf/ |
109 | obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ | 109 | obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ |
110 | obj-$(CONFIG_OMFS_FS) += omfs/ | 110 | obj-$(CONFIG_OMFS_FS) += omfs/ |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 19bc6162fb8e..150822ee0a0b 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -80,13 +80,6 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p, | |||
80 | { | 80 | { |
81 | int i; | 81 | int i; |
82 | 82 | ||
83 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
84 | /* lockdep really cares that we take all of these spinlocks | ||
85 | * in the right order. If any of the locks in the path are not | ||
86 | * currently blocking, it is going to complain. So, make really | ||
87 | * really sure by forcing the path to blocking before we clear | ||
88 | * the path blocking. | ||
89 | */ | ||
90 | if (held) { | 83 | if (held) { |
91 | btrfs_set_lock_blocking_rw(held, held_rw); | 84 | btrfs_set_lock_blocking_rw(held, held_rw); |
92 | if (held_rw == BTRFS_WRITE_LOCK) | 85 | if (held_rw == BTRFS_WRITE_LOCK) |
@@ -95,7 +88,6 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p, | |||
95 | held_rw = BTRFS_READ_LOCK_BLOCKING; | 88 | held_rw = BTRFS_READ_LOCK_BLOCKING; |
96 | } | 89 | } |
97 | btrfs_set_path_blocking(p); | 90 | btrfs_set_path_blocking(p); |
98 | #endif | ||
99 | 91 | ||
100 | for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) { | 92 | for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) { |
101 | if (p->nodes[i] && p->locks[i]) { | 93 | if (p->nodes[i] && p->locks[i]) { |
@@ -107,10 +99,8 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p, | |||
107 | } | 99 | } |
108 | } | 100 | } |
109 | 101 | ||
110 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
111 | if (held) | 102 | if (held) |
112 | btrfs_clear_lock_blocking_rw(held, held_rw); | 103 | btrfs_clear_lock_blocking_rw(held, held_rw); |
113 | #endif | ||
114 | } | 104 | } |
115 | 105 | ||
116 | /* this also releases the path */ | 106 | /* this also releases the path */ |
@@ -2893,7 +2883,7 @@ cow_done: | |||
2893 | } | 2883 | } |
2894 | p->locks[level] = BTRFS_WRITE_LOCK; | 2884 | p->locks[level] = BTRFS_WRITE_LOCK; |
2895 | } else { | 2885 | } else { |
2896 | err = btrfs_try_tree_read_lock(b); | 2886 | err = btrfs_tree_read_lock_atomic(b); |
2897 | if (!err) { | 2887 | if (!err) { |
2898 | btrfs_set_path_blocking(p); | 2888 | btrfs_set_path_blocking(p); |
2899 | btrfs_tree_read_lock(b); | 2889 | btrfs_tree_read_lock(b); |
@@ -3025,7 +3015,7 @@ again: | |||
3025 | } | 3015 | } |
3026 | 3016 | ||
3027 | level = btrfs_header_level(b); | 3017 | level = btrfs_header_level(b); |
3028 | err = btrfs_try_tree_read_lock(b); | 3018 | err = btrfs_tree_read_lock_atomic(b); |
3029 | if (!err) { | 3019 | if (!err) { |
3030 | btrfs_set_path_blocking(p); | 3020 | btrfs_set_path_blocking(p); |
3031 | btrfs_tree_read_lock(b); | 3021 | btrfs_tree_read_lock(b); |
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 5665d2149249..f8229ef1b46d 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
@@ -128,6 +128,26 @@ again: | |||
128 | } | 128 | } |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * take a spinning read lock. | ||
132 | * returns 1 if we get the read lock and 0 if we don't | ||
133 | * this won't wait for blocking writers | ||
134 | */ | ||
135 | int btrfs_tree_read_lock_atomic(struct extent_buffer *eb) | ||
136 | { | ||
137 | if (atomic_read(&eb->blocking_writers)) | ||
138 | return 0; | ||
139 | |||
140 | read_lock(&eb->lock); | ||
141 | if (atomic_read(&eb->blocking_writers)) { | ||
142 | read_unlock(&eb->lock); | ||
143 | return 0; | ||
144 | } | ||
145 | atomic_inc(&eb->read_locks); | ||
146 | atomic_inc(&eb->spinning_readers); | ||
147 | return 1; | ||
148 | } | ||
149 | |||
150 | /* | ||
131 | * returns 1 if we get the read lock and 0 if we don't | 151 | * returns 1 if we get the read lock and 0 if we don't |
132 | * this won't wait for blocking writers | 152 | * this won't wait for blocking writers |
133 | */ | 153 | */ |
@@ -158,9 +178,7 @@ int btrfs_try_tree_write_lock(struct extent_buffer *eb) | |||
158 | atomic_read(&eb->blocking_readers)) | 178 | atomic_read(&eb->blocking_readers)) |
159 | return 0; | 179 | return 0; |
160 | 180 | ||
161 | if (!write_trylock(&eb->lock)) | 181 | write_lock(&eb->lock); |
162 | return 0; | ||
163 | |||
164 | if (atomic_read(&eb->blocking_writers) || | 182 | if (atomic_read(&eb->blocking_writers) || |
165 | atomic_read(&eb->blocking_readers)) { | 183 | atomic_read(&eb->blocking_readers)) { |
166 | write_unlock(&eb->lock); | 184 | write_unlock(&eb->lock); |
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h index b81e0e9a4894..c44a9d5f5362 100644 --- a/fs/btrfs/locking.h +++ b/fs/btrfs/locking.h | |||
@@ -35,6 +35,8 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw); | |||
35 | void btrfs_assert_tree_locked(struct extent_buffer *eb); | 35 | void btrfs_assert_tree_locked(struct extent_buffer *eb); |
36 | int btrfs_try_tree_read_lock(struct extent_buffer *eb); | 36 | int btrfs_try_tree_read_lock(struct extent_buffer *eb); |
37 | int btrfs_try_tree_write_lock(struct extent_buffer *eb); | 37 | int btrfs_try_tree_write_lock(struct extent_buffer *eb); |
38 | int btrfs_tree_read_lock_atomic(struct extent_buffer *eb); | ||
39 | |||
38 | 40 | ||
39 | static inline void btrfs_tree_unlock_rw(struct extent_buffer *eb, int rw) | 41 | static inline void btrfs_tree_unlock_rw(struct extent_buffer *eb, int rw) |
40 | { | 42 | { |
diff --git a/fs/dcache.c b/fs/dcache.c index 3ffef7f4e5cd..5bc72b07fde2 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -778,6 +778,7 @@ restart: | |||
778 | struct dentry *parent = lock_parent(dentry); | 778 | struct dentry *parent = lock_parent(dentry); |
779 | if (likely(!dentry->d_lockref.count)) { | 779 | if (likely(!dentry->d_lockref.count)) { |
780 | __dentry_kill(dentry); | 780 | __dentry_kill(dentry); |
781 | dput(parent); | ||
781 | goto restart; | 782 | goto restart; |
782 | } | 783 | } |
783 | if (parent) | 784 | if (parent) |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index fe839b915116..d67a16f2a45d 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -174,27 +174,6 @@ struct iso9660_options{ | |||
174 | * Compute the hash for the isofs name corresponding to the dentry. | 174 | * Compute the hash for the isofs name corresponding to the dentry. |
175 | */ | 175 | */ |
176 | static int | 176 | static int |
177 | isofs_hash_common(struct qstr *qstr, int ms) | ||
178 | { | ||
179 | const char *name; | ||
180 | int len; | ||
181 | |||
182 | len = qstr->len; | ||
183 | name = qstr->name; | ||
184 | if (ms) { | ||
185 | while (len && name[len-1] == '.') | ||
186 | len--; | ||
187 | } | ||
188 | |||
189 | qstr->hash = full_name_hash(name, len); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Compute the hash for the isofs name corresponding to the dentry. | ||
196 | */ | ||
197 | static int | ||
198 | isofs_hashi_common(struct qstr *qstr, int ms) | 177 | isofs_hashi_common(struct qstr *qstr, int ms) |
199 | { | 178 | { |
200 | const char *name; | 179 | const char *name; |
@@ -263,6 +242,27 @@ isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry, | |||
263 | } | 242 | } |
264 | 243 | ||
265 | #ifdef CONFIG_JOLIET | 244 | #ifdef CONFIG_JOLIET |
245 | /* | ||
246 | * Compute the hash for the isofs name corresponding to the dentry. | ||
247 | */ | ||
248 | static int | ||
249 | isofs_hash_common(struct qstr *qstr, int ms) | ||
250 | { | ||
251 | const char *name; | ||
252 | int len; | ||
253 | |||
254 | len = qstr->len; | ||
255 | name = qstr->name; | ||
256 | if (ms) { | ||
257 | while (len && name[len-1] == '.') | ||
258 | len--; | ||
259 | } | ||
260 | |||
261 | qstr->hash = full_name_hash(name, len); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int | 266 | static int |
267 | isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr) | 267 | isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr) |
268 | { | 268 | { |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 13db95f54176..56598742dde4 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -53,7 +53,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops; | |||
53 | static LIST_HEAD(nlm_blocked); | 53 | static LIST_HEAD(nlm_blocked); |
54 | static DEFINE_SPINLOCK(nlm_blocked_lock); | 54 | static DEFINE_SPINLOCK(nlm_blocked_lock); |
55 | 55 | ||
56 | #ifdef LOCKD_DEBUG | 56 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
57 | static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie) | 57 | static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie) |
58 | { | 58 | { |
59 | /* | 59 | /* |
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 4f46f7a05289..77fec6a55f57 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -812,7 +812,7 @@ static u64 pnfs_num_cont_bytes(struct inode *inode, pgoff_t idx) | |||
812 | 812 | ||
813 | /* Optimize common case that writes from 0 to end of file */ | 813 | /* Optimize common case that writes from 0 to end of file */ |
814 | end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE); | 814 | end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE); |
815 | if (end != NFS_I(inode)->npages) { | 815 | if (end != inode->i_mapping->nrpages) { |
816 | rcu_read_lock(); | 816 | rcu_read_lock(); |
817 | end = page_cache_next_hole(mapping, idx + 1, ULONG_MAX); | 817 | end = page_cache_next_hole(mapping, idx + 1, ULONG_MAX); |
818 | rcu_read_unlock(); | 818 | rcu_read_unlock(); |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 73466b934090..e36a9d78ea49 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -49,7 +49,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, | |||
49 | goto out_iput; | 49 | goto out_iput; |
50 | res->size = i_size_read(inode); | 50 | res->size = i_size_read(inode); |
51 | res->change_attr = delegation->change_attr; | 51 | res->change_attr = delegation->change_attr; |
52 | if (nfsi->npages != 0) | 52 | if (nfsi->nrequests != 0) |
53 | res->change_attr++; | 53 | res->change_attr++; |
54 | res->ctime = inode->i_ctime; | 54 | res->ctime = inode->i_ctime; |
55 | res->mtime = inode->i_mtime; | 55 | res->mtime = inode->i_mtime; |
diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c index 9bb806a76d99..bfecac781f19 100644 --- a/fs/nfs/filelayout/filelayoutdev.c +++ b/fs/nfs/filelayout/filelayoutdev.c | |||
@@ -204,8 +204,7 @@ destroy_ds(struct nfs4_pnfs_ds *ds) | |||
204 | ifdebug(FACILITY) | 204 | ifdebug(FACILITY) |
205 | print_ds(ds); | 205 | print_ds(ds); |
206 | 206 | ||
207 | if (ds->ds_clp) | 207 | nfs_put_client(ds->ds_clp); |
208 | nfs_put_client(ds->ds_clp); | ||
209 | 208 | ||
210 | while (!list_empty(&ds->ds_addrs)) { | 209 | while (!list_empty(&ds->ds_addrs)) { |
211 | da = list_first_entry(&ds->ds_addrs, | 210 | da = list_first_entry(&ds->ds_addrs, |
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 3ef01f0ba0bc..d63bea8bbfbb 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c | |||
@@ -269,8 +269,8 @@ int nfs_fscache_release_page(struct page *page, gfp_t gfp) | |||
269 | if (!fscache_maybe_release_page(cookie, page, gfp)) | 269 | if (!fscache_maybe_release_page(cookie, page, gfp)) |
270 | return 0; | 270 | return 0; |
271 | 271 | ||
272 | nfs_add_fscache_stats(page->mapping->host, | 272 | nfs_inc_fscache_stats(page->mapping->host, |
273 | NFSIOS_FSCACHE_PAGES_UNCACHED, 1); | 273 | NFSIOS_FSCACHE_PAGES_UNCACHED); |
274 | } | 274 | } |
275 | 275 | ||
276 | return 1; | 276 | return 1; |
@@ -293,8 +293,8 @@ void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode) | |||
293 | 293 | ||
294 | BUG_ON(!PageLocked(page)); | 294 | BUG_ON(!PageLocked(page)); |
295 | fscache_uncache_page(cookie, page); | 295 | fscache_uncache_page(cookie, page); |
296 | nfs_add_fscache_stats(page->mapping->host, | 296 | nfs_inc_fscache_stats(page->mapping->host, |
297 | NFSIOS_FSCACHE_PAGES_UNCACHED, 1); | 297 | NFSIOS_FSCACHE_PAGES_UNCACHED); |
298 | } | 298 | } |
299 | 299 | ||
300 | /* | 300 | /* |
@@ -343,19 +343,19 @@ int __nfs_readpage_from_fscache(struct nfs_open_context *ctx, | |||
343 | case 0: /* read BIO submitted (page in fscache) */ | 343 | case 0: /* read BIO submitted (page in fscache) */ |
344 | dfprintk(FSCACHE, | 344 | dfprintk(FSCACHE, |
345 | "NFS: readpage_from_fscache: BIO submitted\n"); | 345 | "NFS: readpage_from_fscache: BIO submitted\n"); |
346 | nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK, 1); | 346 | nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK); |
347 | return ret; | 347 | return ret; |
348 | 348 | ||
349 | case -ENOBUFS: /* inode not in cache */ | 349 | case -ENOBUFS: /* inode not in cache */ |
350 | case -ENODATA: /* page not in cache */ | 350 | case -ENODATA: /* page not in cache */ |
351 | nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 1); | 351 | nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL); |
352 | dfprintk(FSCACHE, | 352 | dfprintk(FSCACHE, |
353 | "NFS: readpage_from_fscache %d\n", ret); | 353 | "NFS: readpage_from_fscache %d\n", ret); |
354 | return 1; | 354 | return 1; |
355 | 355 | ||
356 | default: | 356 | default: |
357 | dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret); | 357 | dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret); |
358 | nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 1); | 358 | nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL); |
359 | } | 359 | } |
360 | return ret; | 360 | return ret; |
361 | } | 361 | } |
@@ -429,11 +429,11 @@ void __nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) | |||
429 | 429 | ||
430 | if (ret != 0) { | 430 | if (ret != 0) { |
431 | fscache_uncache_page(nfs_i_fscache(inode), page); | 431 | fscache_uncache_page(nfs_i_fscache(inode), page); |
432 | nfs_add_fscache_stats(inode, | 432 | nfs_inc_fscache_stats(inode, |
433 | NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL, 1); | 433 | NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL); |
434 | nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED, 1); | 434 | nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED); |
435 | } else { | 435 | } else { |
436 | nfs_add_fscache_stats(inode, | 436 | nfs_inc_fscache_stats(inode, |
437 | NFSIOS_FSCACHE_PAGES_WRITTEN_OK, 1); | 437 | NFSIOS_FSCACHE_PAGES_WRITTEN_OK); |
438 | } | 438 | } |
439 | } | 439 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 00689a8a85e4..4bffe637ea32 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -192,6 +192,7 @@ void nfs_zap_caches(struct inode *inode) | |||
192 | nfs_zap_caches_locked(inode); | 192 | nfs_zap_caches_locked(inode); |
193 | spin_unlock(&inode->i_lock); | 193 | spin_unlock(&inode->i_lock); |
194 | } | 194 | } |
195 | EXPORT_SYMBOL_GPL(nfs_zap_caches); | ||
195 | 196 | ||
196 | void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) | 197 | void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) |
197 | { | 198 | { |
@@ -1149,7 +1150,7 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr | |||
1149 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | 1150 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) |
1150 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) | 1151 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) |
1151 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) | 1152 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) |
1152 | && nfsi->npages == 0) { | 1153 | && nfsi->nrequests == 0) { |
1153 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | 1154 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); |
1154 | ret |= NFS_INO_INVALID_ATTR; | 1155 | ret |= NFS_INO_INVALID_ATTR; |
1155 | } | 1156 | } |
@@ -1192,7 +1193,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
1192 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { | 1193 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1193 | cur_size = i_size_read(inode); | 1194 | cur_size = i_size_read(inode); |
1194 | new_isize = nfs_size_to_loff_t(fattr->size); | 1195 | new_isize = nfs_size_to_loff_t(fattr->size); |
1195 | if (cur_size != new_isize && nfsi->npages == 0) | 1196 | if (cur_size != new_isize && nfsi->nrequests == 0) |
1196 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 1197 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
1197 | } | 1198 | } |
1198 | 1199 | ||
@@ -1619,7 +1620,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1619 | if (new_isize != cur_isize) { | 1620 | if (new_isize != cur_isize) { |
1620 | /* Do we perhaps have any outstanding writes, or has | 1621 | /* Do we perhaps have any outstanding writes, or has |
1621 | * the file grown beyond our last write? */ | 1622 | * the file grown beyond our last write? */ |
1622 | if ((nfsi->npages == 0) || new_isize > cur_isize) { | 1623 | if ((nfsi->nrequests == 0) || new_isize > cur_isize) { |
1623 | i_size_write(inode, new_isize); | 1624 | i_size_write(inode, new_isize); |
1624 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1625 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1625 | invalid &= ~NFS_INO_REVAL_PAGECACHE; | 1626 | invalid &= ~NFS_INO_REVAL_PAGECACHE; |
@@ -1784,7 +1785,7 @@ static void init_once(void *foo) | |||
1784 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | 1785 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); |
1785 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | 1786 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); |
1786 | INIT_LIST_HEAD(&nfsi->commit_info.list); | 1787 | INIT_LIST_HEAD(&nfsi->commit_info.list); |
1787 | nfsi->npages = 0; | 1788 | nfsi->nrequests = 0; |
1788 | nfsi->commit_info.ncommit = 0; | 1789 | nfsi->commit_info.ncommit = 0; |
1789 | atomic_set(&nfsi->commit_info.rpcs_out, 0); | 1790 | atomic_set(&nfsi->commit_info.rpcs_out, 0); |
1790 | atomic_set(&nfsi->silly_count, 1); | 1791 | atomic_set(&nfsi->silly_count, 1); |
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h index c5832487c456..0cb806fbd4c4 100644 --- a/fs/nfs/iostat.h +++ b/fs/nfs/iostat.h | |||
@@ -55,6 +55,11 @@ static inline void nfs_add_fscache_stats(struct inode *inode, | |||
55 | { | 55 | { |
56 | this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend); | 56 | this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend); |
57 | } | 57 | } |
58 | static inline void nfs_inc_fscache_stats(struct inode *inode, | ||
59 | enum nfs_stat_fscachecounters stat) | ||
60 | { | ||
61 | this_cpu_inc(NFS_SERVER(inode)->io_stats->fscache[stat]); | ||
62 | } | ||
58 | #endif | 63 | #endif |
59 | 64 | ||
60 | static inline struct nfs_iostats __percpu *nfs_alloc_iostats(void) | 65 | static inline struct nfs_iostats __percpu *nfs_alloc_iostats(void) |
diff --git a/fs/nfs/nfs42.h b/fs/nfs/nfs42.h index d10333a197bf..7afb8947dfdf 100644 --- a/fs/nfs/nfs42.h +++ b/fs/nfs/nfs42.h | |||
@@ -6,6 +6,8 @@ | |||
6 | #define __LINUX_FS_NFS_NFS4_2_H | 6 | #define __LINUX_FS_NFS_NFS4_2_H |
7 | 7 | ||
8 | /* nfs4.2proc.c */ | 8 | /* nfs4.2proc.c */ |
9 | int nfs42_proc_allocate(struct file *, loff_t, loff_t); | ||
10 | int nfs42_proc_deallocate(struct file *, loff_t, loff_t); | ||
9 | loff_t nfs42_proc_llseek(struct file *, loff_t, int); | 11 | loff_t nfs42_proc_llseek(struct file *, loff_t, int); |
10 | 12 | ||
11 | /* nfs4.2xdr.h */ | 13 | /* nfs4.2xdr.h */ |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 0886f1db5917..cb170722769c 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -32,6 +32,81 @@ static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, | |||
32 | return ret; | 32 | return ret; |
33 | } | 33 | } |
34 | 34 | ||
35 | static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, | ||
36 | loff_t offset, loff_t len) | ||
37 | { | ||
38 | struct inode *inode = file_inode(filep); | ||
39 | struct nfs42_falloc_args args = { | ||
40 | .falloc_fh = NFS_FH(inode), | ||
41 | .falloc_offset = offset, | ||
42 | .falloc_length = len, | ||
43 | }; | ||
44 | struct nfs42_falloc_res res; | ||
45 | struct nfs_server *server = NFS_SERVER(inode); | ||
46 | int status; | ||
47 | |||
48 | msg->rpc_argp = &args; | ||
49 | msg->rpc_resp = &res; | ||
50 | |||
51 | status = nfs42_set_rw_stateid(&args.falloc_stateid, filep, FMODE_WRITE); | ||
52 | if (status) | ||
53 | return status; | ||
54 | |||
55 | return nfs4_call_sync(server->client, server, msg, | ||
56 | &args.seq_args, &res.seq_res, 0); | ||
57 | } | ||
58 | |||
59 | static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, | ||
60 | loff_t offset, loff_t len) | ||
61 | { | ||
62 | struct nfs_server *server = NFS_SERVER(file_inode(filep)); | ||
63 | struct nfs4_exception exception = { }; | ||
64 | int err; | ||
65 | |||
66 | do { | ||
67 | err = _nfs42_proc_fallocate(msg, filep, offset, len); | ||
68 | if (err == -ENOTSUPP) | ||
69 | return -EOPNOTSUPP; | ||
70 | err = nfs4_handle_exception(server, err, &exception); | ||
71 | } while (exception.retry); | ||
72 | |||
73 | return err; | ||
74 | } | ||
75 | |||
76 | int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len) | ||
77 | { | ||
78 | struct rpc_message msg = { | ||
79 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE], | ||
80 | }; | ||
81 | struct inode *inode = file_inode(filep); | ||
82 | int err; | ||
83 | |||
84 | if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE)) | ||
85 | return -EOPNOTSUPP; | ||
86 | |||
87 | err = nfs42_proc_fallocate(&msg, filep, offset, len); | ||
88 | if (err == -EOPNOTSUPP) | ||
89 | NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE; | ||
90 | return err; | ||
91 | } | ||
92 | |||
93 | int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) | ||
94 | { | ||
95 | struct rpc_message msg = { | ||
96 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DEALLOCATE], | ||
97 | }; | ||
98 | struct inode *inode = file_inode(filep); | ||
99 | int err; | ||
100 | |||
101 | if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE)) | ||
102 | return -EOPNOTSUPP; | ||
103 | |||
104 | err = nfs42_proc_fallocate(&msg, filep, offset, len); | ||
105 | if (err == -EOPNOTSUPP) | ||
106 | NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; | ||
107 | return err; | ||
108 | } | ||
109 | |||
35 | loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) | 110 | loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) |
36 | { | 111 | { |
37 | struct inode *inode = file_inode(filep); | 112 | struct inode *inode = file_inode(filep); |
@@ -50,7 +125,7 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) | |||
50 | struct nfs_server *server = NFS_SERVER(inode); | 125 | struct nfs_server *server = NFS_SERVER(inode); |
51 | int status; | 126 | int status; |
52 | 127 | ||
53 | if (!(server->caps & NFS_CAP_SEEK)) | 128 | if (!nfs_server_capable(inode, NFS_CAP_SEEK)) |
54 | return -ENOTSUPP; | 129 | return -ENOTSUPP; |
55 | 130 | ||
56 | status = nfs42_set_rw_stateid(&args.sa_stateid, filep, FMODE_READ); | 131 | status = nfs42_set_rw_stateid(&args.sa_stateid, filep, FMODE_READ); |
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index c90469b604b8..038a7e1521fa 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c | |||
@@ -4,6 +4,15 @@ | |||
4 | #ifndef __LINUX_FS_NFS_NFS4_2XDR_H | 4 | #ifndef __LINUX_FS_NFS_NFS4_2XDR_H |
5 | #define __LINUX_FS_NFS_NFS4_2XDR_H | 5 | #define __LINUX_FS_NFS_NFS4_2XDR_H |
6 | 6 | ||
7 | #define encode_fallocate_maxsz (encode_stateid_maxsz + \ | ||
8 | 2 /* offset */ + \ | ||
9 | 2 /* length */) | ||
10 | #define encode_allocate_maxsz (op_encode_hdr_maxsz + \ | ||
11 | encode_fallocate_maxsz) | ||
12 | #define decode_allocate_maxsz (op_decode_hdr_maxsz) | ||
13 | #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \ | ||
14 | encode_fallocate_maxsz) | ||
15 | #define decode_deallocate_maxsz (op_decode_hdr_maxsz) | ||
7 | #define encode_seek_maxsz (op_encode_hdr_maxsz + \ | 16 | #define encode_seek_maxsz (op_encode_hdr_maxsz + \ |
8 | encode_stateid_maxsz + \ | 17 | encode_stateid_maxsz + \ |
9 | 2 /* offset */ + \ | 18 | 2 /* offset */ + \ |
@@ -14,6 +23,18 @@ | |||
14 | 2 /* offset */ + \ | 23 | 2 /* offset */ + \ |
15 | 2 /* length */) | 24 | 2 /* length */) |
16 | 25 | ||
26 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ | ||
27 | encode_putfh_maxsz + \ | ||
28 | encode_allocate_maxsz) | ||
29 | #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ | ||
30 | decode_putfh_maxsz + \ | ||
31 | decode_allocate_maxsz) | ||
32 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ | ||
33 | encode_putfh_maxsz + \ | ||
34 | encode_deallocate_maxsz) | ||
35 | #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ | ||
36 | decode_putfh_maxsz + \ | ||
37 | decode_deallocate_maxsz) | ||
17 | #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ | 38 | #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ |
18 | encode_putfh_maxsz + \ | 39 | encode_putfh_maxsz + \ |
19 | encode_seek_maxsz) | 40 | encode_seek_maxsz) |
@@ -22,6 +43,30 @@ | |||
22 | decode_seek_maxsz) | 43 | decode_seek_maxsz) |
23 | 44 | ||
24 | 45 | ||
46 | static void encode_fallocate(struct xdr_stream *xdr, | ||
47 | struct nfs42_falloc_args *args) | ||
48 | { | ||
49 | encode_nfs4_stateid(xdr, &args->falloc_stateid); | ||
50 | encode_uint64(xdr, args->falloc_offset); | ||
51 | encode_uint64(xdr, args->falloc_length); | ||
52 | } | ||
53 | |||
54 | static void encode_allocate(struct xdr_stream *xdr, | ||
55 | struct nfs42_falloc_args *args, | ||
56 | struct compound_hdr *hdr) | ||
57 | { | ||
58 | encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr); | ||
59 | encode_fallocate(xdr, args); | ||
60 | } | ||
61 | |||
62 | static void encode_deallocate(struct xdr_stream *xdr, | ||
63 | struct nfs42_falloc_args *args, | ||
64 | struct compound_hdr *hdr) | ||
65 | { | ||
66 | encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr); | ||
67 | encode_fallocate(xdr, args); | ||
68 | } | ||
69 | |||
25 | static void encode_seek(struct xdr_stream *xdr, | 70 | static void encode_seek(struct xdr_stream *xdr, |
26 | struct nfs42_seek_args *args, | 71 | struct nfs42_seek_args *args, |
27 | struct compound_hdr *hdr) | 72 | struct compound_hdr *hdr) |
@@ -33,6 +78,42 @@ static void encode_seek(struct xdr_stream *xdr, | |||
33 | } | 78 | } |
34 | 79 | ||
35 | /* | 80 | /* |
81 | * Encode ALLOCATE request | ||
82 | */ | ||
83 | static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, | ||
84 | struct xdr_stream *xdr, | ||
85 | struct nfs42_falloc_args *args) | ||
86 | { | ||
87 | struct compound_hdr hdr = { | ||
88 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
89 | }; | ||
90 | |||
91 | encode_compound_hdr(xdr, req, &hdr); | ||
92 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
93 | encode_putfh(xdr, args->falloc_fh, &hdr); | ||
94 | encode_allocate(xdr, args, &hdr); | ||
95 | encode_nops(&hdr); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Encode DEALLOCATE request | ||
100 | */ | ||
101 | static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, | ||
102 | struct xdr_stream *xdr, | ||
103 | struct nfs42_falloc_args *args) | ||
104 | { | ||
105 | struct compound_hdr hdr = { | ||
106 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
107 | }; | ||
108 | |||
109 | encode_compound_hdr(xdr, req, &hdr); | ||
110 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
111 | encode_putfh(xdr, args->falloc_fh, &hdr); | ||
112 | encode_deallocate(xdr, args, &hdr); | ||
113 | encode_nops(&hdr); | ||
114 | } | ||
115 | |||
116 | /* | ||
36 | * Encode SEEK request | 117 | * Encode SEEK request |
37 | */ | 118 | */ |
38 | static void nfs4_xdr_enc_seek(struct rpc_rqst *req, | 119 | static void nfs4_xdr_enc_seek(struct rpc_rqst *req, |
@@ -50,6 +131,16 @@ static void nfs4_xdr_enc_seek(struct rpc_rqst *req, | |||
50 | encode_nops(&hdr); | 131 | encode_nops(&hdr); |
51 | } | 132 | } |
52 | 133 | ||
134 | static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) | ||
135 | { | ||
136 | return decode_op_hdr(xdr, OP_ALLOCATE); | ||
137 | } | ||
138 | |||
139 | static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) | ||
140 | { | ||
141 | return decode_op_hdr(xdr, OP_DEALLOCATE); | ||
142 | } | ||
143 | |||
53 | static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) | 144 | static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) |
54 | { | 145 | { |
55 | int status; | 146 | int status; |
@@ -73,6 +164,54 @@ out_overflow: | |||
73 | } | 164 | } |
74 | 165 | ||
75 | /* | 166 | /* |
167 | * Decode ALLOCATE request | ||
168 | */ | ||
169 | static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, | ||
170 | struct xdr_stream *xdr, | ||
171 | struct nfs42_falloc_res *res) | ||
172 | { | ||
173 | struct compound_hdr hdr; | ||
174 | int status; | ||
175 | |||
176 | status = decode_compound_hdr(xdr, &hdr); | ||
177 | if (status) | ||
178 | goto out; | ||
179 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
180 | if (status) | ||
181 | goto out; | ||
182 | status = decode_putfh(xdr); | ||
183 | if (status) | ||
184 | goto out; | ||
185 | status = decode_allocate(xdr, res); | ||
186 | out: | ||
187 | return status; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Decode DEALLOCATE request | ||
192 | */ | ||
193 | static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, | ||
194 | struct xdr_stream *xdr, | ||
195 | struct nfs42_falloc_res *res) | ||
196 | { | ||
197 | struct compound_hdr hdr; | ||
198 | int status; | ||
199 | |||
200 | status = decode_compound_hdr(xdr, &hdr); | ||
201 | if (status) | ||
202 | goto out; | ||
203 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
204 | if (status) | ||
205 | goto out; | ||
206 | status = decode_putfh(xdr); | ||
207 | if (status) | ||
208 | goto out; | ||
209 | status = decode_deallocate(xdr, res); | ||
210 | out: | ||
211 | return status; | ||
212 | } | ||
213 | |||
214 | /* | ||
76 | * Decode SEEK request | 215 | * Decode SEEK request |
77 | */ | 216 | */ |
78 | static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, | 217 | static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index be6cac37ea10..a08178764cf9 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -226,6 +226,7 @@ int nfs4_replace_transport(struct nfs_server *server, | |||
226 | const struct nfs4_fs_locations *locations); | 226 | const struct nfs4_fs_locations *locations); |
227 | 227 | ||
228 | /* nfs4proc.c */ | 228 | /* nfs4proc.c */ |
229 | extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *); | ||
229 | extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, | 230 | extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, |
230 | struct rpc_message *, struct nfs4_sequence_args *, | 231 | struct rpc_message *, struct nfs4_sequence_args *, |
231 | struct nfs4_sequence_res *, int); | 232 | struct nfs4_sequence_res *, int); |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index ffdb28d86cf8..03311259b0c4 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -241,28 +241,25 @@ void nfs4_free_client(struct nfs_client *clp) | |||
241 | */ | 241 | */ |
242 | static int nfs4_init_callback(struct nfs_client *clp) | 242 | static int nfs4_init_callback(struct nfs_client *clp) |
243 | { | 243 | { |
244 | struct rpc_xprt *xprt; | ||
244 | int error; | 245 | int error; |
245 | 246 | ||
246 | if (clp->rpc_ops->version == 4) { | 247 | xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt); |
247 | struct rpc_xprt *xprt; | ||
248 | 248 | ||
249 | xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt); | 249 | if (nfs4_has_session(clp)) { |
250 | 250 | error = xprt_setup_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); | |
251 | if (nfs4_has_session(clp)) { | 251 | if (error < 0) |
252 | error = xprt_setup_backchannel(xprt, | ||
253 | NFS41_BC_MIN_CALLBACKS); | ||
254 | if (error < 0) | ||
255 | return error; | ||
256 | } | ||
257 | |||
258 | error = nfs_callback_up(clp->cl_mvops->minor_version, xprt); | ||
259 | if (error < 0) { | ||
260 | dprintk("%s: failed to start callback. Error = %d\n", | ||
261 | __func__, error); | ||
262 | return error; | 252 | return error; |
263 | } | ||
264 | __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); | ||
265 | } | 253 | } |
254 | |||
255 | error = nfs_callback_up(clp->cl_mvops->minor_version, xprt); | ||
256 | if (error < 0) { | ||
257 | dprintk("%s: failed to start callback. Error = %d\n", | ||
258 | __func__, error); | ||
259 | return error; | ||
260 | } | ||
261 | __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); | ||
262 | |||
266 | return 0; | 263 | return 0; |
267 | } | 264 | } |
268 | 265 | ||
@@ -498,8 +495,7 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
498 | atomic_inc(&pos->cl_count); | 495 | atomic_inc(&pos->cl_count); |
499 | spin_unlock(&nn->nfs_client_lock); | 496 | spin_unlock(&nn->nfs_client_lock); |
500 | 497 | ||
501 | if (prev) | 498 | nfs_put_client(prev); |
502 | nfs_put_client(prev); | ||
503 | prev = pos; | 499 | prev = pos; |
504 | 500 | ||
505 | status = nfs_wait_client_init_complete(pos); | 501 | status = nfs_wait_client_init_complete(pos); |
@@ -517,8 +513,7 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
517 | atomic_inc(&pos->cl_count); | 513 | atomic_inc(&pos->cl_count); |
518 | spin_unlock(&nn->nfs_client_lock); | 514 | spin_unlock(&nn->nfs_client_lock); |
519 | 515 | ||
520 | if (prev) | 516 | nfs_put_client(prev); |
521 | nfs_put_client(prev); | ||
522 | prev = pos; | 517 | prev = pos; |
523 | 518 | ||
524 | status = nfs4_proc_setclientid_confirm(pos, &clid, cred); | 519 | status = nfs4_proc_setclientid_confirm(pos, &clid, cred); |
@@ -549,8 +544,7 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
549 | 544 | ||
550 | /* No match found. The server lost our clientid */ | 545 | /* No match found. The server lost our clientid */ |
551 | out: | 546 | out: |
552 | if (prev) | 547 | nfs_put_client(prev); |
553 | nfs_put_client(prev); | ||
554 | dprintk("NFS: <-- %s status = %d\n", __func__, status); | 548 | dprintk("NFS: <-- %s status = %d\n", __func__, status); |
555 | return status; | 549 | return status; |
556 | } | 550 | } |
@@ -641,8 +635,7 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
641 | atomic_inc(&pos->cl_count); | 635 | atomic_inc(&pos->cl_count); |
642 | spin_unlock(&nn->nfs_client_lock); | 636 | spin_unlock(&nn->nfs_client_lock); |
643 | 637 | ||
644 | if (prev) | 638 | nfs_put_client(prev); |
645 | nfs_put_client(prev); | ||
646 | prev = pos; | 639 | prev = pos; |
647 | 640 | ||
648 | status = nfs_wait_client_init_complete(pos); | 641 | status = nfs_wait_client_init_complete(pos); |
@@ -675,8 +668,7 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
675 | /* No matching nfs_client found. */ | 668 | /* No matching nfs_client found. */ |
676 | spin_unlock(&nn->nfs_client_lock); | 669 | spin_unlock(&nn->nfs_client_lock); |
677 | dprintk("NFS: <-- %s status = %d\n", __func__, status); | 670 | dprintk("NFS: <-- %s status = %d\n", __func__, status); |
678 | if (prev) | 671 | nfs_put_client(prev); |
679 | nfs_put_client(prev); | ||
680 | return status; | 672 | return status; |
681 | } | 673 | } |
682 | #endif /* CONFIG_NFS_V4_1 */ | 674 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index c51fb4db9bfe..8b46389c4c5b 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1992 Rick Sladkey | 4 | * Copyright (C) 1992 Rick Sladkey |
5 | */ | 5 | */ |
6 | #include <linux/fs.h> | ||
7 | #include <linux/falloc.h> | ||
6 | #include <linux/nfs_fs.h> | 8 | #include <linux/nfs_fs.h> |
7 | #include "internal.h" | 9 | #include "internal.h" |
8 | #include "fscache.h" | 10 | #include "fscache.h" |
@@ -134,6 +136,32 @@ static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) | |||
134 | return nfs_file_llseek(filep, offset, whence); | 136 | return nfs_file_llseek(filep, offset, whence); |
135 | } | 137 | } |
136 | } | 138 | } |
139 | |||
140 | static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t len) | ||
141 | { | ||
142 | struct inode *inode = file_inode(filep); | ||
143 | long ret; | ||
144 | |||
145 | if (!S_ISREG(inode->i_mode)) | ||
146 | return -EOPNOTSUPP; | ||
147 | |||
148 | if ((mode != 0) && (mode != (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE))) | ||
149 | return -EOPNOTSUPP; | ||
150 | |||
151 | ret = inode_newsize_ok(inode, offset + len); | ||
152 | if (ret < 0) | ||
153 | return ret; | ||
154 | |||
155 | mutex_lock(&inode->i_mutex); | ||
156 | if (mode & FALLOC_FL_PUNCH_HOLE) | ||
157 | ret = nfs42_proc_deallocate(filep, offset, len); | ||
158 | else | ||
159 | ret = nfs42_proc_allocate(filep, offset, len); | ||
160 | mutex_unlock(&inode->i_mutex); | ||
161 | |||
162 | nfs_zap_caches(inode); | ||
163 | return ret; | ||
164 | } | ||
137 | #endif /* CONFIG_NFS_V4_2 */ | 165 | #endif /* CONFIG_NFS_V4_2 */ |
138 | 166 | ||
139 | const struct file_operations nfs4_file_operations = { | 167 | const struct file_operations nfs4_file_operations = { |
@@ -155,6 +183,9 @@ const struct file_operations nfs4_file_operations = { | |||
155 | .flock = nfs_flock, | 183 | .flock = nfs_flock, |
156 | .splice_read = nfs_file_splice_read, | 184 | .splice_read = nfs_file_splice_read, |
157 | .splice_write = iter_file_splice_write, | 185 | .splice_write = iter_file_splice_write, |
186 | #ifdef CONFIG_NFS_V4_2 | ||
187 | .fallocate = nfs42_fallocate, | ||
188 | #endif /* CONFIG_NFS_V4_2 */ | ||
158 | .check_flags = nfs_check_flags, | 189 | .check_flags = nfs_check_flags, |
159 | .setlease = simple_nosetlease, | 190 | .setlease = simple_nosetlease, |
160 | }; | 191 | }; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 69dc20a743f9..e7f8d5ff2581 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -158,8 +158,6 @@ static int nfs4_map_errors(int err) | |||
158 | return -EACCES; | 158 | return -EACCES; |
159 | case -NFS4ERR_MINOR_VERS_MISMATCH: | 159 | case -NFS4ERR_MINOR_VERS_MISMATCH: |
160 | return -EPROTONOSUPPORT; | 160 | return -EPROTONOSUPPORT; |
161 | case -NFS4ERR_ACCESS: | ||
162 | return -EACCES; | ||
163 | case -NFS4ERR_FILE_OPEN: | 161 | case -NFS4ERR_FILE_OPEN: |
164 | return -EBUSY; | 162 | return -EBUSY; |
165 | default: | 163 | default: |
@@ -344,7 +342,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
344 | /* This is the error handling routine for processes that are allowed | 342 | /* This is the error handling routine for processes that are allowed |
345 | * to sleep. | 343 | * to sleep. |
346 | */ | 344 | */ |
347 | static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | 345 | int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) |
348 | { | 346 | { |
349 | struct nfs_client *clp = server->nfs_client; | 347 | struct nfs_client *clp = server->nfs_client; |
350 | struct nfs4_state *state = exception->state; | 348 | struct nfs4_state *state = exception->state; |
@@ -7704,6 +7702,9 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
7704 | 7702 | ||
7705 | dprintk("--> %s\n", __func__); | 7703 | dprintk("--> %s\n", __func__); |
7706 | 7704 | ||
7705 | /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ | ||
7706 | pnfs_get_layout_hdr(NFS_I(inode)->layout); | ||
7707 | |||
7707 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); | 7708 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); |
7708 | if (!lgp->args.layout.pages) { | 7709 | if (!lgp->args.layout.pages) { |
7709 | nfs4_layoutget_release(lgp); | 7710 | nfs4_layoutget_release(lgp); |
@@ -7716,9 +7717,6 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
7716 | lgp->res.seq_res.sr_slot = NULL; | 7717 | lgp->res.seq_res.sr_slot = NULL; |
7717 | nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 7718 | nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
7718 | 7719 | ||
7719 | /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ | ||
7720 | pnfs_get_layout_hdr(NFS_I(inode)->layout); | ||
7721 | |||
7722 | task = rpc_run_task(&task_setup_data); | 7720 | task = rpc_run_task(&task_setup_data); |
7723 | if (IS_ERR(task)) | 7721 | if (IS_ERR(task)) |
7724 | return ERR_CAST(task); | 7722 | return ERR_CAST(task); |
@@ -8426,6 +8424,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
8426 | | NFS_CAP_POSIX_LOCK | 8424 | | NFS_CAP_POSIX_LOCK |
8427 | | NFS_CAP_STATEID_NFSV41 | 8425 | | NFS_CAP_STATEID_NFSV41 |
8428 | | NFS_CAP_ATOMIC_OPEN_V1 | 8426 | | NFS_CAP_ATOMIC_OPEN_V1 |
8427 | | NFS_CAP_ALLOCATE | ||
8428 | | NFS_CAP_DEALLOCATE | ||
8429 | | NFS_CAP_SEEK, | 8429 | | NFS_CAP_SEEK, |
8430 | .init_client = nfs41_init_client, | 8430 | .init_client = nfs41_init_client, |
8431 | .shutdown_client = nfs41_shutdown_client, | 8431 | .shutdown_client = nfs41_shutdown_client, |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 206c08a60c7f..cb4376b78ed9 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -141,13 +141,15 @@ static int nfs4_stat_to_errno(int); | |||
141 | XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ | 141 | XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ |
142 | XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ | 142 | XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ |
143 | 1 /* sc_prog */ + \ | 143 | 1 /* sc_prog */ + \ |
144 | XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ | 144 | 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ |
145 | XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ | 145 | 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ |
146 | 1) /* sc_cb_ident */ | 146 | 1) /* sc_cb_ident */ |
147 | #define decode_setclientid_maxsz \ | 147 | #define decode_setclientid_maxsz \ |
148 | (op_decode_hdr_maxsz + \ | 148 | (op_decode_hdr_maxsz + \ |
149 | 2 + \ | 149 | 2 /* clientid */ + \ |
150 | 1024) /* large value for CLID_INUSE */ | 150 | XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ |
151 | 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ | ||
152 | 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) | ||
151 | #define encode_setclientid_confirm_maxsz \ | 153 | #define encode_setclientid_confirm_maxsz \ |
152 | (op_encode_hdr_maxsz + \ | 154 | (op_encode_hdr_maxsz + \ |
153 | 3 + (NFS4_VERIFIER_SIZE >> 2)) | 155 | 3 + (NFS4_VERIFIER_SIZE >> 2)) |
@@ -7394,6 +7396,8 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
7394 | #endif /* CONFIG_NFS_V4_1 */ | 7396 | #endif /* CONFIG_NFS_V4_1 */ |
7395 | #ifdef CONFIG_NFS_V4_2 | 7397 | #ifdef CONFIG_NFS_V4_2 |
7396 | PROC(SEEK, enc_seek, dec_seek), | 7398 | PROC(SEEK, enc_seek, dec_seek), |
7399 | PROC(ALLOCATE, enc_allocate, dec_allocate), | ||
7400 | PROC(DEALLOCATE, enc_deallocate, dec_deallocate), | ||
7397 | #endif /* CONFIG_NFS_V4_2 */ | 7401 | #endif /* CONFIG_NFS_V4_2 */ |
7398 | }; | 7402 | }; |
7399 | 7403 | ||
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index ed0db61f8543..2b5e769beb16 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -258,6 +258,7 @@ bool nfs_page_group_sync_on_bit(struct nfs_page *req, unsigned int bit) | |||
258 | static inline void | 258 | static inline void |
259 | nfs_page_group_init(struct nfs_page *req, struct nfs_page *prev) | 259 | nfs_page_group_init(struct nfs_page *req, struct nfs_page *prev) |
260 | { | 260 | { |
261 | struct inode *inode; | ||
261 | WARN_ON_ONCE(prev == req); | 262 | WARN_ON_ONCE(prev == req); |
262 | 263 | ||
263 | if (!prev) { | 264 | if (!prev) { |
@@ -276,12 +277,16 @@ nfs_page_group_init(struct nfs_page *req, struct nfs_page *prev) | |||
276 | * nfs_page_group_destroy is called */ | 277 | * nfs_page_group_destroy is called */ |
277 | kref_get(&req->wb_head->wb_kref); | 278 | kref_get(&req->wb_head->wb_kref); |
278 | 279 | ||
279 | /* grab extra ref if head request has extra ref from | 280 | /* grab extra ref and bump the request count if head request |
280 | * the write/commit path to handle handoff between write | 281 | * has extra ref from the write/commit path to handle handoff |
281 | * and commit lists */ | 282 | * between write and commit lists. */ |
282 | if (test_bit(PG_INODE_REF, &prev->wb_head->wb_flags)) { | 283 | if (test_bit(PG_INODE_REF, &prev->wb_head->wb_flags)) { |
284 | inode = page_file_mapping(req->wb_page)->host; | ||
283 | set_bit(PG_INODE_REF, &req->wb_flags); | 285 | set_bit(PG_INODE_REF, &req->wb_flags); |
284 | kref_get(&req->wb_kref); | 286 | kref_get(&req->wb_kref); |
287 | spin_lock(&inode->i_lock); | ||
288 | NFS_I(inode)->nrequests++; | ||
289 | spin_unlock(&inode->i_lock); | ||
285 | } | 290 | } |
286 | } | 291 | } |
287 | } | 292 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index beff2769c5c5..c91a4799c562 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -269,7 +269,7 @@ int nfs_readpage(struct file *file, struct page *page) | |||
269 | dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", | 269 | dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", |
270 | page, PAGE_CACHE_SIZE, page_file_index(page)); | 270 | page, PAGE_CACHE_SIZE, page_file_index(page)); |
271 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); | 271 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); |
272 | nfs_add_stats(inode, NFSIOS_READPAGES, 1); | 272 | nfs_inc_stats(inode, NFSIOS_READPAGES); |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * Try to flush any pending writes to the file.. | 275 | * Try to flush any pending writes to the file.. |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f83b02dc9166..af3af685a9e3 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -575,7 +575,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st | |||
575 | int ret; | 575 | int ret; |
576 | 576 | ||
577 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); | 577 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); |
578 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); | 578 | nfs_inc_stats(inode, NFSIOS_WRITEPAGES); |
579 | 579 | ||
580 | nfs_pageio_cond_complete(pgio, page_file_index(page)); | 580 | nfs_pageio_cond_complete(pgio, page_file_index(page)); |
581 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); | 581 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); |
@@ -670,7 +670,8 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
670 | nfs_lock_request(req); | 670 | nfs_lock_request(req); |
671 | 671 | ||
672 | spin_lock(&inode->i_lock); | 672 | spin_lock(&inode->i_lock); |
673 | if (!nfsi->npages && NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) | 673 | if (!nfsi->nrequests && |
674 | NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) | ||
674 | inode->i_version++; | 675 | inode->i_version++; |
675 | /* | 676 | /* |
676 | * Swap-space should not get truncated. Hence no need to plug the race | 677 | * Swap-space should not get truncated. Hence no need to plug the race |
@@ -681,9 +682,11 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
681 | SetPagePrivate(req->wb_page); | 682 | SetPagePrivate(req->wb_page); |
682 | set_page_private(req->wb_page, (unsigned long)req); | 683 | set_page_private(req->wb_page, (unsigned long)req); |
683 | } | 684 | } |
684 | nfsi->npages++; | 685 | nfsi->nrequests++; |
685 | /* this a head request for a page group - mark it as having an | 686 | /* this a head request for a page group - mark it as having an |
686 | * extra reference so sub groups can follow suit */ | 687 | * extra reference so sub groups can follow suit. |
688 | * This flag also informs pgio layer when to bump nrequests when | ||
689 | * adding subrequests. */ | ||
687 | WARN_ON(test_and_set_bit(PG_INODE_REF, &req->wb_flags)); | 690 | WARN_ON(test_and_set_bit(PG_INODE_REF, &req->wb_flags)); |
688 | kref_get(&req->wb_kref); | 691 | kref_get(&req->wb_kref); |
689 | spin_unlock(&inode->i_lock); | 692 | spin_unlock(&inode->i_lock); |
@@ -709,7 +712,11 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
709 | wake_up_page(head->wb_page, PG_private); | 712 | wake_up_page(head->wb_page, PG_private); |
710 | clear_bit(PG_MAPPED, &head->wb_flags); | 713 | clear_bit(PG_MAPPED, &head->wb_flags); |
711 | } | 714 | } |
712 | nfsi->npages--; | 715 | nfsi->nrequests--; |
716 | spin_unlock(&inode->i_lock); | ||
717 | } else { | ||
718 | spin_lock(&inode->i_lock); | ||
719 | nfsi->nrequests--; | ||
713 | spin_unlock(&inode->i_lock); | 720 | spin_unlock(&inode->i_lock); |
714 | } | 721 | } |
715 | 722 | ||
@@ -1735,7 +1742,7 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
1735 | /* Don't commit yet if this is a non-blocking flush and there | 1742 | /* Don't commit yet if this is a non-blocking flush and there |
1736 | * are a lot of outstanding writes for this mapping. | 1743 | * are a lot of outstanding writes for this mapping. |
1737 | */ | 1744 | */ |
1738 | if (nfsi->commit_info.ncommit <= (nfsi->npages >> 1)) | 1745 | if (nfsi->commit_info.ncommit <= (nfsi->nrequests >> 1)) |
1739 | goto out_mark_dirty; | 1746 | goto out_mark_dirty; |
1740 | 1747 | ||
1741 | /* don't wait for the COMMIT response */ | 1748 | /* don't wait for the COMMIT response */ |
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig index e60125976873..34355818a2e0 100644 --- a/fs/overlayfs/Kconfig +++ b/fs/overlayfs/Kconfig | |||
@@ -1,4 +1,4 @@ | |||
1 | config OVERLAYFS_FS | 1 | config OVERLAY_FS |
2 | tristate "Overlay filesystem support" | 2 | tristate "Overlay filesystem support" |
3 | help | 3 | help |
4 | An overlay filesystem combines two filesystems - an 'upper' filesystem | 4 | An overlay filesystem combines two filesystems - an 'upper' filesystem |
diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile index 8f91889480d0..900daed3e91d 100644 --- a/fs/overlayfs/Makefile +++ b/fs/overlayfs/Makefile | |||
@@ -2,6 +2,6 @@ | |||
2 | # Makefile for the overlay filesystem. | 2 | # Makefile for the overlay filesystem. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_OVERLAYFS_FS) += overlayfs.o | 5 | obj-$(CONFIG_OVERLAY_FS) += overlay.o |
6 | 6 | ||
7 | overlayfs-objs := super.o inode.o dir.o readdir.o copy_up.o | 7 | overlay-objs := super.o inode.o dir.o readdir.o copy_up.o |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 15cd91ad9940..8ffc4b980f1b 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
@@ -284,8 +284,7 @@ out: | |||
284 | return ERR_PTR(err); | 284 | return ERR_PTR(err); |
285 | } | 285 | } |
286 | 286 | ||
287 | static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry, | 287 | static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry) |
288 | enum ovl_path_type type) | ||
289 | { | 288 | { |
290 | int err; | 289 | int err; |
291 | struct dentry *ret = NULL; | 290 | struct dentry *ret = NULL; |
@@ -294,8 +293,17 @@ static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry, | |||
294 | err = ovl_check_empty_dir(dentry, &list); | 293 | err = ovl_check_empty_dir(dentry, &list); |
295 | if (err) | 294 | if (err) |
296 | ret = ERR_PTR(err); | 295 | ret = ERR_PTR(err); |
297 | else if (type == OVL_PATH_MERGE) | 296 | else { |
298 | ret = ovl_clear_empty(dentry, &list); | 297 | /* |
298 | * If no upperdentry then skip clearing whiteouts. | ||
299 | * | ||
300 | * Can race with copy-up, since we don't hold the upperdir | ||
301 | * mutex. Doesn't matter, since copy-up can't create a | ||
302 | * non-empty directory from an empty one. | ||
303 | */ | ||
304 | if (ovl_dentry_upper(dentry)) | ||
305 | ret = ovl_clear_empty(dentry, &list); | ||
306 | } | ||
299 | 307 | ||
300 | ovl_cache_free(&list); | 308 | ovl_cache_free(&list); |
301 | 309 | ||
@@ -487,8 +495,7 @@ out: | |||
487 | return err; | 495 | return err; |
488 | } | 496 | } |
489 | 497 | ||
490 | static int ovl_remove_and_whiteout(struct dentry *dentry, | 498 | static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir) |
491 | enum ovl_path_type type, bool is_dir) | ||
492 | { | 499 | { |
493 | struct dentry *workdir = ovl_workdir(dentry); | 500 | struct dentry *workdir = ovl_workdir(dentry); |
494 | struct inode *wdir = workdir->d_inode; | 501 | struct inode *wdir = workdir->d_inode; |
@@ -500,7 +507,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, | |||
500 | int err; | 507 | int err; |
501 | 508 | ||
502 | if (is_dir) { | 509 | if (is_dir) { |
503 | opaquedir = ovl_check_empty_and_clear(dentry, type); | 510 | opaquedir = ovl_check_empty_and_clear(dentry); |
504 | err = PTR_ERR(opaquedir); | 511 | err = PTR_ERR(opaquedir); |
505 | if (IS_ERR(opaquedir)) | 512 | if (IS_ERR(opaquedir)) |
506 | goto out; | 513 | goto out; |
@@ -515,9 +522,10 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, | |||
515 | if (IS_ERR(whiteout)) | 522 | if (IS_ERR(whiteout)) |
516 | goto out_unlock; | 523 | goto out_unlock; |
517 | 524 | ||
518 | if (type == OVL_PATH_LOWER) { | 525 | upper = ovl_dentry_upper(dentry); |
526 | if (!upper) { | ||
519 | upper = lookup_one_len(dentry->d_name.name, upperdir, | 527 | upper = lookup_one_len(dentry->d_name.name, upperdir, |
520 | dentry->d_name.len); | 528 | dentry->d_name.len); |
521 | err = PTR_ERR(upper); | 529 | err = PTR_ERR(upper); |
522 | if (IS_ERR(upper)) | 530 | if (IS_ERR(upper)) |
523 | goto kill_whiteout; | 531 | goto kill_whiteout; |
@@ -529,7 +537,6 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, | |||
529 | } else { | 537 | } else { |
530 | int flags = 0; | 538 | int flags = 0; |
531 | 539 | ||
532 | upper = ovl_dentry_upper(dentry); | ||
533 | if (opaquedir) | 540 | if (opaquedir) |
534 | upper = opaquedir; | 541 | upper = opaquedir; |
535 | err = -ESTALE; | 542 | err = -ESTALE; |
@@ -648,7 +655,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) | |||
648 | cap_raise(override_cred->cap_effective, CAP_CHOWN); | 655 | cap_raise(override_cred->cap_effective, CAP_CHOWN); |
649 | old_cred = override_creds(override_cred); | 656 | old_cred = override_creds(override_cred); |
650 | 657 | ||
651 | err = ovl_remove_and_whiteout(dentry, type, is_dir); | 658 | err = ovl_remove_and_whiteout(dentry, is_dir); |
652 | 659 | ||
653 | revert_creds(old_cred); | 660 | revert_creds(old_cred); |
654 | put_cred(override_cred); | 661 | put_cred(override_cred); |
@@ -781,7 +788,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
781 | } | 788 | } |
782 | 789 | ||
783 | if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) { | 790 | if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) { |
784 | opaquedir = ovl_check_empty_and_clear(new, new_type); | 791 | opaquedir = ovl_check_empty_and_clear(new); |
785 | err = PTR_ERR(opaquedir); | 792 | err = PTR_ERR(opaquedir); |
786 | if (IS_ERR(opaquedir)) { | 793 | if (IS_ERR(opaquedir)) { |
787 | opaquedir = NULL; | 794 | opaquedir = NULL; |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index af2d18c9fcee..07d74b24913b 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -235,26 +235,36 @@ out: | |||
235 | return err; | 235 | return err; |
236 | } | 236 | } |
237 | 237 | ||
238 | static bool ovl_need_xattr_filter(struct dentry *dentry, | ||
239 | enum ovl_path_type type) | ||
240 | { | ||
241 | return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode); | ||
242 | } | ||
243 | |||
238 | ssize_t ovl_getxattr(struct dentry *dentry, const char *name, | 244 | ssize_t ovl_getxattr(struct dentry *dentry, const char *name, |
239 | void *value, size_t size) | 245 | void *value, size_t size) |
240 | { | 246 | { |
241 | if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && | 247 | struct path realpath; |
242 | ovl_is_private_xattr(name)) | 248 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); |
249 | |||
250 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | ||
243 | return -ENODATA; | 251 | return -ENODATA; |
244 | 252 | ||
245 | return vfs_getxattr(ovl_dentry_real(dentry), name, value, size); | 253 | return vfs_getxattr(realpath.dentry, name, value, size); |
246 | } | 254 | } |
247 | 255 | ||
248 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) | 256 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) |
249 | { | 257 | { |
258 | struct path realpath; | ||
259 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
250 | ssize_t res; | 260 | ssize_t res; |
251 | int off; | 261 | int off; |
252 | 262 | ||
253 | res = vfs_listxattr(ovl_dentry_real(dentry), list, size); | 263 | res = vfs_listxattr(realpath.dentry, list, size); |
254 | if (res <= 0 || size == 0) | 264 | if (res <= 0 || size == 0) |
255 | return res; | 265 | return res; |
256 | 266 | ||
257 | if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE) | 267 | if (!ovl_need_xattr_filter(dentry, type)) |
258 | return res; | 268 | return res; |
259 | 269 | ||
260 | /* filter out private xattrs */ | 270 | /* filter out private xattrs */ |
@@ -279,17 +289,16 @@ int ovl_removexattr(struct dentry *dentry, const char *name) | |||
279 | { | 289 | { |
280 | int err; | 290 | int err; |
281 | struct path realpath; | 291 | struct path realpath; |
282 | enum ovl_path_type type; | 292 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); |
283 | 293 | ||
284 | err = ovl_want_write(dentry); | 294 | err = ovl_want_write(dentry); |
285 | if (err) | 295 | if (err) |
286 | goto out; | 296 | goto out; |
287 | 297 | ||
288 | if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && | 298 | err = -ENODATA; |
289 | ovl_is_private_xattr(name)) | 299 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) |
290 | goto out_drop_write; | 300 | goto out_drop_write; |
291 | 301 | ||
292 | type = ovl_path_real(dentry, &realpath); | ||
293 | if (type == OVL_PATH_LOWER) { | 302 | if (type == OVL_PATH_LOWER) { |
294 | err = vfs_getxattr(realpath.dentry, name, NULL, 0); | 303 | err = vfs_getxattr(realpath.dentry, name, NULL, 0); |
295 | if (err < 0) | 304 | if (err < 0) |
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 2a7ef4f8e2a6..ab1e3dcbed95 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c | |||
@@ -274,11 +274,11 @@ static int ovl_dir_mark_whiteouts(struct dentry *dir, | |||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
276 | 276 | ||
277 | static inline int ovl_dir_read_merged(struct path *upperpath, | 277 | static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) |
278 | struct path *lowerpath, | ||
279 | struct list_head *list) | ||
280 | { | 278 | { |
281 | int err; | 279 | int err; |
280 | struct path lowerpath; | ||
281 | struct path upperpath; | ||
282 | struct ovl_readdir_data rdd = { | 282 | struct ovl_readdir_data rdd = { |
283 | .ctx.actor = ovl_fill_merge, | 283 | .ctx.actor = ovl_fill_merge, |
284 | .list = list, | 284 | .list = list, |
@@ -286,25 +286,28 @@ static inline int ovl_dir_read_merged(struct path *upperpath, | |||
286 | .is_merge = false, | 286 | .is_merge = false, |
287 | }; | 287 | }; |
288 | 288 | ||
289 | if (upperpath->dentry) { | 289 | ovl_path_lower(dentry, &lowerpath); |
290 | err = ovl_dir_read(upperpath, &rdd); | 290 | ovl_path_upper(dentry, &upperpath); |
291 | |||
292 | if (upperpath.dentry) { | ||
293 | err = ovl_dir_read(&upperpath, &rdd); | ||
291 | if (err) | 294 | if (err) |
292 | goto out; | 295 | goto out; |
293 | 296 | ||
294 | if (lowerpath->dentry) { | 297 | if (lowerpath.dentry) { |
295 | err = ovl_dir_mark_whiteouts(upperpath->dentry, &rdd); | 298 | err = ovl_dir_mark_whiteouts(upperpath.dentry, &rdd); |
296 | if (err) | 299 | if (err) |
297 | goto out; | 300 | goto out; |
298 | } | 301 | } |
299 | } | 302 | } |
300 | if (lowerpath->dentry) { | 303 | if (lowerpath.dentry) { |
301 | /* | 304 | /* |
302 | * Insert lowerpath entries before upperpath ones, this allows | 305 | * Insert lowerpath entries before upperpath ones, this allows |
303 | * offsets to be reasonably constant | 306 | * offsets to be reasonably constant |
304 | */ | 307 | */ |
305 | list_add(&rdd.middle, rdd.list); | 308 | list_add(&rdd.middle, rdd.list); |
306 | rdd.is_merge = true; | 309 | rdd.is_merge = true; |
307 | err = ovl_dir_read(lowerpath, &rdd); | 310 | err = ovl_dir_read(&lowerpath, &rdd); |
308 | list_del(&rdd.middle); | 311 | list_del(&rdd.middle); |
309 | } | 312 | } |
310 | out: | 313 | out: |
@@ -329,8 +332,6 @@ static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) | |||
329 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | 332 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) |
330 | { | 333 | { |
331 | int res; | 334 | int res; |
332 | struct path lowerpath; | ||
333 | struct path upperpath; | ||
334 | struct ovl_dir_cache *cache; | 335 | struct ovl_dir_cache *cache; |
335 | 336 | ||
336 | cache = ovl_dir_cache(dentry); | 337 | cache = ovl_dir_cache(dentry); |
@@ -347,10 +348,7 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | |||
347 | cache->refcount = 1; | 348 | cache->refcount = 1; |
348 | INIT_LIST_HEAD(&cache->entries); | 349 | INIT_LIST_HEAD(&cache->entries); |
349 | 350 | ||
350 | ovl_path_lower(dentry, &lowerpath); | 351 | res = ovl_dir_read_merged(dentry, &cache->entries); |
351 | ovl_path_upper(dentry, &upperpath); | ||
352 | |||
353 | res = ovl_dir_read_merged(&upperpath, &lowerpath, &cache->entries); | ||
354 | if (res) { | 352 | if (res) { |
355 | ovl_cache_free(&cache->entries); | 353 | ovl_cache_free(&cache->entries); |
356 | kfree(cache); | 354 | kfree(cache); |
@@ -452,10 +450,10 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, | |||
452 | /* | 450 | /* |
453 | * Need to check if we started out being a lower dir, but got copied up | 451 | * Need to check if we started out being a lower dir, but got copied up |
454 | */ | 452 | */ |
455 | if (!od->is_upper && ovl_path_type(dentry) == OVL_PATH_MERGE) { | 453 | if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) { |
456 | struct inode *inode = file_inode(file); | 454 | struct inode *inode = file_inode(file); |
457 | 455 | ||
458 | realfile =lockless_dereference(od->upperfile); | 456 | realfile = lockless_dereference(od->upperfile); |
459 | if (!realfile) { | 457 | if (!realfile) { |
460 | struct path upperpath; | 458 | struct path upperpath; |
461 | 459 | ||
@@ -538,14 +536,9 @@ const struct file_operations ovl_dir_operations = { | |||
538 | int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) | 536 | int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) |
539 | { | 537 | { |
540 | int err; | 538 | int err; |
541 | struct path lowerpath; | ||
542 | struct path upperpath; | ||
543 | struct ovl_cache_entry *p; | 539 | struct ovl_cache_entry *p; |
544 | 540 | ||
545 | ovl_path_upper(dentry, &upperpath); | 541 | err = ovl_dir_read_merged(dentry, list); |
546 | ovl_path_lower(dentry, &lowerpath); | ||
547 | |||
548 | err = ovl_dir_read_merged(&upperpath, &lowerpath, list); | ||
549 | if (err) | 542 | if (err) |
550 | return err; | 543 | return err; |
551 | 544 | ||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 08b704cebfc4..f16d318b71f8 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -24,7 +24,7 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); | |||
24 | MODULE_DESCRIPTION("Overlay filesystem"); | 24 | MODULE_DESCRIPTION("Overlay filesystem"); |
25 | MODULE_LICENSE("GPL"); | 25 | MODULE_LICENSE("GPL"); |
26 | 26 | ||
27 | #define OVERLAYFS_SUPER_MAGIC 0x794c764f | 27 | #define OVERLAYFS_SUPER_MAGIC 0x794c7630 |
28 | 28 | ||
29 | struct ovl_config { | 29 | struct ovl_config { |
30 | char *lowerdir; | 30 | char *lowerdir; |
@@ -84,12 +84,7 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry) | |||
84 | 84 | ||
85 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) | 85 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) |
86 | { | 86 | { |
87 | struct dentry *upperdentry = ACCESS_ONCE(oe->__upperdentry); | 87 | return lockless_dereference(oe->__upperdentry); |
88 | /* | ||
89 | * Make sure to order reads to upperdentry wrt ovl_dentry_update() | ||
90 | */ | ||
91 | smp_read_barrier_depends(); | ||
92 | return upperdentry; | ||
93 | } | 88 | } |
94 | 89 | ||
95 | void ovl_path_upper(struct dentry *dentry, struct path *path) | 90 | void ovl_path_upper(struct dentry *dentry, struct path *path) |
@@ -462,11 +457,34 @@ static const match_table_t ovl_tokens = { | |||
462 | {OPT_ERR, NULL} | 457 | {OPT_ERR, NULL} |
463 | }; | 458 | }; |
464 | 459 | ||
460 | static char *ovl_next_opt(char **s) | ||
461 | { | ||
462 | char *sbegin = *s; | ||
463 | char *p; | ||
464 | |||
465 | if (sbegin == NULL) | ||
466 | return NULL; | ||
467 | |||
468 | for (p = sbegin; *p; p++) { | ||
469 | if (*p == '\\') { | ||
470 | p++; | ||
471 | if (!*p) | ||
472 | break; | ||
473 | } else if (*p == ',') { | ||
474 | *p = '\0'; | ||
475 | *s = p + 1; | ||
476 | return sbegin; | ||
477 | } | ||
478 | } | ||
479 | *s = NULL; | ||
480 | return sbegin; | ||
481 | } | ||
482 | |||
465 | static int ovl_parse_opt(char *opt, struct ovl_config *config) | 483 | static int ovl_parse_opt(char *opt, struct ovl_config *config) |
466 | { | 484 | { |
467 | char *p; | 485 | char *p; |
468 | 486 | ||
469 | while ((p = strsep(&opt, ",")) != NULL) { | 487 | while ((p = ovl_next_opt(&opt)) != NULL) { |
470 | int token; | 488 | int token; |
471 | substring_t args[MAX_OPT_ARGS]; | 489 | substring_t args[MAX_OPT_ARGS]; |
472 | 490 | ||
@@ -554,15 +572,34 @@ out_dput: | |||
554 | goto out_unlock; | 572 | goto out_unlock; |
555 | } | 573 | } |
556 | 574 | ||
575 | static void ovl_unescape(char *s) | ||
576 | { | ||
577 | char *d = s; | ||
578 | |||
579 | for (;; s++, d++) { | ||
580 | if (*s == '\\') | ||
581 | s++; | ||
582 | *d = *s; | ||
583 | if (!*s) | ||
584 | break; | ||
585 | } | ||
586 | } | ||
587 | |||
557 | static int ovl_mount_dir(const char *name, struct path *path) | 588 | static int ovl_mount_dir(const char *name, struct path *path) |
558 | { | 589 | { |
559 | int err; | 590 | int err; |
591 | char *tmp = kstrdup(name, GFP_KERNEL); | ||
592 | |||
593 | if (!tmp) | ||
594 | return -ENOMEM; | ||
560 | 595 | ||
561 | err = kern_path(name, LOOKUP_FOLLOW, path); | 596 | ovl_unescape(tmp); |
597 | err = kern_path(tmp, LOOKUP_FOLLOW, path); | ||
562 | if (err) { | 598 | if (err) { |
563 | pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); | 599 | pr_err("overlayfs: failed to resolve '%s': %i\n", tmp, err); |
564 | err = -EINVAL; | 600 | err = -EINVAL; |
565 | } | 601 | } |
602 | kfree(tmp); | ||
566 | return err; | 603 | return err; |
567 | } | 604 | } |
568 | 605 | ||
@@ -776,11 +813,11 @@ static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags, | |||
776 | 813 | ||
777 | static struct file_system_type ovl_fs_type = { | 814 | static struct file_system_type ovl_fs_type = { |
778 | .owner = THIS_MODULE, | 815 | .owner = THIS_MODULE, |
779 | .name = "overlayfs", | 816 | .name = "overlay", |
780 | .mount = ovl_mount, | 817 | .mount = ovl_mount, |
781 | .kill_sb = kill_anon_super, | 818 | .kill_sb = kill_anon_super, |
782 | }; | 819 | }; |
783 | MODULE_ALIAS_FS("overlayfs"); | 820 | MODULE_ALIAS_FS("overlay"); |
784 | 821 | ||
785 | static int __init ovl_init(void) | 822 | static int __init ovl_init(void) |
786 | { | 823 | { |