ovl: mount read-only if workdir can't be created
OpenWRT folks reported that overlayfs fails to mount if upper fs is full, because workdir can't be created. Wordir creation can fail for various other reasons too. There's no reason that the mount itself should fail, overlayfs can work fine without a workdir, as long as the overlay isn't modified. So mount it read-only and don't allow remounting read-write. Add a couple of WARN_ON()s for the impossible case of workdir being used despite being read-only. Reported-by: Bastian Bittorf <bittorf@bluebottle.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Cc: <stable@vger.kernel.org> # v3.18+
This commit is contained in:
parent
d377c5eb54
commit
cc6f67bcaf
|
@ -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,6 +512,9 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
|
|||
struct dentry *opaquedir = NULL;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
|
|
@ -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 @@ out_put_lower_mnt:
|
|||
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 New Issue