diff options
author | Chandan Rajendra <chandan@linux.vnet.ibm.com> | 2017-07-24 01:57:54 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2017-11-09 10:23:27 +0100 |
commit | b93436320c1e9089a055941523571cd7c037f7cb (patch) | |
tree | c97ece67e4499dd7b184b728272786b597aed681 /fs/overlayfs/super.c | |
parent | ee023c30d7d6bc21d3a85f3625a30209bdcc41e6 (diff) |
ovl: re-structure overlay lower layers in-memory
Define new structures to represent overlay instance lower layers and
overlay merge dir lower layers to make room for storing more per layer
information in-memory.
Instead of keeping the fs instance lower layers in an array of struct
vfsmount, keep them in an array of new struct ovl_layer, that has a
pointer to struct vfsmount.
Instead of keeping the dentry lower layers in an array of struct path,
keep them in an array of new struct ovl_path, that has a pointer to
struct dentry and to struct ovl_layer.
Add a small helper to find the fs layer id that correspopnds to a lower
struct ovl_path and use it in ovl_lookup().
[amir: split re-structure from anonymous bdev patch]
Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs/super.c')
-rw-r--r-- | fs/overlayfs/super.c | 62 |
1 files changed, 34 insertions, 28 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index e3d49e965224..a10fff49194b 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -220,8 +220,8 @@ static void ovl_put_super(struct super_block *sb) ovl_inuse_unlock(ufs->upper_mnt->mnt_root); mntput(ufs->upper_mnt); for (i = 0; i < ufs->numlower; i++) - mntput(ufs->lower_mnt[i]); - kfree(ufs->lower_mnt); + mntput(ufs->lower_layers[i].mnt); + kfree(ufs->lower_layers); kfree(ufs->config.lowerdir); kfree(ufs->config.upperdir); @@ -1026,24 +1026,26 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) } err = -ENOMEM; - ufs->lower_mnt = kcalloc(numlower, sizeof(struct vfsmount *), GFP_KERNEL); - if (ufs->lower_mnt == NULL) + ufs->lower_layers = kcalloc(numlower, sizeof(struct ovl_layer), + GFP_KERNEL); + if (ufs->lower_layers == NULL) goto out_put_workdir; for (i = 0; i < numlower; i++) { - struct vfsmount *mnt = clone_private_mount(&stack[i]); + struct vfsmount *mnt; + mnt = clone_private_mount(&stack[i]); err = PTR_ERR(mnt); if (IS_ERR(mnt)) { pr_err("overlayfs: failed to clone lowerpath\n"); - goto out_put_lower_mnt; + goto out_put_lower_layers; } /* - * Make lower_mnt R/O. That way fchmod/fchown on lower file + * Make lower layers R/O. That way fchmod/fchown on lower file * will fail instead of modifying lower fs. */ mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME; - ufs->lower_mnt[ufs->numlower] = mnt; + ufs->lower_layers[ufs->numlower].mnt = mnt; ufs->numlower++; /* Check if all lower layers are on same sb */ @@ -1059,13 +1061,25 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) else if (ufs->upper_mnt->mnt_sb != ufs->same_sb) ufs->same_sb = NULL; + err = -ENOMEM; + oe = ovl_alloc_entry(numlower); + if (!oe) + goto out_put_lower_layers; + + for (i = 0; i < numlower; i++) { + oe->lowerstack[i].dentry = stack[i].dentry; + oe->lowerstack[i].layer = &(ufs->lower_layers[i]); + } + if (!(ovl_force_readonly(ufs)) && ufs->config.index) { /* Verify lower root is upper root origin */ - err = ovl_verify_origin(upperpath.dentry, ufs->lower_mnt[0], - stack[0].dentry, false, true); + err = ovl_verify_origin(upperpath.dentry, + oe->lowerstack[0].layer->mnt, + oe->lowerstack[0].dentry, + false, true); if (err) { pr_err("overlayfs: failed to verify upper root origin\n"); - goto out_put_lower_mnt; + goto out_free_oe; } ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry, @@ -1081,7 +1095,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) if (!err) err = ovl_indexdir_cleanup(ufs->indexdir, ufs->upper_mnt, - stack, numlower); + oe->lowerstack, + numlower); } if (err || !ufs->indexdir) pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); @@ -1106,11 +1121,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) /* Never override disk quota limits or use reserved space */ cap_lower(cred->cap_effective, CAP_SYS_RESOURCE); - err = -ENOMEM; - oe = ovl_alloc_entry(numlower); - if (!oe) - goto out_put_cred; - sb->s_magic = OVERLAYFS_SUPER_MAGIC; sb->s_op = &ovl_super_operations; sb->s_xattr = ovl_xattr_handlers; @@ -1119,11 +1129,12 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, 0)); if (!root_dentry) - goto out_free_oe; + goto out_put_cred; mntput(upperpath.mnt); for (i = 0; i < numlower; i++) mntput(stack[i].mnt); + kfree(stack); mntput(workpath.mnt); kfree(lowertmp); @@ -1132,11 +1143,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) if (ovl_is_impuredir(upperpath.dentry)) ovl_set_flag(OVL_IMPURE, d_inode(root_dentry)); } - for (i = 0; i < numlower; i++) { - oe->lowerstack[i].dentry = stack[i].dentry; - oe->lowerstack[i].mnt = ufs->lower_mnt[i]; - } - kfree(stack); root_dentry->d_fsdata = oe; @@ -1149,16 +1155,16 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) return 0; -out_free_oe: - kfree(oe); out_put_cred: put_cred(ufs->creator_cred); out_put_indexdir: dput(ufs->indexdir); -out_put_lower_mnt: +out_free_oe: + kfree(oe); +out_put_lower_layers: for (i = 0; i < ufs->numlower; i++) - mntput(ufs->lower_mnt[i]); - kfree(ufs->lower_mnt); + mntput(ufs->lower_layers[i].mnt); + kfree(ufs->lower_layers); out_put_workdir: dput(ufs->workdir); mntput(ufs->upper_mnt); |