diff options
author | Amir Goldstein <amir73il@gmail.com> | 2017-11-06 09:48:02 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2018-04-12 06:04:50 -0400 |
commit | adbf4f7ea834671c9d12002136c8162b34e011d5 (patch) | |
tree | da12574cba5a268ec1b92c2a0b3cb91afa32613e | |
parent | 12574a9f4c9cc9d8d6fd9078cbb8ec7d3e9ed46b (diff) |
ovl: consistent d_ino for non-samefs with xino
When overlay layers are not all on the same fs, but all inode numbers
of underlying fs do not use the high 'xino' bits, overlay st_ino values
are constant and persistent.
In that case, relax non-samefs constraint for consistent d_ino and always
iterate non-merge dir using ovl_fill_real() actor so we can remap lower
inode numbers to unique lower fs range.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r-- | fs/overlayfs/readdir.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index c11f5c0906c3..ef1fe42ff7bb 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c | |||
@@ -120,6 +120,10 @@ static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd, | |||
120 | if (!rdd->dentry) | 120 | if (!rdd->dentry) |
121 | return false; | 121 | return false; |
122 | 122 | ||
123 | /* Always recalc d_ino when remapping lower inode numbers */ | ||
124 | if (ovl_xino_bits(rdd->dentry->d_sb)) | ||
125 | return true; | ||
126 | |||
123 | /* Always recalc d_ino for parent */ | 127 | /* Always recalc d_ino for parent */ |
124 | if (strcmp(p->name, "..") == 0) | 128 | if (strcmp(p->name, "..") == 0) |
125 | return true; | 129 | return true; |
@@ -435,6 +439,19 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | |||
435 | return cache; | 439 | return cache; |
436 | } | 440 | } |
437 | 441 | ||
442 | /* Map inode number to lower fs unique range */ | ||
443 | static u64 ovl_remap_lower_ino(u64 ino, int xinobits, int fsid, | ||
444 | const char *name, int namelen) | ||
445 | { | ||
446 | if (ino >> (64 - xinobits)) { | ||
447 | pr_warn_ratelimited("overlayfs: d_ino too big (%.*s, ino=%llu, xinobits=%d)\n", | ||
448 | namelen, name, ino, xinobits); | ||
449 | return ino; | ||
450 | } | ||
451 | |||
452 | return ino | ((u64)fsid) << (64 - xinobits); | ||
453 | } | ||
454 | |||
438 | /* | 455 | /* |
439 | * Set d_ino for upper entries. Non-upper entries should always report | 456 | * Set d_ino for upper entries. Non-upper entries should always report |
440 | * the uppermost real inode ino and should not call this function. | 457 | * the uppermost real inode ino and should not call this function. |
@@ -452,9 +469,10 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p) | |||
452 | struct dentry *this = NULL; | 469 | struct dentry *this = NULL; |
453 | enum ovl_path_type type; | 470 | enum ovl_path_type type; |
454 | u64 ino = p->real_ino; | 471 | u64 ino = p->real_ino; |
472 | int xinobits = ovl_xino_bits(dir->d_sb); | ||
455 | int err = 0; | 473 | int err = 0; |
456 | 474 | ||
457 | if (!ovl_same_sb(dir->d_sb)) | 475 | if (!ovl_same_sb(dir->d_sb) && !xinobits) |
458 | goto out; | 476 | goto out; |
459 | 477 | ||
460 | if (p->name[0] == '.') { | 478 | if (p->name[0] == '.') { |
@@ -491,6 +509,10 @@ get: | |||
491 | 509 | ||
492 | WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev); | 510 | WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev); |
493 | ino = stat.ino; | 511 | ino = stat.ino; |
512 | } else if (xinobits && !OVL_TYPE_UPPER(type)) { | ||
513 | ino = ovl_remap_lower_ino(ino, xinobits, | ||
514 | ovl_layer_lower(this)->fsid, | ||
515 | p->name, p->len); | ||
494 | } | 516 | } |
495 | 517 | ||
496 | out: | 518 | out: |
@@ -618,6 +640,8 @@ struct ovl_readdir_translate { | |||
618 | struct ovl_dir_cache *cache; | 640 | struct ovl_dir_cache *cache; |
619 | struct dir_context ctx; | 641 | struct dir_context ctx; |
620 | u64 parent_ino; | 642 | u64 parent_ino; |
643 | int fsid; | ||
644 | int xinobits; | ||
621 | }; | 645 | }; |
622 | 646 | ||
623 | static int ovl_fill_real(struct dir_context *ctx, const char *name, | 647 | static int ovl_fill_real(struct dir_context *ctx, const char *name, |
@@ -628,14 +652,17 @@ static int ovl_fill_real(struct dir_context *ctx, const char *name, | |||
628 | container_of(ctx, struct ovl_readdir_translate, ctx); | 652 | container_of(ctx, struct ovl_readdir_translate, ctx); |
629 | struct dir_context *orig_ctx = rdt->orig_ctx; | 653 | struct dir_context *orig_ctx = rdt->orig_ctx; |
630 | 654 | ||
631 | if (rdt->parent_ino && strcmp(name, "..") == 0) | 655 | if (rdt->parent_ino && strcmp(name, "..") == 0) { |
632 | ino = rdt->parent_ino; | 656 | ino = rdt->parent_ino; |
633 | else if (rdt->cache) { | 657 | } else if (rdt->cache) { |
634 | struct ovl_cache_entry *p; | 658 | struct ovl_cache_entry *p; |
635 | 659 | ||
636 | p = ovl_cache_entry_find(&rdt->cache->root, name, namelen); | 660 | p = ovl_cache_entry_find(&rdt->cache->root, name, namelen); |
637 | if (p) | 661 | if (p) |
638 | ino = p->ino; | 662 | ino = p->ino; |
663 | } else if (rdt->xinobits) { | ||
664 | ino = ovl_remap_lower_ino(ino, rdt->xinobits, rdt->fsid, | ||
665 | name, namelen); | ||
639 | } | 666 | } |
640 | 667 | ||
641 | return orig_ctx->actor(orig_ctx, name, namelen, offset, ino, d_type); | 668 | return orig_ctx->actor(orig_ctx, name, namelen, offset, ino, d_type); |
@@ -646,11 +673,16 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx) | |||
646 | int err; | 673 | int err; |
647 | struct ovl_dir_file *od = file->private_data; | 674 | struct ovl_dir_file *od = file->private_data; |
648 | struct dentry *dir = file->f_path.dentry; | 675 | struct dentry *dir = file->f_path.dentry; |
676 | struct ovl_layer *lower_layer = ovl_layer_lower(dir); | ||
649 | struct ovl_readdir_translate rdt = { | 677 | struct ovl_readdir_translate rdt = { |
650 | .ctx.actor = ovl_fill_real, | 678 | .ctx.actor = ovl_fill_real, |
651 | .orig_ctx = ctx, | 679 | .orig_ctx = ctx, |
680 | .xinobits = ovl_xino_bits(dir->d_sb), | ||
652 | }; | 681 | }; |
653 | 682 | ||
683 | if (rdt.xinobits && lower_layer) | ||
684 | rdt.fsid = lower_layer->fsid; | ||
685 | |||
654 | if (OVL_TYPE_MERGE(ovl_path_type(dir->d_parent))) { | 686 | if (OVL_TYPE_MERGE(ovl_path_type(dir->d_parent))) { |
655 | struct kstat stat; | 687 | struct kstat stat; |
656 | struct path statpath = file->f_path; | 688 | struct path statpath = file->f_path; |
@@ -693,9 +725,10 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) | |||
693 | * dir is impure then need to adjust d_ino for copied up | 725 | * dir is impure then need to adjust d_ino for copied up |
694 | * entries. | 726 | * entries. |
695 | */ | 727 | */ |
696 | if (ovl_same_sb(dentry->d_sb) && | 728 | if (ovl_xino_bits(dentry->d_sb) || |
697 | (ovl_test_flag(OVL_IMPURE, d_inode(dentry)) || | 729 | (ovl_same_sb(dentry->d_sb) && |
698 | OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent)))) { | 730 | (ovl_test_flag(OVL_IMPURE, d_inode(dentry)) || |
731 | OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) { | ||
699 | return ovl_iterate_real(file, ctx); | 732 | return ovl_iterate_real(file, ctx); |
700 | } | 733 | } |
701 | return iterate_dir(od->realfile, ctx); | 734 | return iterate_dir(od->realfile, ctx); |