[PATCH v2 04/20] ovl: generalize ovl_create_workdir()

Amir Goldstein
2017-06-07T07:51:08Z

Pass in the subdir name to create and specify if subdir is persistent
or if it should be cleaned up on every mount.

Move fallback to readonly mount on failure to create dir and print of error
message into the helper.

This function is going to be used for creating the persistent 'index' dir
under workbasedir.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/overlayfs/super.c | 45 +++++++++++++++++++++++++++++----------------
1 file changed, 29 insertions(+), 16 deletions(-)

diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 476f021baf2a..5114627799e9 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -395,22 +395,25 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)

#define OVL_WORKDIR_NAME "work"

-static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
- struct dentry *dentry)
+static struct dentry *ovl_workdir_create(struct super_block *sb,
+ struct ovl_fs *ufs,
+ struct dentry *dentry,
+ const char *name, bool persist)
{
- struct inode *dir = dentry->d_inode;
- struct dentry *work;
+ struct vfsmount *mnt = ufs->upper_mnt;
+ struct inode *dir = NULL;
+ struct dentry *work = NULL;
int err;
bool retried = false;

err = mnt_want_write(mnt);
if (err)
- return ERR_PTR(err);
+ goto out_err;

+ dir = d_inode(dentry);
inode_lock_nested(dir, I_MUTEX_PARENT);
retry:
- work = lookup_one_len(OVL_WORKDIR_NAME, dentry,
- strlen(OVL_WORKDIR_NAME));
+ work = lookup_one_len(name, dentry, strlen(name));

if (!IS_ERR(work)) {
struct iattr attr = {
@@ -423,6 +426,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
if (retried)
goto out_dput;

+ if (persist)
+ goto out_unlock;
+
retried = true;
ovl_workdir_cleanup(dir, mnt, work, 0);
dput(work);
@@ -462,16 +468,25 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
inode_unlock(work->d_inode);
if (err)
goto out_dput;
+ } else {
+ err = PTR_ERR(work);
+ goto out_err;
}
+
out_unlock:
- inode_unlock(dir);
+ if (dir)
+ inode_unlock(dir);
mnt_drop_write(mnt);

return work;

out_dput:
dput(work);
- work = ERR_PTR(err);
+out_err:
+ pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n",
+ ufs->config.workdir, name, -err);
+ sb->s_flags |= MS_RDONLY;
+ work = NULL;
goto out_unlock;
}

@@ -885,14 +900,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)

sb->s_time_gran = ufs->upper_mnt->mnt_sb->s_time_gran;

- ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
+ ufs->workdir = ovl_workdir_create(sb, ufs, workpath.dentry,
+ OVL_WORKDIR_NAME, false);
err = PTR_ERR(ufs->workdir);
- if (IS_ERR(ufs->workdir)) {
- pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n",
- ufs->config.workdir, OVL_WORKDIR_NAME, -err);
- sb->s_flags |= MS_RDONLY;
- ufs->workdir = NULL;
- }
+ if (IS_ERR(ufs->workdir))
+ goto out_put_upper_mnt;

/*
* Upper should support d_type, else whiteouts are visible.
@@ -1035,6 +1047,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
kfree(ufs->lower_mnt);
out_put_workdir:
dput(ufs->workdir);
+out_put_upper_mnt:
mntput(ufs->upper_mnt);
out_put_lowerpath:
for (i = 0; i < numlower; i++)
--
2.7.4