diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-30 22:21:03 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-30 22:21:03 -0500 |
commit | c00552ebafddfe6abb397d957004f165e010abd2 (patch) | |
tree | b397d6773b545755ffdae7566f8b96b08ee54ebb /fs | |
parent | 842f57baab186417d89810f3dd6147f1ef3009dd (diff) | |
parent | 009d0431c3914de64666bec0d350e54fdd59df6a (diff) |
Merge 3.18-rc7 into usb-next
We need the xhci fixes here and this resolves a merge issue with
drivers/usb/dwc3/ep0.c
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
36 files changed, 397 insertions, 203 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/ |
@@ -165,6 +165,15 @@ static struct vfsmount *aio_mnt; | |||
165 | static const struct file_operations aio_ring_fops; | 165 | static const struct file_operations aio_ring_fops; |
166 | static const struct address_space_operations aio_ctx_aops; | 166 | static const struct address_space_operations aio_ctx_aops; |
167 | 167 | ||
168 | /* Backing dev info for aio fs. | ||
169 | * -no dirty page accounting or writeback happens | ||
170 | */ | ||
171 | static struct backing_dev_info aio_fs_backing_dev_info = { | ||
172 | .name = "aiofs", | ||
173 | .state = 0, | ||
174 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_MAP_COPY, | ||
175 | }; | ||
176 | |||
168 | static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) | 177 | static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) |
169 | { | 178 | { |
170 | struct qstr this = QSTR_INIT("[aio]", 5); | 179 | struct qstr this = QSTR_INIT("[aio]", 5); |
@@ -176,6 +185,7 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) | |||
176 | 185 | ||
177 | inode->i_mapping->a_ops = &aio_ctx_aops; | 186 | inode->i_mapping->a_ops = &aio_ctx_aops; |
178 | inode->i_mapping->private_data = ctx; | 187 | inode->i_mapping->private_data = ctx; |
188 | inode->i_mapping->backing_dev_info = &aio_fs_backing_dev_info; | ||
179 | inode->i_size = PAGE_SIZE * nr_pages; | 189 | inode->i_size = PAGE_SIZE * nr_pages; |
180 | 190 | ||
181 | path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this); | 191 | path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this); |
@@ -220,6 +230,9 @@ static int __init aio_setup(void) | |||
220 | if (IS_ERR(aio_mnt)) | 230 | if (IS_ERR(aio_mnt)) |
221 | panic("Failed to create aio fs mount."); | 231 | panic("Failed to create aio fs mount."); |
222 | 232 | ||
233 | if (bdi_init(&aio_fs_backing_dev_info)) | ||
234 | panic("Failed to init aio fs backing dev info."); | ||
235 | |||
223 | kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC); | 236 | kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC); |
224 | kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); | 237 | kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); |
225 | 238 | ||
@@ -281,11 +294,6 @@ static const struct file_operations aio_ring_fops = { | |||
281 | .mmap = aio_ring_mmap, | 294 | .mmap = aio_ring_mmap, |
282 | }; | 295 | }; |
283 | 296 | ||
284 | static int aio_set_page_dirty(struct page *page) | ||
285 | { | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | #if IS_ENABLED(CONFIG_MIGRATION) | 297 | #if IS_ENABLED(CONFIG_MIGRATION) |
290 | static int aio_migratepage(struct address_space *mapping, struct page *new, | 298 | static int aio_migratepage(struct address_space *mapping, struct page *new, |
291 | struct page *old, enum migrate_mode mode) | 299 | struct page *old, enum migrate_mode mode) |
@@ -357,7 +365,7 @@ out: | |||
357 | #endif | 365 | #endif |
358 | 366 | ||
359 | static const struct address_space_operations aio_ctx_aops = { | 367 | static const struct address_space_operations aio_ctx_aops = { |
360 | .set_page_dirty = aio_set_page_dirty, | 368 | .set_page_dirty = __set_page_dirty_no_writeback, |
361 | #if IS_ENABLED(CONFIG_MIGRATION) | 369 | #if IS_ENABLED(CONFIG_MIGRATION) |
362 | .migratepage = aio_migratepage, | 370 | .migratepage = aio_migratepage, |
363 | #endif | 371 | #endif |
@@ -412,7 +420,6 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
412 | pr_debug("pid(%d) page[%d]->count=%d\n", | 420 | pr_debug("pid(%d) page[%d]->count=%d\n", |
413 | current->pid, i, page_count(page)); | 421 | current->pid, i, page_count(page)); |
414 | SetPageUptodate(page); | 422 | SetPageUptodate(page); |
415 | SetPageDirty(page); | ||
416 | unlock_page(page); | 423 | unlock_page(page); |
417 | 424 | ||
418 | ctx->ring_pages[i] = page; | 425 | ctx->ring_pages[i] = page; |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index d3220d31d3cb..dcd9be32ac57 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
@@ -1011,8 +1011,6 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
1011 | bytes = min(bytes, working_bytes); | 1011 | bytes = min(bytes, working_bytes); |
1012 | kaddr = kmap_atomic(page_out); | 1012 | kaddr = kmap_atomic(page_out); |
1013 | memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); | 1013 | memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); |
1014 | if (*pg_index == (vcnt - 1) && *pg_offset == 0) | ||
1015 | memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); | ||
1016 | kunmap_atomic(kaddr); | 1014 | kunmap_atomic(kaddr); |
1017 | flush_dcache_page(page_out); | 1015 | flush_dcache_page(page_out); |
1018 | 1016 | ||
@@ -1054,3 +1052,34 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
1054 | 1052 | ||
1055 | return 1; | 1053 | return 1; |
1056 | } | 1054 | } |
1055 | |||
1056 | /* | ||
1057 | * When uncompressing data, we need to make sure and zero any parts of | ||
1058 | * the biovec that were not filled in by the decompression code. pg_index | ||
1059 | * and pg_offset indicate the last page and the last offset of that page | ||
1060 | * that have been filled in. This will zero everything remaining in the | ||
1061 | * biovec. | ||
1062 | */ | ||
1063 | void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt, | ||
1064 | unsigned long pg_index, | ||
1065 | unsigned long pg_offset) | ||
1066 | { | ||
1067 | while (pg_index < vcnt) { | ||
1068 | struct page *page = bvec[pg_index].bv_page; | ||
1069 | unsigned long off = bvec[pg_index].bv_offset; | ||
1070 | unsigned long len = bvec[pg_index].bv_len; | ||
1071 | |||
1072 | if (pg_offset < off) | ||
1073 | pg_offset = off; | ||
1074 | if (pg_offset < off + len) { | ||
1075 | unsigned long bytes = off + len - pg_offset; | ||
1076 | char *kaddr; | ||
1077 | |||
1078 | kaddr = kmap_atomic(page); | ||
1079 | memset(kaddr + pg_offset, 0, bytes); | ||
1080 | kunmap_atomic(kaddr); | ||
1081 | } | ||
1082 | pg_index++; | ||
1083 | pg_offset = 0; | ||
1084 | } | ||
1085 | } | ||
diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h index 0c803b4fbf93..d181f70caae0 100644 --- a/fs/btrfs/compression.h +++ b/fs/btrfs/compression.h | |||
@@ -45,7 +45,9 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
45 | unsigned long nr_pages); | 45 | unsigned long nr_pages); |
46 | int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | 46 | int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, |
47 | int mirror_num, unsigned long bio_flags); | 47 | int mirror_num, unsigned long bio_flags); |
48 | 48 | void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt, | |
49 | unsigned long pg_index, | ||
50 | unsigned long pg_offset); | ||
49 | struct btrfs_compress_op { | 51 | struct btrfs_compress_op { |
50 | struct list_head *(*alloc_workspace)(void); | 52 | struct list_head *(*alloc_workspace)(void); |
51 | 53 | ||
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/btrfs/lzo.c b/fs/btrfs/lzo.c index 78285f30909e..617553cdb7d3 100644 --- a/fs/btrfs/lzo.c +++ b/fs/btrfs/lzo.c | |||
@@ -373,6 +373,8 @@ cont: | |||
373 | } | 373 | } |
374 | done: | 374 | done: |
375 | kunmap(pages_in[page_in_index]); | 375 | kunmap(pages_in[page_in_index]); |
376 | if (!ret) | ||
377 | btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset); | ||
376 | return ret; | 378 | return ret; |
377 | } | 379 | } |
378 | 380 | ||
@@ -410,10 +412,23 @@ static int lzo_decompress(struct list_head *ws, unsigned char *data_in, | |||
410 | goto out; | 412 | goto out; |
411 | } | 413 | } |
412 | 414 | ||
415 | /* | ||
416 | * the caller is already checking against PAGE_SIZE, but lets | ||
417 | * move this check closer to the memcpy/memset | ||
418 | */ | ||
419 | destlen = min_t(unsigned long, destlen, PAGE_SIZE); | ||
413 | bytes = min_t(unsigned long, destlen, out_len - start_byte); | 420 | bytes = min_t(unsigned long, destlen, out_len - start_byte); |
414 | 421 | ||
415 | kaddr = kmap_atomic(dest_page); | 422 | kaddr = kmap_atomic(dest_page); |
416 | memcpy(kaddr, workspace->buf + start_byte, bytes); | 423 | memcpy(kaddr, workspace->buf + start_byte, bytes); |
424 | |||
425 | /* | ||
426 | * btrfs_getblock is doing a zero on the tail of the page too, | ||
427 | * but this will cover anything missing from the decompressed | ||
428 | * data. | ||
429 | */ | ||
430 | if (bytes < destlen) | ||
431 | memset(kaddr+bytes, 0, destlen-bytes); | ||
417 | kunmap_atomic(kaddr); | 432 | kunmap_atomic(kaddr); |
418 | out: | 433 | out: |
419 | return ret; | 434 | return ret; |
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index 759fa4e2de8f..fb22fd8d8fb8 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c | |||
@@ -299,6 +299,8 @@ done: | |||
299 | zlib_inflateEnd(&workspace->strm); | 299 | zlib_inflateEnd(&workspace->strm); |
300 | if (data_in) | 300 | if (data_in) |
301 | kunmap(pages_in[page_in_index]); | 301 | kunmap(pages_in[page_in_index]); |
302 | if (!ret) | ||
303 | btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset); | ||
302 | return ret; | 304 | return ret; |
303 | } | 305 | } |
304 | 306 | ||
@@ -310,10 +312,14 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in, | |||
310 | struct workspace *workspace = list_entry(ws, struct workspace, list); | 312 | struct workspace *workspace = list_entry(ws, struct workspace, list); |
311 | int ret = 0; | 313 | int ret = 0; |
312 | int wbits = MAX_WBITS; | 314 | int wbits = MAX_WBITS; |
313 | unsigned long bytes_left = destlen; | 315 | unsigned long bytes_left; |
314 | unsigned long total_out = 0; | 316 | unsigned long total_out = 0; |
317 | unsigned long pg_offset = 0; | ||
315 | char *kaddr; | 318 | char *kaddr; |
316 | 319 | ||
320 | destlen = min_t(unsigned long, destlen, PAGE_SIZE); | ||
321 | bytes_left = destlen; | ||
322 | |||
317 | workspace->strm.next_in = data_in; | 323 | workspace->strm.next_in = data_in; |
318 | workspace->strm.avail_in = srclen; | 324 | workspace->strm.avail_in = srclen; |
319 | workspace->strm.total_in = 0; | 325 | workspace->strm.total_in = 0; |
@@ -341,7 +347,6 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in, | |||
341 | unsigned long buf_start; | 347 | unsigned long buf_start; |
342 | unsigned long buf_offset; | 348 | unsigned long buf_offset; |
343 | unsigned long bytes; | 349 | unsigned long bytes; |
344 | unsigned long pg_offset = 0; | ||
345 | 350 | ||
346 | ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH); | 351 | ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH); |
347 | if (ret != Z_OK && ret != Z_STREAM_END) | 352 | if (ret != Z_OK && ret != Z_STREAM_END) |
@@ -384,6 +389,17 @@ next: | |||
384 | ret = 0; | 389 | ret = 0; |
385 | 390 | ||
386 | zlib_inflateEnd(&workspace->strm); | 391 | zlib_inflateEnd(&workspace->strm); |
392 | |||
393 | /* | ||
394 | * this should only happen if zlib returned fewer bytes than we | ||
395 | * expected. btrfs_get_block is responsible for zeroing from the | ||
396 | * end of the inline extent (destlen) to the end of the page | ||
397 | */ | ||
398 | if (pg_offset < destlen) { | ||
399 | kaddr = kmap_atomic(dest_page); | ||
400 | memset(kaddr + pg_offset, 0, destlen - pg_offset); | ||
401 | kunmap_atomic(kaddr); | ||
402 | } | ||
387 | return ret; | 403 | return ret; |
388 | } | 404 | } |
389 | 405 | ||
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 659f2ea9e6f7..cefca661464b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -2638,7 +2638,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, | |||
2638 | 2638 | ||
2639 | for (i = 0; i < CEPH_CAP_BITS; i++) | 2639 | for (i = 0; i < CEPH_CAP_BITS; i++) |
2640 | if ((dirty & (1 << i)) && | 2640 | if ((dirty & (1 << i)) && |
2641 | flush_tid == ci->i_cap_flush_tid[i]) | 2641 | (u16)flush_tid == ci->i_cap_flush_tid[i]) |
2642 | cleaned |= 1 << i; | 2642 | cleaned |= 1 << i; |
2643 | 2643 | ||
2644 | dout("handle_cap_flush_ack inode %p mds%d seq %d on %s cleaned %s," | 2644 | dout("handle_cap_flush_ack inode %p mds%d seq %d on %s cleaned %s," |
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/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 5228f201d3d5..4f46f7a05289 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -378,7 +378,7 @@ bl_write_pagelist(struct nfs_pgio_header *header, int sync) | |||
378 | loff_t offset = header->args.offset; | 378 | loff_t offset = header->args.offset; |
379 | size_t count = header->args.count; | 379 | size_t count = header->args.count; |
380 | struct page **pages = header->args.pages; | 380 | struct page **pages = header->args.pages; |
381 | int pg_index = pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT; | 381 | int pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT; |
382 | unsigned int pg_len; | 382 | unsigned int pg_len; |
383 | struct blk_plug plug; | 383 | struct blk_plug plug; |
384 | int i; | 384 | int i; |
diff --git a/fs/nfs/blocklayout/rpc_pipefs.c b/fs/nfs/blocklayout/rpc_pipefs.c index e966c023b1b7..acbf9ca4018c 100644 --- a/fs/nfs/blocklayout/rpc_pipefs.c +++ b/fs/nfs/blocklayout/rpc_pipefs.c | |||
@@ -65,17 +65,18 @@ bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b, | |||
65 | 65 | ||
66 | dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); | 66 | dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); |
67 | 67 | ||
68 | mutex_lock(&nn->bl_mutex); | ||
68 | bl_pipe_msg.bl_wq = &nn->bl_wq; | 69 | bl_pipe_msg.bl_wq = &nn->bl_wq; |
69 | 70 | ||
70 | b->simple.len += 4; /* single volume */ | 71 | b->simple.len += 4; /* single volume */ |
71 | if (b->simple.len > PAGE_SIZE) | 72 | if (b->simple.len > PAGE_SIZE) |
72 | return -EIO; | 73 | goto out_unlock; |
73 | 74 | ||
74 | memset(msg, 0, sizeof(*msg)); | 75 | memset(msg, 0, sizeof(*msg)); |
75 | msg->len = sizeof(*bl_msg) + b->simple.len; | 76 | msg->len = sizeof(*bl_msg) + b->simple.len; |
76 | msg->data = kzalloc(msg->len, gfp_mask); | 77 | msg->data = kzalloc(msg->len, gfp_mask); |
77 | if (!msg->data) | 78 | if (!msg->data) |
78 | goto out; | 79 | goto out_free_data; |
79 | 80 | ||
80 | bl_msg = msg->data; | 81 | bl_msg = msg->data; |
81 | bl_msg->type = BL_DEVICE_MOUNT, | 82 | bl_msg->type = BL_DEVICE_MOUNT, |
@@ -87,7 +88,7 @@ bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b, | |||
87 | rc = rpc_queue_upcall(nn->bl_device_pipe, msg); | 88 | rc = rpc_queue_upcall(nn->bl_device_pipe, msg); |
88 | if (rc < 0) { | 89 | if (rc < 0) { |
89 | remove_wait_queue(&nn->bl_wq, &wq); | 90 | remove_wait_queue(&nn->bl_wq, &wq); |
90 | goto out; | 91 | goto out_free_data; |
91 | } | 92 | } |
92 | 93 | ||
93 | set_current_state(TASK_UNINTERRUPTIBLE); | 94 | set_current_state(TASK_UNINTERRUPTIBLE); |
@@ -97,12 +98,14 @@ bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b, | |||
97 | if (reply->status != BL_DEVICE_REQUEST_PROC) { | 98 | if (reply->status != BL_DEVICE_REQUEST_PROC) { |
98 | printk(KERN_WARNING "%s failed to decode device: %d\n", | 99 | printk(KERN_WARNING "%s failed to decode device: %d\n", |
99 | __func__, reply->status); | 100 | __func__, reply->status); |
100 | goto out; | 101 | goto out_free_data; |
101 | } | 102 | } |
102 | 103 | ||
103 | dev = MKDEV(reply->major, reply->minor); | 104 | dev = MKDEV(reply->major, reply->minor); |
104 | out: | 105 | out_free_data: |
105 | kfree(msg->data); | 106 | kfree(msg->data); |
107 | out_unlock: | ||
108 | mutex_unlock(&nn->bl_mutex); | ||
106 | return dev; | 109 | return dev; |
107 | } | 110 | } |
108 | 111 | ||
@@ -232,6 +235,7 @@ static int nfs4blocklayout_net_init(struct net *net) | |||
232 | struct nfs_net *nn = net_generic(net, nfs_net_id); | 235 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
233 | struct dentry *dentry; | 236 | struct dentry *dentry; |
234 | 237 | ||
238 | mutex_init(&nn->bl_mutex); | ||
235 | init_waitqueue_head(&nn->bl_wq); | 239 | init_waitqueue_head(&nn->bl_wq); |
236 | nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0); | 240 | nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0); |
237 | if (IS_ERR(nn->bl_device_pipe)) | 241 | if (IS_ERR(nn->bl_device_pipe)) |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 5853f53db732..7f3f60641344 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -125,6 +125,8 @@ again: | |||
125 | continue; | 125 | continue; |
126 | if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) | 126 | if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) |
127 | continue; | 127 | continue; |
128 | if (!nfs4_valid_open_stateid(state)) | ||
129 | continue; | ||
128 | if (!nfs4_stateid_match(&state->stateid, stateid)) | 130 | if (!nfs4_stateid_match(&state->stateid, stateid)) |
129 | continue; | 131 | continue; |
130 | get_nfs_open_context(ctx); | 132 | get_nfs_open_context(ctx); |
@@ -193,7 +195,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation * | |||
193 | { | 195 | { |
194 | int res = 0; | 196 | int res = 0; |
195 | 197 | ||
196 | res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); | 198 | if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) |
199 | res = nfs4_proc_delegreturn(inode, | ||
200 | delegation->cred, | ||
201 | &delegation->stateid, | ||
202 | issync); | ||
197 | nfs_free_delegation(delegation); | 203 | nfs_free_delegation(delegation); |
198 | return res; | 204 | return res; |
199 | } | 205 | } |
@@ -380,11 +386,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation | |||
380 | { | 386 | { |
381 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 387 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
382 | struct nfs_inode *nfsi = NFS_I(inode); | 388 | struct nfs_inode *nfsi = NFS_I(inode); |
383 | int err; | 389 | int err = 0; |
384 | 390 | ||
385 | if (delegation == NULL) | 391 | if (delegation == NULL) |
386 | return 0; | 392 | return 0; |
387 | do { | 393 | do { |
394 | if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) | ||
395 | break; | ||
388 | err = nfs_delegation_claim_opens(inode, &delegation->stateid); | 396 | err = nfs_delegation_claim_opens(inode, &delegation->stateid); |
389 | if (!issync || err != -EAGAIN) | 397 | if (!issync || err != -EAGAIN) |
390 | break; | 398 | break; |
@@ -605,10 +613,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl | |||
605 | rcu_read_unlock(); | 613 | rcu_read_unlock(); |
606 | } | 614 | } |
607 | 615 | ||
616 | static void nfs_revoke_delegation(struct inode *inode) | ||
617 | { | ||
618 | struct nfs_delegation *delegation; | ||
619 | rcu_read_lock(); | ||
620 | delegation = rcu_dereference(NFS_I(inode)->delegation); | ||
621 | if (delegation != NULL) { | ||
622 | set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); | ||
623 | nfs_mark_return_delegation(NFS_SERVER(inode), delegation); | ||
624 | } | ||
625 | rcu_read_unlock(); | ||
626 | } | ||
627 | |||
608 | void nfs_remove_bad_delegation(struct inode *inode) | 628 | void nfs_remove_bad_delegation(struct inode *inode) |
609 | { | 629 | { |
610 | struct nfs_delegation *delegation; | 630 | struct nfs_delegation *delegation; |
611 | 631 | ||
632 | nfs_revoke_delegation(inode); | ||
612 | delegation = nfs_inode_detach_delegation(inode); | 633 | delegation = nfs_inode_detach_delegation(inode); |
613 | if (delegation) { | 634 | if (delegation) { |
614 | nfs_inode_find_state_and_recover(inode, &delegation->stateid); | 635 | nfs_inode_find_state_and_recover(inode, &delegation->stateid); |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 5c1cce39297f..e3c20a3ccc93 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -31,6 +31,7 @@ enum { | |||
31 | NFS_DELEGATION_RETURN_IF_CLOSED, | 31 | NFS_DELEGATION_RETURN_IF_CLOSED, |
32 | NFS_DELEGATION_REFERENCED, | 32 | NFS_DELEGATION_REFERENCED, |
33 | NFS_DELEGATION_RETURNING, | 33 | NFS_DELEGATION_RETURNING, |
34 | NFS_DELEGATION_REVOKED, | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 37 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 06e8cfcbb670..6e62155abf26 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1527,6 +1527,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1527 | case -ENOENT: | 1527 | case -ENOENT: |
1528 | d_drop(dentry); | 1528 | d_drop(dentry); |
1529 | d_add(dentry, NULL); | 1529 | d_add(dentry, NULL); |
1530 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1530 | break; | 1531 | break; |
1531 | case -EISDIR: | 1532 | case -EISDIR: |
1532 | case -ENOTDIR: | 1533 | case -ENOTDIR: |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 20cffc830468..10bf07280f4a 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -266,6 +266,7 @@ static void nfs_direct_req_free(struct kref *kref) | |||
266 | { | 266 | { |
267 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); | 267 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); |
268 | 268 | ||
269 | nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo); | ||
269 | if (dreq->l_ctx != NULL) | 270 | if (dreq->l_ctx != NULL) |
270 | nfs_put_lock_context(dreq->l_ctx); | 271 | nfs_put_lock_context(dreq->l_ctx); |
271 | if (dreq->ctx != NULL) | 272 | if (dreq->ctx != NULL) |
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 46fab1cb455a..7afb52f6a25a 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -145,9 +145,6 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
145 | case -NFS4ERR_DELEG_REVOKED: | 145 | case -NFS4ERR_DELEG_REVOKED: |
146 | case -NFS4ERR_ADMIN_REVOKED: | 146 | case -NFS4ERR_ADMIN_REVOKED: |
147 | case -NFS4ERR_BAD_STATEID: | 147 | case -NFS4ERR_BAD_STATEID: |
148 | if (state == NULL) | ||
149 | break; | ||
150 | nfs_remove_bad_delegation(state->inode); | ||
151 | case -NFS4ERR_OPENMODE: | 148 | case -NFS4ERR_OPENMODE: |
152 | if (state == NULL) | 149 | if (state == NULL) |
153 | break; | 150 | break; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6388a59f2add..00689a8a85e4 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -626,7 +626,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
626 | { | 626 | { |
627 | struct inode *inode = dentry->d_inode; | 627 | struct inode *inode = dentry->d_inode; |
628 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; | 628 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
629 | int err; | 629 | int err = 0; |
630 | 630 | ||
631 | trace_nfs_getattr_enter(inode); | 631 | trace_nfs_getattr_enter(inode); |
632 | /* Flush out writes to the server in order to update c/mtime. */ | 632 | /* Flush out writes to the server in order to update c/mtime. */ |
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index ef221fb8a183..f0e06e4acbef 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h | |||
@@ -19,6 +19,7 @@ struct nfs_net { | |||
19 | struct rpc_pipe *bl_device_pipe; | 19 | struct rpc_pipe *bl_device_pipe; |
20 | struct bl_dev_msg bl_mount_reply; | 20 | struct bl_dev_msg bl_mount_reply; |
21 | wait_queue_head_t bl_wq; | 21 | wait_queue_head_t bl_wq; |
22 | struct mutex bl_mutex; | ||
22 | struct list_head nfs_client_list; | 23 | struct list_head nfs_client_list; |
23 | struct list_head nfs_volume_list; | 24 | struct list_head nfs_volume_list; |
24 | #if IS_ENABLED(CONFIG_NFS_V4) | 25 | #if IS_ENABLED(CONFIG_NFS_V4) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 405bd95c1f58..69dc20a743f9 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -370,11 +370,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
370 | case -NFS4ERR_DELEG_REVOKED: | 370 | case -NFS4ERR_DELEG_REVOKED: |
371 | case -NFS4ERR_ADMIN_REVOKED: | 371 | case -NFS4ERR_ADMIN_REVOKED: |
372 | case -NFS4ERR_BAD_STATEID: | 372 | case -NFS4ERR_BAD_STATEID: |
373 | if (inode != NULL && nfs4_have_delegation(inode, FMODE_READ)) { | ||
374 | nfs_remove_bad_delegation(inode); | ||
375 | exception->retry = 1; | ||
376 | break; | ||
377 | } | ||
378 | if (state == NULL) | 373 | if (state == NULL) |
379 | break; | 374 | break; |
380 | ret = nfs4_schedule_stateid_recovery(server, state); | 375 | ret = nfs4_schedule_stateid_recovery(server, state); |
@@ -1654,7 +1649,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct | |||
1654 | nfs_inode_find_state_and_recover(state->inode, | 1649 | nfs_inode_find_state_and_recover(state->inode, |
1655 | stateid); | 1650 | stateid); |
1656 | nfs4_schedule_stateid_recovery(server, state); | 1651 | nfs4_schedule_stateid_recovery(server, state); |
1657 | return 0; | 1652 | return -EAGAIN; |
1658 | case -NFS4ERR_DELAY: | 1653 | case -NFS4ERR_DELAY: |
1659 | case -NFS4ERR_GRACE: | 1654 | case -NFS4ERR_GRACE: |
1660 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 1655 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
@@ -2109,46 +2104,60 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta | |||
2109 | return ret; | 2104 | return ret; |
2110 | } | 2105 | } |
2111 | 2106 | ||
2107 | static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) | ||
2108 | { | ||
2109 | nfs_remove_bad_delegation(state->inode); | ||
2110 | write_seqlock(&state->seqlock); | ||
2111 | nfs4_stateid_copy(&state->stateid, &state->open_stateid); | ||
2112 | write_sequnlock(&state->seqlock); | ||
2113 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | ||
2114 | } | ||
2115 | |||
2116 | static void nfs40_clear_delegation_stateid(struct nfs4_state *state) | ||
2117 | { | ||
2118 | if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) | ||
2119 | nfs_finish_clear_delegation_stateid(state); | ||
2120 | } | ||
2121 | |||
2122 | static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) | ||
2123 | { | ||
2124 | /* NFSv4.0 doesn't allow for delegation recovery on open expire */ | ||
2125 | nfs40_clear_delegation_stateid(state); | ||
2126 | return nfs4_open_expired(sp, state); | ||
2127 | } | ||
2128 | |||
2112 | #if defined(CONFIG_NFS_V4_1) | 2129 | #if defined(CONFIG_NFS_V4_1) |
2113 | static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | 2130 | static void nfs41_check_delegation_stateid(struct nfs4_state *state) |
2114 | { | 2131 | { |
2115 | struct nfs_server *server = NFS_SERVER(state->inode); | 2132 | struct nfs_server *server = NFS_SERVER(state->inode); |
2116 | nfs4_stateid *stateid = &state->stateid; | 2133 | nfs4_stateid stateid; |
2117 | struct nfs_delegation *delegation; | 2134 | struct nfs_delegation *delegation; |
2118 | struct rpc_cred *cred = NULL; | 2135 | struct rpc_cred *cred; |
2119 | int status = -NFS4ERR_BAD_STATEID; | 2136 | int status; |
2120 | |||
2121 | /* If a state reset has been done, test_stateid is unneeded */ | ||
2122 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | ||
2123 | return; | ||
2124 | 2137 | ||
2125 | /* Get the delegation credential for use by test/free_stateid */ | 2138 | /* Get the delegation credential for use by test/free_stateid */ |
2126 | rcu_read_lock(); | 2139 | rcu_read_lock(); |
2127 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | 2140 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); |
2128 | if (delegation != NULL && | 2141 | if (delegation == NULL) { |
2129 | nfs4_stateid_match(&delegation->stateid, stateid)) { | ||
2130 | cred = get_rpccred(delegation->cred); | ||
2131 | rcu_read_unlock(); | ||
2132 | status = nfs41_test_stateid(server, stateid, cred); | ||
2133 | trace_nfs4_test_delegation_stateid(state, NULL, status); | ||
2134 | } else | ||
2135 | rcu_read_unlock(); | 2142 | rcu_read_unlock(); |
2143 | return; | ||
2144 | } | ||
2145 | |||
2146 | nfs4_stateid_copy(&stateid, &delegation->stateid); | ||
2147 | cred = get_rpccred(delegation->cred); | ||
2148 | rcu_read_unlock(); | ||
2149 | status = nfs41_test_stateid(server, &stateid, cred); | ||
2150 | trace_nfs4_test_delegation_stateid(state, NULL, status); | ||
2136 | 2151 | ||
2137 | if (status != NFS_OK) { | 2152 | if (status != NFS_OK) { |
2138 | /* Free the stateid unless the server explicitly | 2153 | /* Free the stateid unless the server explicitly |
2139 | * informs us the stateid is unrecognized. */ | 2154 | * informs us the stateid is unrecognized. */ |
2140 | if (status != -NFS4ERR_BAD_STATEID) | 2155 | if (status != -NFS4ERR_BAD_STATEID) |
2141 | nfs41_free_stateid(server, stateid, cred); | 2156 | nfs41_free_stateid(server, &stateid, cred); |
2142 | nfs_remove_bad_delegation(state->inode); | 2157 | nfs_finish_clear_delegation_stateid(state); |
2143 | |||
2144 | write_seqlock(&state->seqlock); | ||
2145 | nfs4_stateid_copy(&state->stateid, &state->open_stateid); | ||
2146 | write_sequnlock(&state->seqlock); | ||
2147 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | ||
2148 | } | 2158 | } |
2149 | 2159 | ||
2150 | if (cred != NULL) | 2160 | put_rpccred(cred); |
2151 | put_rpccred(cred); | ||
2152 | } | 2161 | } |
2153 | 2162 | ||
2154 | /** | 2163 | /** |
@@ -2192,7 +2201,7 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
2192 | { | 2201 | { |
2193 | int status; | 2202 | int status; |
2194 | 2203 | ||
2195 | nfs41_clear_delegation_stateid(state); | 2204 | nfs41_check_delegation_stateid(state); |
2196 | status = nfs41_check_open_stateid(state); | 2205 | status = nfs41_check_open_stateid(state); |
2197 | if (status != NFS_OK) | 2206 | if (status != NFS_OK) |
2198 | status = nfs4_open_expired(sp, state); | 2207 | status = nfs4_open_expired(sp, state); |
@@ -2231,19 +2240,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2231 | seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); | 2240 | seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); |
2232 | 2241 | ||
2233 | ret = _nfs4_proc_open(opendata); | 2242 | ret = _nfs4_proc_open(opendata); |
2234 | if (ret != 0) { | 2243 | if (ret != 0) |
2235 | if (ret == -ENOENT) { | ||
2236 | dentry = opendata->dentry; | ||
2237 | if (dentry->d_inode) | ||
2238 | d_delete(dentry); | ||
2239 | else if (d_unhashed(dentry)) | ||
2240 | d_add(dentry, NULL); | ||
2241 | |||
2242 | nfs_set_verifier(dentry, | ||
2243 | nfs_save_change_attribute(opendata->dir->d_inode)); | ||
2244 | } | ||
2245 | goto out; | 2244 | goto out; |
2246 | } | ||
2247 | 2245 | ||
2248 | state = nfs4_opendata_to_nfs4_state(opendata); | 2246 | state = nfs4_opendata_to_nfs4_state(opendata); |
2249 | ret = PTR_ERR(state); | 2247 | ret = PTR_ERR(state); |
@@ -4841,9 +4839,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
4841 | case -NFS4ERR_DELEG_REVOKED: | 4839 | case -NFS4ERR_DELEG_REVOKED: |
4842 | case -NFS4ERR_ADMIN_REVOKED: | 4840 | case -NFS4ERR_ADMIN_REVOKED: |
4843 | case -NFS4ERR_BAD_STATEID: | 4841 | case -NFS4ERR_BAD_STATEID: |
4844 | if (state == NULL) | ||
4845 | break; | ||
4846 | nfs_remove_bad_delegation(state->inode); | ||
4847 | case -NFS4ERR_OPENMODE: | 4842 | case -NFS4ERR_OPENMODE: |
4848 | if (state == NULL) | 4843 | if (state == NULL) |
4849 | break; | 4844 | break; |
@@ -8341,7 +8336,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | |||
8341 | static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { | 8336 | static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { |
8342 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, | 8337 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, |
8343 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, | 8338 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, |
8344 | .recover_open = nfs4_open_expired, | 8339 | .recover_open = nfs40_open_expired, |
8345 | .recover_lock = nfs4_lock_expired, | 8340 | .recover_lock = nfs4_lock_expired, |
8346 | .establish_clid = nfs4_init_clientid, | 8341 | .establish_clid = nfs4_init_clientid, |
8347 | }; | 8342 | }; |
@@ -8408,8 +8403,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
8408 | | NFS_CAP_CHANGE_ATTR | 8403 | | NFS_CAP_CHANGE_ATTR |
8409 | | NFS_CAP_POSIX_LOCK | 8404 | | NFS_CAP_POSIX_LOCK |
8410 | | NFS_CAP_STATEID_NFSV41 | 8405 | | NFS_CAP_STATEID_NFSV41 |
8411 | | NFS_CAP_ATOMIC_OPEN_V1 | 8406 | | NFS_CAP_ATOMIC_OPEN_V1, |
8412 | | NFS_CAP_SEEK, | ||
8413 | .init_client = nfs41_init_client, | 8407 | .init_client = nfs41_init_client, |
8414 | .shutdown_client = nfs41_shutdown_client, | 8408 | .shutdown_client = nfs41_shutdown_client, |
8415 | .match_stateid = nfs41_match_stateid, | 8409 | .match_stateid = nfs41_match_stateid, |
@@ -8431,7 +8425,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
8431 | | NFS_CAP_CHANGE_ATTR | 8425 | | NFS_CAP_CHANGE_ATTR |
8432 | | NFS_CAP_POSIX_LOCK | 8426 | | NFS_CAP_POSIX_LOCK |
8433 | | NFS_CAP_STATEID_NFSV41 | 8427 | | NFS_CAP_STATEID_NFSV41 |
8434 | | NFS_CAP_ATOMIC_OPEN_V1, | 8428 | | NFS_CAP_ATOMIC_OPEN_V1 |
8429 | | NFS_CAP_SEEK, | ||
8435 | .init_client = nfs41_init_client, | 8430 | .init_client = nfs41_init_client, |
8436 | .shutdown_client = nfs41_shutdown_client, | 8431 | .shutdown_client = nfs41_shutdown_client, |
8437 | .match_stateid = nfs41_match_stateid, | 8432 | .match_stateid = nfs41_match_stateid, |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 12493846a2d3..f83b02dc9166 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -715,8 +715,6 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
715 | 715 | ||
716 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) | 716 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) |
717 | nfs_release_request(req); | 717 | nfs_release_request(req); |
718 | else | ||
719 | WARN_ON_ONCE(1); | ||
720 | } | 718 | } |
721 | 719 | ||
722 | static void | 720 | static void |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index ed2b1151b171..7cbdf1b2e4ab 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -774,8 +774,12 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) | |||
774 | { | 774 | { |
775 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { | 775 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { |
776 | rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); | 776 | rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); |
777 | dprintk("%s slot is busy\n", __func__); | 777 | /* Race breaker */ |
778 | return false; | 778 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { |
779 | dprintk("%s slot is busy\n", __func__); | ||
780 | return false; | ||
781 | } | ||
782 | rpc_wake_up_queued_task(&clp->cl_cb_waitq, task); | ||
779 | } | 783 | } |
780 | return true; | 784 | return true; |
781 | } | 785 | } |
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 747f3b95bd11..33a46a8dfaf7 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
@@ -335,12 +335,15 @@ void nfsd_lockd_shutdown(void); | |||
335 | (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) | 335 | (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) |
336 | 336 | ||
337 | #ifdef CONFIG_NFSD_V4_SECURITY_LABEL | 337 | #ifdef CONFIG_NFSD_V4_SECURITY_LABEL |
338 | #define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ | 338 | #define NFSD4_2_SECURITY_ATTRS FATTR4_WORD2_SECURITY_LABEL |
339 | (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL) | ||
340 | #else | 339 | #else |
341 | #define NFSD4_2_SUPPORTED_ATTRS_WORD2 0 | 340 | #define NFSD4_2_SECURITY_ATTRS 0 |
342 | #endif | 341 | #endif |
343 | 342 | ||
343 | #define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ | ||
344 | (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ | ||
345 | NFSD4_2_SECURITY_ATTRS) | ||
346 | |||
344 | static inline u32 nfsd_suppattrs0(u32 minorversion) | 347 | static inline u32 nfsd_suppattrs0(u32 minorversion) |
345 | { | 348 | { |
346 | return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 | 349 | return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 9d3e9c50066a..89326acd4561 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -229,8 +229,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
229 | &fsnotify_mark_srcu); | 229 | &fsnotify_mark_srcu); |
230 | } | 230 | } |
231 | 231 | ||
232 | /* | ||
233 | * We need to merge inode & vfsmount mark lists so that inode mark | ||
234 | * ignore masks are properly reflected for mount mark notifications. | ||
235 | * That's why this traversal is so complicated... | ||
236 | */ | ||
232 | while (inode_node || vfsmount_node) { | 237 | while (inode_node || vfsmount_node) { |
233 | inode_group = vfsmount_group = NULL; | 238 | inode_group = NULL; |
239 | inode_mark = NULL; | ||
240 | vfsmount_group = NULL; | ||
241 | vfsmount_mark = NULL; | ||
234 | 242 | ||
235 | if (inode_node) { | 243 | if (inode_node) { |
236 | inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu), | 244 | inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu), |
@@ -244,21 +252,19 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
244 | vfsmount_group = vfsmount_mark->group; | 252 | vfsmount_group = vfsmount_mark->group; |
245 | } | 253 | } |
246 | 254 | ||
247 | if (inode_group > vfsmount_group) { | 255 | if (inode_group && vfsmount_group) { |
248 | /* handle inode */ | 256 | int cmp = fsnotify_compare_groups(inode_group, |
249 | ret = send_to_group(to_tell, inode_mark, NULL, mask, | 257 | vfsmount_group); |
250 | data, data_is, cookie, file_name); | 258 | if (cmp > 0) { |
251 | /* we didn't use the vfsmount_mark */ | 259 | inode_group = NULL; |
252 | vfsmount_group = NULL; | 260 | inode_mark = NULL; |
253 | } else if (vfsmount_group > inode_group) { | 261 | } else if (cmp < 0) { |
254 | ret = send_to_group(to_tell, NULL, vfsmount_mark, mask, | 262 | vfsmount_group = NULL; |
255 | data, data_is, cookie, file_name); | 263 | vfsmount_mark = NULL; |
256 | inode_group = NULL; | 264 | } |
257 | } else { | ||
258 | ret = send_to_group(to_tell, inode_mark, vfsmount_mark, | ||
259 | mask, data, data_is, cookie, | ||
260 | file_name); | ||
261 | } | 265 | } |
266 | ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask, | ||
267 | data, data_is, cookie, file_name); | ||
262 | 268 | ||
263 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) | 269 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) |
264 | goto out; | 270 | goto out; |
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index 9c0898c4cfe1..3b68b0ae0a97 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h | |||
@@ -12,6 +12,10 @@ extern void fsnotify_flush_notify(struct fsnotify_group *group); | |||
12 | /* protects reads of inode and vfsmount marks list */ | 12 | /* protects reads of inode and vfsmount marks list */ |
13 | extern struct srcu_struct fsnotify_mark_srcu; | 13 | extern struct srcu_struct fsnotify_mark_srcu; |
14 | 14 | ||
15 | /* compare two groups for sorting of marks lists */ | ||
16 | extern int fsnotify_compare_groups(struct fsnotify_group *a, | ||
17 | struct fsnotify_group *b); | ||
18 | |||
15 | extern void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *fsn_mark, | 19 | extern void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *fsn_mark, |
16 | __u32 mask); | 20 | __u32 mask); |
17 | /* add a mark to an inode */ | 21 | /* add a mark to an inode */ |
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index e8497144b323..dfbf5447eea4 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -194,6 +194,7 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | |||
194 | { | 194 | { |
195 | struct fsnotify_mark *lmark, *last = NULL; | 195 | struct fsnotify_mark *lmark, *last = NULL; |
196 | int ret = 0; | 196 | int ret = 0; |
197 | int cmp; | ||
197 | 198 | ||
198 | mark->flags |= FSNOTIFY_MARK_FLAG_INODE; | 199 | mark->flags |= FSNOTIFY_MARK_FLAG_INODE; |
199 | 200 | ||
@@ -219,11 +220,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | |||
219 | goto out; | 220 | goto out; |
220 | } | 221 | } |
221 | 222 | ||
222 | if (mark->group->priority < lmark->group->priority) | 223 | cmp = fsnotify_compare_groups(lmark->group, mark->group); |
223 | continue; | 224 | if (cmp < 0) |
224 | |||
225 | if ((mark->group->priority == lmark->group->priority) && | ||
226 | (mark->group < lmark->group)) | ||
227 | continue; | 225 | continue; |
228 | 226 | ||
229 | hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list); | 227 | hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list); |
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index d90deaa08e78..34c38fabf514 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -210,6 +210,42 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas | |||
210 | } | 210 | } |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * Sorting function for lists of fsnotify marks. | ||
214 | * | ||
215 | * Fanotify supports different notification classes (reflected as priority of | ||
216 | * notification group). Events shall be passed to notification groups in | ||
217 | * decreasing priority order. To achieve this marks in notification lists for | ||
218 | * inodes and vfsmounts are sorted so that priorities of corresponding groups | ||
219 | * are descending. | ||
220 | * | ||
221 | * Furthermore correct handling of the ignore mask requires processing inode | ||
222 | * and vfsmount marks of each group together. Using the group address as | ||
223 | * further sort criterion provides a unique sorting order and thus we can | ||
224 | * merge inode and vfsmount lists of marks in linear time and find groups | ||
225 | * present in both lists. | ||
226 | * | ||
227 | * A return value of 1 signifies that b has priority over a. | ||
228 | * A return value of 0 signifies that the two marks have to be handled together. | ||
229 | * A return value of -1 signifies that a has priority over b. | ||
230 | */ | ||
231 | int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b) | ||
232 | { | ||
233 | if (a == b) | ||
234 | return 0; | ||
235 | if (!a) | ||
236 | return 1; | ||
237 | if (!b) | ||
238 | return -1; | ||
239 | if (a->priority < b->priority) | ||
240 | return 1; | ||
241 | if (a->priority > b->priority) | ||
242 | return -1; | ||
243 | if (a < b) | ||
244 | return 1; | ||
245 | return -1; | ||
246 | } | ||
247 | |||
248 | /* | ||
213 | * Attach an initialized mark to a given group and fs object. | 249 | * Attach an initialized mark to a given group and fs object. |
214 | * These marks may be used for the fsnotify backend to determine which | 250 | * These marks may be used for the fsnotify backend to determine which |
215 | * event types should be delivered to which group. | 251 | * event types should be delivered to which group. |
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c index ac851e8376b1..faefa72a11eb 100644 --- a/fs/notify/vfsmount_mark.c +++ b/fs/notify/vfsmount_mark.c | |||
@@ -153,6 +153,7 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, | |||
153 | struct mount *m = real_mount(mnt); | 153 | struct mount *m = real_mount(mnt); |
154 | struct fsnotify_mark *lmark, *last = NULL; | 154 | struct fsnotify_mark *lmark, *last = NULL; |
155 | int ret = 0; | 155 | int ret = 0; |
156 | int cmp; | ||
156 | 157 | ||
157 | mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT; | 158 | mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT; |
158 | 159 | ||
@@ -178,11 +179,8 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, | |||
178 | goto out; | 179 | goto out; |
179 | } | 180 | } |
180 | 181 | ||
181 | if (mark->group->priority < lmark->group->priority) | 182 | cmp = fsnotify_compare_groups(lmark->group, mark->group); |
182 | continue; | 183 | if (cmp < 0) |
183 | |||
184 | if ((mark->group->priority == lmark->group->priority) && | ||
185 | (mark->group < lmark->group)) | ||
186 | continue; | 184 | continue; |
187 | 185 | ||
188 | hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list); | 186 | hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list); |
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 | { |