Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+133 -85
+1 -1
Documentation/filesystems/overlayfs.txt
··· 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
+4 -3
MAINTAINERS
··· 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
+1 -1
fs/Makefile
··· 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/
+1
fs/dcache.c
··· 778 778 struct dentry *parent = lock_parent(dentry); 779 779 if (likely(!dentry->d_lockref.count)) { 780 780 __dentry_kill(dentry); 781 + dput(parent); 781 782 goto restart; 782 783 } 783 784 if (parent)
+21 -21
fs/isofs/inode.c
··· 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; ··· 242 263 } 243 264 244 265 #ifdef CONFIG_JOLIET 266 + /* 267 + * Compute the hash for the isofs name corresponding to the dentry. 268 + */ 269 + static int 270 + isofs_hash_common(struct qstr *qstr, int ms) 271 + { 272 + const char *name; 273 + int len; 274 + 275 + len = qstr->len; 276 + name = qstr->name; 277 + if (ms) { 278 + while (len && name[len-1] == '.') 279 + len--; 280 + } 281 + 282 + qstr->hash = full_name_hash(name, len); 283 + 284 + return 0; 285 + } 286 + 245 287 static int 246 288 isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr) 247 289 {
+1 -1
fs/overlayfs/Kconfig
··· 1 - config OVERLAYFS_FS 1 + config OVERLAY_FS 2 2 tristate "Overlay filesystem support" 3 3 help 4 4 An overlay filesystem combines two filesystems - an 'upper' filesystem
+2 -2
fs/overlayfs/Makefile
··· 2 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
+19 -12
fs/overlayfs/dir.c
··· 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; ··· 293 294 err = ovl_check_empty_dir(dentry, &list); 294 295 if (err) 295 296 ret = ERR_PTR(err); 296 - else if (type == OVL_PATH_MERGE) 297 - ret = ovl_clear_empty(dentry, &list); 297 + else { 298 + /* 299 + * If no upperdentry then skip clearing whiteouts. 300 + * 301 + * Can race with copy-up, since we don't hold the upperdir 302 + * mutex. Doesn't matter, since copy-up can't create a 303 + * non-empty directory from an empty one. 304 + */ 305 + if (ovl_dentry_upper(dentry)) 306 + ret = ovl_clear_empty(dentry, &list); 307 + } 298 308 299 309 ovl_cache_free(&list); 300 310 ··· 495 487 return err; 496 488 } 497 489 498 - static int ovl_remove_and_whiteout(struct dentry *dentry, 499 - enum ovl_path_type type, bool is_dir) 490 + static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir) 500 491 { 501 492 struct dentry *workdir = ovl_workdir(dentry); 502 493 struct inode *wdir = workdir->d_inode; ··· 507 500 int err; 508 501 509 502 if (is_dir) { 510 - opaquedir = ovl_check_empty_and_clear(dentry, type); 503 + opaquedir = ovl_check_empty_and_clear(dentry); 511 504 err = PTR_ERR(opaquedir); 512 505 if (IS_ERR(opaquedir)) 513 506 goto out; ··· 522 515 if (IS_ERR(whiteout)) 523 516 goto out_unlock; 524 517 525 - if (type == OVL_PATH_LOWER) { 518 + upper = ovl_dentry_upper(dentry); 519 + if (!upper) { 526 520 upper = lookup_one_len(dentry->d_name.name, upperdir, 527 - dentry->d_name.len); 521 + dentry->d_name.len); 528 522 err = PTR_ERR(upper); 529 523 if (IS_ERR(upper)) 530 524 goto kill_whiteout; ··· 537 529 } else { 538 530 int flags = 0; 539 531 540 - upper = ovl_dentry_upper(dentry); 541 532 if (opaquedir) 542 533 upper = opaquedir; 543 534 err = -ESTALE; ··· 655 648 cap_raise(override_cred->cap_effective, CAP_CHOWN); 656 649 old_cred = override_creds(override_cred); 657 650 658 - err = ovl_remove_and_whiteout(dentry, type, is_dir); 651 + err = ovl_remove_and_whiteout(dentry, is_dir); 659 652 660 653 revert_creds(old_cred); 661 654 put_cred(override_cred); ··· 788 781 } 789 782 790 783 if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) { 791 - opaquedir = ovl_check_empty_and_clear(new, new_type); 784 + opaquedir = ovl_check_empty_and_clear(new); 792 785 err = PTR_ERR(opaquedir); 793 786 if (IS_ERR(opaquedir)) { 794 787 opaquedir = NULL;
+18 -9
fs/overlayfs/inode.c
··· 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 */ ··· 289 279 { 290 280 int err; 291 281 struct path realpath; 292 - enum ovl_path_type type; 282 + enum ovl_path_type type = ovl_path_real(dentry, &realpath); 293 283 294 284 err = ovl_want_write(dentry); 295 285 if (err) 296 286 goto out; 297 287 298 - if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && 299 - ovl_is_private_xattr(name)) 288 + err = -ENODATA; 289 + if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) 300 290 goto out_drop_write; 301 291 302 - type = ovl_path_real(dentry, &realpath); 303 292 if (type == OVL_PATH_LOWER) { 304 293 err = vfs_getxattr(realpath.dentry, name, NULL, 0); 305 294 if (err < 0)
+16 -23
fs/overlayfs/readdir.c
··· 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, ··· 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: ··· 332 329 static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) 333 330 { 334 331 int res; 335 - struct path lowerpath; 336 - struct path upperpath; 337 332 struct ovl_dir_cache *cache; 338 333 339 334 cache = ovl_dir_cache(dentry); ··· 348 347 cache->refcount = 1; 349 348 INIT_LIST_HEAD(&cache->entries); 350 349 351 - ovl_path_lower(dentry, &lowerpath); 352 - ovl_path_upper(dentry, &upperpath); 353 - 354 - res = ovl_dir_read_merged(&upperpath, &lowerpath, &cache->entries); 350 + res = ovl_dir_read_merged(dentry, &cache->entries); 355 351 if (res) { 356 352 ovl_cache_free(&cache->entries); 357 353 kfree(cache); ··· 450 452 /* 451 453 * Need to check if we started out being a lower dir, but got copied up 452 454 */ 453 - if (!od->is_upper && ovl_path_type(dentry) == OVL_PATH_MERGE) { 455 + if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) { 454 456 struct inode *inode = file_inode(file); 455 457 456 - realfile =lockless_dereference(od->upperfile); 458 + realfile = lockless_dereference(od->upperfile); 457 459 if (!realfile) { 458 460 struct path upperpath; 459 461 ··· 536 538 int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) 537 539 { 538 540 int err; 539 - struct path lowerpath; 540 - struct path upperpath; 541 541 struct ovl_cache_entry *p; 542 542 543 - ovl_path_upper(dentry, &upperpath); 544 - ovl_path_lower(dentry, &lowerpath); 545 - 546 - err = ovl_dir_read_merged(&upperpath, &lowerpath, list); 543 + err = ovl_dir_read_merged(dentry, list); 547 544 if (err) 548 545 return err; 549 546
+49 -12
fs/overlayfs/super.c
··· 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 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) ··· 457 462 {OPT_ERR, NULL} 458 463 }; 459 464 465 + static char *ovl_next_opt(char **s) 466 + { 467 + char *sbegin = *s; 468 + char *p; 469 + 470 + if (sbegin == NULL) 471 + return NULL; 472 + 473 + for (p = sbegin; *p; p++) { 474 + if (*p == '\\') { 475 + p++; 476 + if (!*p) 477 + break; 478 + } else if (*p == ',') { 479 + *p = '\0'; 480 + *s = p + 1; 481 + return sbegin; 482 + } 483 + } 484 + *s = NULL; 485 + return sbegin; 486 + } 487 + 460 488 static int ovl_parse_opt(char *opt, struct ovl_config *config) 461 489 { 462 490 char *p; 463 491 464 - while ((p = strsep(&opt, ",")) != NULL) { 492 + while ((p = ovl_next_opt(&opt)) != NULL) { 465 493 int token; 466 494 substring_t args[MAX_OPT_ARGS]; 467 495 ··· 572 554 goto out_unlock; 573 555 } 574 556 557 + static void ovl_unescape(char *s) 558 + { 559 + char *d = s; 560 + 561 + for (;; s++, d++) { 562 + if (*s == '\\') 563 + s++; 564 + *d = *s; 565 + if (!*s) 566 + break; 567 + } 568 + } 569 + 575 570 static int ovl_mount_dir(const char *name, struct path *path) 576 571 { 577 572 int err; 573 + char *tmp = kstrdup(name, GFP_KERNEL); 578 574 579 - err = kern_path(name, LOOKUP_FOLLOW, path); 575 + if (!tmp) 576 + return -ENOMEM; 577 + 578 + ovl_unescape(tmp); 579 + err = kern_path(tmp, LOOKUP_FOLLOW, path); 580 580 if (err) { 581 - pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); 581 + pr_err("overlayfs: failed to resolve '%s': %i\n", tmp, err); 582 582 err = -EINVAL; 583 583 } 584 + kfree(tmp); 584 585 return err; 585 586 } 586 587 ··· 813 776 814 777 static struct file_system_type ovl_fs_type = { 815 778 .owner = THIS_MODULE, 816 - .name = "overlayfs", 779 + .name = "overlay", 817 780 .mount = ovl_mount, 818 781 .kill_sb = kill_anon_super, 819 782 }; 820 - MODULE_ALIAS_FS("overlayfs"); 783 + MODULE_ALIAS_FS("overlay"); 821 784 822 785 static int __init ovl_init(void) 823 786 {