Commit ecde00642c79c2dfc9006e7751ee60bd0e21e1e9
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "Assorted fixes, most in overlayfs land" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: ovl: ovl_dir_fsync() cleanup ovl: update MAINTAINERS ovl: pass dentry into ovl_dir_read_merged() ovl: use lockless_dereference() for upperdentry ovl: allow filenames with comma ovl: fix race in private xattr checks ovl: fix remove/copy-up race ovl: rename filesystem type to "overlay" isofs: avoid unused function warning vfs: fix reference leak in d_prune_aliases()
Showing 11 changed files Side-by-side Diff
Documentation/filesystems/overlayfs.txt
... | ... | @@ -64,7 +64,7 @@ |
64 | 64 | At mount time, the two directories given as mount options "lowerdir" and |
65 | 65 | "upperdir" are combined into a merged directory: |
66 | 66 | |
67 | - mount -t overlayfs overlayfs -olowerdir=/lower,upperdir=/upper,\ | |
67 | + mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\ | |
68 | 68 | workdir=/work /merged |
69 | 69 | |
70 | 70 | The "workdir" needs to be an empty directory on the same filesystem |
MAINTAINERS
... | ... | @@ -6888,11 +6888,12 @@ |
6888 | 6888 | F: include/scsi/osd_* |
6889 | 6889 | F: fs/exofs/ |
6890 | 6890 | |
6891 | -OVERLAYFS FILESYSTEM | |
6891 | +OVERLAY FILESYSTEM | |
6892 | 6892 | M: Miklos Szeredi <miklos@szeredi.hu> |
6893 | -L: linux-fsdevel@vger.kernel.org | |
6893 | +L: linux-unionfs@vger.kernel.org | |
6894 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git | |
6894 | 6895 | S: Supported |
6895 | -F: fs/overlayfs/* | |
6896 | +F: fs/overlayfs/ | |
6896 | 6897 | F: Documentation/filesystems/overlayfs.txt |
6897 | 6898 | |
6898 | 6899 | P54 WIRELESS DRIVER |
fs/Makefile
... | ... | @@ -104,7 +104,7 @@ |
104 | 104 | obj-$(CONFIG_AUTOFS4_FS) += autofs4/ |
105 | 105 | obj-$(CONFIG_ADFS_FS) += adfs/ |
106 | 106 | obj-$(CONFIG_FUSE_FS) += fuse/ |
107 | -obj-$(CONFIG_OVERLAYFS_FS) += overlayfs/ | |
107 | +obj-$(CONFIG_OVERLAY_FS) += overlayfs/ | |
108 | 108 | obj-$(CONFIG_UDF_FS) += udf/ |
109 | 109 | obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ |
110 | 110 | obj-$(CONFIG_OMFS_FS) += omfs/ |
fs/dcache.c
fs/isofs/inode.c
... | ... | @@ -174,27 +174,6 @@ |
174 | 174 | * Compute the hash for the isofs name corresponding to the dentry. |
175 | 175 | */ |
176 | 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 | 177 | isofs_hashi_common(struct qstr *qstr, int ms) |
199 | 178 | { |
200 | 179 | const char *name; |
... | ... | @@ -263,6 +242,27 @@ |
263 | 242 | } |
264 | 243 | |
265 | 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 | 266 | static int |
267 | 267 | isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr) |
268 | 268 | { |
fs/overlayfs/Kconfig
fs/overlayfs/Makefile
fs/overlayfs/dir.c
... | ... | @@ -284,8 +284,7 @@ |
284 | 284 | return ERR_PTR(err); |
285 | 285 | } |
286 | 286 | |
287 | -static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry, | |
288 | - enum ovl_path_type type) | |
287 | +static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry) | |
289 | 288 | { |
290 | 289 | int err; |
291 | 290 | struct dentry *ret = NULL; |
... | ... | @@ -294,8 +293,17 @@ |
294 | 293 | err = ovl_check_empty_dir(dentry, &list); |
295 | 294 | if (err) |
296 | 295 | ret = ERR_PTR(err); |
297 | - else if (type == OVL_PATH_MERGE) | |
298 | - ret = ovl_clear_empty(dentry, &list); | |
296 | + else { | |
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 | 308 | ovl_cache_free(&list); |
301 | 309 | |
... | ... | @@ -487,8 +495,7 @@ |
487 | 495 | return err; |
488 | 496 | } |
489 | 497 | |
490 | -static int ovl_remove_and_whiteout(struct dentry *dentry, | |
491 | - enum ovl_path_type type, bool is_dir) | |
498 | +static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir) | |
492 | 499 | { |
493 | 500 | struct dentry *workdir = ovl_workdir(dentry); |
494 | 501 | struct inode *wdir = workdir->d_inode; |
... | ... | @@ -500,7 +507,7 @@ |
500 | 507 | int err; |
501 | 508 | |
502 | 509 | if (is_dir) { |
503 | - opaquedir = ovl_check_empty_and_clear(dentry, type); | |
510 | + opaquedir = ovl_check_empty_and_clear(dentry); | |
504 | 511 | err = PTR_ERR(opaquedir); |
505 | 512 | if (IS_ERR(opaquedir)) |
506 | 513 | goto out; |
507 | 514 | |
... | ... | @@ -515,9 +522,10 @@ |
515 | 522 | if (IS_ERR(whiteout)) |
516 | 523 | goto out_unlock; |
517 | 524 | |
518 | - if (type == OVL_PATH_LOWER) { | |
525 | + upper = ovl_dentry_upper(dentry); | |
526 | + if (!upper) { | |
519 | 527 | upper = lookup_one_len(dentry->d_name.name, upperdir, |
520 | - dentry->d_name.len); | |
528 | + dentry->d_name.len); | |
521 | 529 | err = PTR_ERR(upper); |
522 | 530 | if (IS_ERR(upper)) |
523 | 531 | goto kill_whiteout; |
... | ... | @@ -529,7 +537,6 @@ |
529 | 537 | } else { |
530 | 538 | int flags = 0; |
531 | 539 | |
532 | - upper = ovl_dentry_upper(dentry); | |
533 | 540 | if (opaquedir) |
534 | 541 | upper = opaquedir; |
535 | 542 | err = -ESTALE; |
... | ... | @@ -648,7 +655,7 @@ |
648 | 655 | cap_raise(override_cred->cap_effective, CAP_CHOWN); |
649 | 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 | 660 | revert_creds(old_cred); |
654 | 661 | put_cred(override_cred); |
... | ... | @@ -781,7 +788,7 @@ |
781 | 788 | } |
782 | 789 | |
783 | 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 | 792 | err = PTR_ERR(opaquedir); |
786 | 793 | if (IS_ERR(opaquedir)) { |
787 | 794 | opaquedir = NULL; |
fs/overlayfs/inode.c
... | ... | @@ -235,26 +235,36 @@ |
235 | 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 | 244 | ssize_t ovl_getxattr(struct dentry *dentry, const char *name, |
239 | 245 | void *value, size_t size) |
240 | 246 | { |
241 | - if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && | |
242 | - ovl_is_private_xattr(name)) | |
247 | + struct path realpath; | |
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 | 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 | 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 | 260 | ssize_t res; |
251 | 261 | int off; |
252 | 262 | |
253 | - res = vfs_listxattr(ovl_dentry_real(dentry), list, size); | |
263 | + res = vfs_listxattr(realpath.dentry, list, size); | |
254 | 264 | if (res <= 0 || size == 0) |
255 | 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 | 268 | return res; |
259 | 269 | |
260 | 270 | /* filter out private xattrs */ |
261 | 271 | |
262 | 272 | |
... | ... | @@ -279,17 +289,16 @@ |
279 | 289 | { |
280 | 290 | int err; |
281 | 291 | struct path realpath; |
282 | - enum ovl_path_type type; | |
292 | + enum ovl_path_type type = ovl_path_real(dentry, &realpath); | |
283 | 293 | |
284 | 294 | err = ovl_want_write(dentry); |
285 | 295 | if (err) |
286 | 296 | goto out; |
287 | 297 | |
288 | - if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && | |
289 | - ovl_is_private_xattr(name)) | |
298 | + err = -ENODATA; | |
299 | + if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | |
290 | 300 | goto out_drop_write; |
291 | 301 | |
292 | - type = ovl_path_real(dentry, &realpath); | |
293 | 302 | if (type == OVL_PATH_LOWER) { |
294 | 303 | err = vfs_getxattr(realpath.dentry, name, NULL, 0); |
295 | 304 | if (err < 0) |
fs/overlayfs/readdir.c
... | ... | @@ -274,11 +274,11 @@ |
274 | 274 | return 0; |
275 | 275 | } |
276 | 276 | |
277 | -static inline int ovl_dir_read_merged(struct path *upperpath, | |
278 | - struct path *lowerpath, | |
279 | - struct list_head *list) | |
277 | +static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) | |
280 | 278 | { |
281 | 279 | int err; |
280 | + struct path lowerpath; | |
281 | + struct path upperpath; | |
282 | 282 | struct ovl_readdir_data rdd = { |
283 | 283 | .ctx.actor = ovl_fill_merge, |
284 | 284 | .list = list, |
285 | 285 | |
286 | 286 | |
287 | 287 | |
... | ... | @@ -286,25 +286,28 @@ |
286 | 286 | .is_merge = false, |
287 | 287 | }; |
288 | 288 | |
289 | - if (upperpath->dentry) { | |
290 | - err = ovl_dir_read(upperpath, &rdd); | |
289 | + ovl_path_lower(dentry, &lowerpath); | |
290 | + ovl_path_upper(dentry, &upperpath); | |
291 | + | |
292 | + if (upperpath.dentry) { | |
293 | + err = ovl_dir_read(&upperpath, &rdd); | |
291 | 294 | if (err) |
292 | 295 | goto out; |
293 | 296 | |
294 | - if (lowerpath->dentry) { | |
295 | - err = ovl_dir_mark_whiteouts(upperpath->dentry, &rdd); | |
297 | + if (lowerpath.dentry) { | |
298 | + err = ovl_dir_mark_whiteouts(upperpath.dentry, &rdd); | |
296 | 299 | if (err) |
297 | 300 | goto out; |
298 | 301 | } |
299 | 302 | } |
300 | - if (lowerpath->dentry) { | |
303 | + if (lowerpath.dentry) { | |
301 | 304 | /* |
302 | 305 | * Insert lowerpath entries before upperpath ones, this allows |
303 | 306 | * offsets to be reasonably constant |
304 | 307 | */ |
305 | 308 | list_add(&rdd.middle, rdd.list); |
306 | 309 | rdd.is_merge = true; |
307 | - err = ovl_dir_read(lowerpath, &rdd); | |
310 | + err = ovl_dir_read(&lowerpath, &rdd); | |
308 | 311 | list_del(&rdd.middle); |
309 | 312 | } |
310 | 313 | out: |
... | ... | @@ -329,8 +332,6 @@ |
329 | 332 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) |
330 | 333 | { |
331 | 334 | int res; |
332 | - struct path lowerpath; | |
333 | - struct path upperpath; | |
334 | 335 | struct ovl_dir_cache *cache; |
335 | 336 | |
336 | 337 | cache = ovl_dir_cache(dentry); |
... | ... | @@ -347,10 +348,7 @@ |
347 | 348 | cache->refcount = 1; |
348 | 349 | INIT_LIST_HEAD(&cache->entries); |
349 | 350 | |
350 | - ovl_path_lower(dentry, &lowerpath); | |
351 | - ovl_path_upper(dentry, &upperpath); | |
352 | - | |
353 | - res = ovl_dir_read_merged(&upperpath, &lowerpath, &cache->entries); | |
351 | + res = ovl_dir_read_merged(dentry, &cache->entries); | |
354 | 352 | if (res) { |
355 | 353 | ovl_cache_free(&cache->entries); |
356 | 354 | kfree(cache); |
357 | 355 | |
... | ... | @@ -452,10 +450,10 @@ |
452 | 450 | /* |
453 | 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 | 454 | struct inode *inode = file_inode(file); |
457 | 455 | |
458 | - realfile =lockless_dereference(od->upperfile); | |
456 | + realfile = lockless_dereference(od->upperfile); | |
459 | 457 | if (!realfile) { |
460 | 458 | struct path upperpath; |
461 | 459 | |
462 | 460 | |
... | ... | @@ -538,14 +536,9 @@ |
538 | 536 | int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) |
539 | 537 | { |
540 | 538 | int err; |
541 | - struct path lowerpath; | |
542 | - struct path upperpath; | |
543 | 539 | struct ovl_cache_entry *p; |
544 | 540 | |
545 | - ovl_path_upper(dentry, &upperpath); | |
546 | - ovl_path_lower(dentry, &lowerpath); | |
547 | - | |
548 | - err = ovl_dir_read_merged(&upperpath, &lowerpath, list); | |
541 | + err = ovl_dir_read_merged(dentry, list); | |
549 | 542 | if (err) |
550 | 543 | return err; |
551 | 544 |
fs/overlayfs/super.c
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | MODULE_DESCRIPTION("Overlay filesystem"); |
25 | 25 | MODULE_LICENSE("GPL"); |
26 | 26 | |
27 | -#define OVERLAYFS_SUPER_MAGIC 0x794c764f | |
27 | +#define OVERLAYFS_SUPER_MAGIC 0x794c7630 | |
28 | 28 | |
29 | 29 | struct ovl_config { |
30 | 30 | char *lowerdir; |
... | ... | @@ -84,12 +84,7 @@ |
84 | 84 | |
85 | 85 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) |
86 | 86 | { |
87 | - struct dentry *upperdentry = ACCESS_ONCE(oe->__upperdentry); | |
88 | - /* | |
89 | - * Make sure to order reads to upperdentry wrt ovl_dentry_update() | |
90 | - */ | |
91 | - smp_read_barrier_depends(); | |
92 | - return upperdentry; | |
87 | + return lockless_dereference(oe->__upperdentry); | |
93 | 88 | } |
94 | 89 | |
95 | 90 | void ovl_path_upper(struct dentry *dentry, struct path *path) |
96 | 91 | |
... | ... | @@ -462,11 +457,34 @@ |
462 | 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 | 483 | static int ovl_parse_opt(char *opt, struct ovl_config *config) |
466 | 484 | { |
467 | 485 | char *p; |
468 | 486 | |
469 | - while ((p = strsep(&opt, ",")) != NULL) { | |
487 | + while ((p = ovl_next_opt(&opt)) != NULL) { | |
470 | 488 | int token; |
471 | 489 | substring_t args[MAX_OPT_ARGS]; |
472 | 490 | |
473 | 491 | |
474 | 492 | |
475 | 493 | |
476 | 494 | |
... | ... | @@ -554,15 +572,34 @@ |
554 | 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 | 588 | static int ovl_mount_dir(const char *name, struct path *path) |
558 | 589 | { |
559 | 590 | int err; |
591 | + char *tmp = kstrdup(name, GFP_KERNEL); | |
560 | 592 | |
561 | - err = kern_path(name, LOOKUP_FOLLOW, path); | |
593 | + if (!tmp) | |
594 | + return -ENOMEM; | |
595 | + | |
596 | + ovl_unescape(tmp); | |
597 | + err = kern_path(tmp, LOOKUP_FOLLOW, path); | |
562 | 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 | 600 | err = -EINVAL; |
565 | 601 | } |
602 | + kfree(tmp); | |
566 | 603 | return err; |
567 | 604 | } |
568 | 605 | |
569 | 606 | |
... | ... | @@ -776,11 +813,11 @@ |
776 | 813 | |
777 | 814 | static struct file_system_type ovl_fs_type = { |
778 | 815 | .owner = THIS_MODULE, |
779 | - .name = "overlayfs", | |
816 | + .name = "overlay", | |
780 | 817 | .mount = ovl_mount, |
781 | 818 | .kill_sb = kill_anon_super, |
782 | 819 | }; |
783 | -MODULE_ALIAS_FS("overlayfs"); | |
820 | +MODULE_ALIAS_FS("overlay"); | |
784 | 821 | |
785 | 822 | static int __init ovl_init(void) |
786 | 823 | { |