Merge branch 'overlayfs-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull two overlayfs fixes from Miklos Szeredi: "Overlayfs rmdir() failed to check for emptiness in one case; this was introduced in 4.0. The other bug was there since day one: failure to mount if upper fs is full, which bit some OpenWRT folks" * 'overlayfs-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: mount read-only if workdir can't be created ovl: don't remove non-empty opaque directory
This commit is contained in:
commit
3cfd4ba7d3
3 changed files with 36 additions and 10 deletions
|
@ -299,6 +299,9 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
|
|||
struct cred *override_cred;
|
||||
char *link = NULL;
|
||||
|
||||
if (WARN_ON(!workdir))
|
||||
return -EROFS;
|
||||
|
||||
ovl_path_upper(parent, &parentpath);
|
||||
upperdir = parentpath.dentry;
|
||||
|
||||
|
|
|
@ -222,6 +222,9 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
|
|||
struct kstat stat;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!workdir))
|
||||
return ERR_PTR(-EROFS);
|
||||
|
||||
err = ovl_lock_rename_workdir(workdir, upperdir);
|
||||
if (err)
|
||||
goto out;
|
||||
|
@ -322,6 +325,9 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
|
|||
struct dentry *newdentry;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!workdir))
|
||||
return -EROFS;
|
||||
|
||||
err = ovl_lock_rename_workdir(workdir, upperdir);
|
||||
if (err)
|
||||
goto out;
|
||||
|
@ -506,11 +512,28 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
|
|||
struct dentry *opaquedir = NULL;
|
||||
int err;
|
||||
|
||||
if (is_dir && OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {
|
||||
opaquedir = ovl_check_empty_and_clear(dentry);
|
||||
err = PTR_ERR(opaquedir);
|
||||
if (IS_ERR(opaquedir))
|
||||
goto out;
|
||||
if (WARN_ON(!workdir))
|
||||
return -EROFS;
|
||||
|
||||
if (is_dir) {
|
||||
if (OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {
|
||||
opaquedir = ovl_check_empty_and_clear(dentry);
|
||||
err = PTR_ERR(opaquedir);
|
||||
if (IS_ERR(opaquedir))
|
||||
goto out;
|
||||
} else {
|
||||
LIST_HEAD(list);
|
||||
|
||||
/*
|
||||
* When removing an empty opaque directory, then it
|
||||
* makes no sense to replace it with an exact replica of
|
||||
* itself. But emptiness still needs to be checked.
|
||||
*/
|
||||
err = ovl_check_empty_dir(dentry, &list);
|
||||
ovl_cache_free(&list);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
err = ovl_lock_rename_workdir(workdir, upperdir);
|
||||
|
|
|
@ -529,7 +529,7 @@ static int ovl_remount(struct super_block *sb, int *flags, char *data)
|
|||
{
|
||||
struct ovl_fs *ufs = sb->s_fs_info;
|
||||
|
||||
if (!(*flags & MS_RDONLY) && !ufs->upper_mnt)
|
||||
if (!(*flags & MS_RDONLY) && (!ufs->upper_mnt || !ufs->workdir))
|
||||
return -EROFS;
|
||||
|
||||
return 0;
|
||||
|
@ -925,9 +925,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|||
ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
|
||||
err = PTR_ERR(ufs->workdir);
|
||||
if (IS_ERR(ufs->workdir)) {
|
||||
pr_err("overlayfs: failed to create directory %s/%s\n",
|
||||
ufs->config.workdir, OVL_WORKDIR_NAME);
|
||||
goto out_put_upper_mnt;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -997,7 +998,6 @@ 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++)
|
||||
|
|
Loading…
Reference in a new issue