Commit 6b8aa129 authored by Amir Goldstein's avatar Amir Goldstein Committed by Miklos Szeredi

ovl: generalize ovl_create_workdir()

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: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent f7d3daca
...@@ -418,22 +418,27 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) ...@@ -418,22 +418,27 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
#define OVL_WORKDIR_NAME "work" #define OVL_WORKDIR_NAME "work"
static struct dentry *ovl_workdir_create(struct vfsmount *mnt, static struct dentry *ovl_workdir_create(struct super_block *sb,
struct dentry *dentry) struct ovl_fs *ufs,
struct dentry *dentry,
const char *name, bool persist)
{ {
struct inode *dir = dentry->d_inode; struct inode *dir = dentry->d_inode;
struct vfsmount *mnt = ufs->upper_mnt;
struct dentry *work; struct dentry *work;
int err; int err;
bool retried = false; bool retried = false;
bool locked = false;
err = mnt_want_write(mnt); err = mnt_want_write(mnt);
if (err) if (err)
return ERR_PTR(err); goto out_err;
inode_lock_nested(dir, I_MUTEX_PARENT); inode_lock_nested(dir, I_MUTEX_PARENT);
locked = true;
retry: retry:
work = lookup_one_len(OVL_WORKDIR_NAME, dentry, work = lookup_one_len(name, dentry, strlen(name));
strlen(OVL_WORKDIR_NAME));
if (!IS_ERR(work)) { if (!IS_ERR(work)) {
struct iattr attr = { struct iattr attr = {
...@@ -446,6 +451,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt, ...@@ -446,6 +451,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
if (retried) if (retried)
goto out_dput; goto out_dput;
if (persist)
goto out_unlock;
retried = true; retried = true;
ovl_workdir_cleanup(dir, mnt, work, 0); ovl_workdir_cleanup(dir, mnt, work, 0);
dput(work); dput(work);
...@@ -485,16 +493,24 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt, ...@@ -485,16 +493,24 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
inode_unlock(work->d_inode); inode_unlock(work->d_inode);
if (err) if (err)
goto out_dput; goto out_dput;
} else {
err = PTR_ERR(work);
goto out_err;
} }
out_unlock: out_unlock:
inode_unlock(dir);
mnt_drop_write(mnt); mnt_drop_write(mnt);
if (locked)
inode_unlock(dir);
return work; return work;
out_dput: out_dput:
dput(work); 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; goto out_unlock;
} }
...@@ -906,15 +922,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) ...@@ -906,15 +922,8 @@ 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; 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,
err = PTR_ERR(ufs->workdir); OVL_WORKDIR_NAME, false);
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;
}
/* /*
* Upper should support d_type, else whiteouts are visible. * Upper should support d_type, else whiteouts are visible.
* Given workdir and upper are on same fs, we can do * Given workdir and upper are on same fs, we can do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment