aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2015-05-19 08:30:12 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2015-05-19 08:30:12 -0400
commitcc6f67bcafcb6bbbb2d1be1603dcd95125a52800 (patch)
tree0d3cb24661ad0c375540791ec24c6fc80760f5b3 /fs
parentd377c5eb54dd05aeb3094b7740252d19ba7791f7 (diff)
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+
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/copy_up.c3
-rw-r--r--fs/overlayfs/dir.c9
-rw-r--r--fs/overlayfs/super.c10
3 files changed, 17 insertions, 5 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 24f640441bd9..84d693d37428 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -299,6 +299,9 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
299 struct cred *override_cred; 299 struct cred *override_cred;
300 char *link = NULL; 300 char *link = NULL;
301 301
302 if (WARN_ON(!workdir))
303 return -EROFS;
304
302 ovl_path_upper(parent, &parentpath); 305 ovl_path_upper(parent, &parentpath);
303 upperdir = parentpath.dentry; 306 upperdir = parentpath.dentry;
304 307
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 2578a0c0677d..692ceda3bc21 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -222,6 +222,9 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
222 struct kstat stat; 222 struct kstat stat;
223 int err; 223 int err;
224 224
225 if (WARN_ON(!workdir))
226 return ERR_PTR(-EROFS);
227
225 err = ovl_lock_rename_workdir(workdir, upperdir); 228 err = ovl_lock_rename_workdir(workdir, upperdir);
226 if (err) 229 if (err)
227 goto out; 230 goto out;
@@ -322,6 +325,9 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
322 struct dentry *newdentry; 325 struct dentry *newdentry;
323 int err; 326 int err;
324 327
328 if (WARN_ON(!workdir))
329 return -EROFS;
330
325 err = ovl_lock_rename_workdir(workdir, upperdir); 331 err = ovl_lock_rename_workdir(workdir, upperdir);
326 if (err) 332 if (err)
327 goto out; 333 goto out;
@@ -506,6 +512,9 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
506 struct dentry *opaquedir = NULL; 512 struct dentry *opaquedir = NULL;
507 int err; 513 int err;
508 514
515 if (WARN_ON(!workdir))
516 return -EROFS;
517
509 if (is_dir) { 518 if (is_dir) {
510 if (OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) { 519 if (OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {
511 opaquedir = ovl_check_empty_and_clear(dentry); 520 opaquedir = ovl_check_empty_and_clear(dentry);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 5f0d1993e6e3..bf8537c7f455 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -529,7 +529,7 @@ static int ovl_remount(struct super_block *sb, int *flags, char *data)
529{ 529{
530 struct ovl_fs *ufs = sb->s_fs_info; 530 struct ovl_fs *ufs = sb->s_fs_info;
531 531
532 if (!(*flags & MS_RDONLY) && !ufs->upper_mnt) 532 if (!(*flags & MS_RDONLY) && (!ufs->upper_mnt || !ufs->workdir))
533 return -EROFS; 533 return -EROFS;
534 534
535 return 0; 535 return 0;
@@ -925,9 +925,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
925 ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry); 925 ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
926 err = PTR_ERR(ufs->workdir); 926 err = PTR_ERR(ufs->workdir);
927 if (IS_ERR(ufs->workdir)) { 927 if (IS_ERR(ufs->workdir)) {
928 pr_err("overlayfs: failed to create directory %s/%s\n", 928 pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n",
929 ufs->config.workdir, OVL_WORKDIR_NAME); 929 ufs->config.workdir, OVL_WORKDIR_NAME, -err);
930 goto out_put_upper_mnt; 930 sb->s_flags |= MS_RDONLY;
931 ufs->workdir = NULL;
931 } 932 }
932 } 933 }
933 934
@@ -997,7 +998,6 @@ out_put_lower_mnt:
997 kfree(ufs->lower_mnt); 998 kfree(ufs->lower_mnt);
998out_put_workdir: 999out_put_workdir:
999 dput(ufs->workdir); 1000 dput(ufs->workdir);
1000out_put_upper_mnt:
1001 mntput(ufs->upper_mnt); 1001 mntput(ufs->upper_mnt);
1002out_put_lowerpath: 1002out_put_lowerpath:
1003 for (i = 0; i < numlower; i++) 1003 for (i = 0; i < numlower; i++)