diff mbox

[OpenWrt-Devel,v3,kernel] upstream fix: mount overlayfs r/o if workdir cannot be created

Message ID 20150527165815.GA26924@medion.lan
State Accepted
Headers show

Commit Message

Bastian Bittorf May 27, 2015, 4:58 p.m. UTC
This is the case e.g. if JFFS2 partition is full.

see: https://www.mail-archive.com/linux-unionfs@vger.kernel.org/msg00246.html
(a small error in a logmessage was changed and reported upstream)

runtime tested on ar71xx with kernel 3.18.11 and r45772
this paritially fixes #19564

Signed-off-by: Bastian Bittorf <bittorf@bluebottle.com>
---
 ...-overlayfs-fallback-to-readonly-when-full.patch |  109 ++++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100644 target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch

Comments

Jo-Philipp Wich May 27, 2015, 4:52 p.m. UTC | #1
On 05/27/2015 06:58 PM, Bastian Bittorf wrote:
> This is the case e.g. if JFFS2 partition is full.
> 
> see: https://www.mail-archive.com/linux-unionfs@vger.kernel.org/msg00246.html
> (a small error in a logmessage was changed and reported upstream)
> 
> runtime tested on ar71xx with kernel 3.18.11 and r45772
> this paritially fixes #19564
> 
> Signed-off-by: Bastian Bittorf <bittorf@bluebottle.com>

Acked-by: Jo-Philipp Wich <jow@openwrt.org>

> ---
>  ...-overlayfs-fallback-to-readonly-when-full.patch |  109 ++++++++++++++++++++
>  1 file changed, 109 insertions(+)
>  create mode 100644 target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch
> 
> diff --git a/target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch b/target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch
> new file mode 100644
> index 0000000..21f11fd
> --- /dev/null
> +++ b/target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch
> @@ -0,0 +1,109 @@
> +[linux-unionfs added to Cc]
> +
> +On Tue, May 19, 2015 at 09:51:20AM +0200, Bastian Bittorf wrote:
> +> Hi Miklos,
> +>
> +> sorry for writing directly to you, feel free to forward
> +> this to the appropriate mailinglist.
> +>
> +> we have a problem with mainline overlay filesystem on kernel 3.18:
> +> https://dev.openwrt.org/ticket/19564
> +>
> +> 2 things are odd:
> +> when the working filesystem is full, overlays fails with:
> +>
> +> overlayfs: failed to create directory /overlay/work/work
> +>
> +> what is strange, that we call it with:
> +>
> +> mount(overlay, "/mnt", "overlay", MS_NOATIME, lowerdir)
> +>
> +> see here:
> +> http://nbd.name/gitweb.cgi?p=fstools.git;a=blob;f=libfstools/mount.c;h=81176ce399b4cd8e2d347c0008c13dec92407f55;hb=e6004000ff15d7bd32cf5663e8690fc94d7ec747#l125
> +>
> +> do you have an idea whats wrong?
> +> 1) is it really needed, that we need space for creating dir "/overlay/work"?
> +> 2) why does overlay need "/overlay/work/work"?
> +
> +The work directory is needed for atomic copy-up and similar.  It is not actually
> +necessary to mount a read-only overlay.  Post 4.0 it is possible to mount the
> +overlay without workdir (but even then it won't happen automatically in case the
> +upper fs is full, so this should be fixed in the latest kernel too).
> +
> +Could you please try the following patch?  If the workdir can't be created it
> +will fall back to mounting the overlay read-only.
> +
> +Thanks,
> +Miklos
> +
> +---
> + fs/overlayfs/copy_up.c |    3 +++
> + fs/overlayfs/dir.c     |    9 +++++++++
> + fs/overlayfs/super.c   |   12 +++++++++---
> + 3 files changed, 21 insertions(+), 3 deletions(-)
> +
> +--- a/fs/overlayfs/copy_up.c
> ++++ b/fs/overlayfs/copy_up.c
> +@@ -300,6 +300,9 @@ int ovl_copy_up_one(struct dentry *paren
> +	struct cred *override_cred;
> +	char *link = NULL;
> +
> ++	if (WARN_ON(!workdir))
> ++		return -EROFS;
> ++
> +	ovl_path_upper(parent, &parentpath);
> +	upperdir = parentpath.dentry;
> +
> +--- a/fs/overlayfs/dir.c
> ++++ b/fs/overlayfs/dir.c
> +@@ -222,6 +222,9 @@ static struct dentry *ovl_clear_empty(st
> +	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(stru
> +	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(struc
> +	struct dentry *opaquedir = NULL;
> +	int err;
> +
> ++	if (WARN_ON(!workdir))
> ++		return -EROFS;
> ++
> +	if (is_dir) {
> +		opaquedir = ovl_check_empty_and_clear(dentry);
> +		err = PTR_ERR(opaquedir);
> +--- a/fs/overlayfs/super.c
> ++++ b/fs/overlayfs/super.c
> +@@ -740,9 +740,15 @@ static int ovl_fill_super(struct super_b
> +	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_lower_mnt;
> ++		if (err == -ENOSPC || err == -EROFS) {
> ++			pr_warning("overlayfs: failed to create work directory (%s), mounting read-only\n", err == ENOSPC ? "ENOSPC" : "EROFS");
> ++			sb->s_flags |= MS_RDONLY;
> ++			ufs->workdir = NULL;
> ++		} else {
> ++			pr_err("overlayfs: failed to create directory %s/%s\n",
> ++			       ufs->config.workdir, OVL_WORKDIR_NAME);
> ++			goto out_put_lower_mnt;
> ++		}
> +	}
> +
> +	/*
>
diff mbox

Patch

diff --git a/target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch b/target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch
new file mode 100644
index 0000000..21f11fd
--- /dev/null
+++ b/target/linux/ar71xx/patches-3.18/910-overlayfs-fallback-to-readonly-when-full.patch
@@ -0,0 +1,109 @@ 
+[linux-unionfs added to Cc]
+
+On Tue, May 19, 2015 at 09:51:20AM +0200, Bastian Bittorf wrote:
+> Hi Miklos,
+>
+> sorry for writing directly to you, feel free to forward
+> this to the appropriate mailinglist.
+>
+> we have a problem with mainline overlay filesystem on kernel 3.18:
+> https://dev.openwrt.org/ticket/19564
+>
+> 2 things are odd:
+> when the working filesystem is full, overlays fails with:
+>
+> overlayfs: failed to create directory /overlay/work/work
+>
+> what is strange, that we call it with:
+>
+> mount(overlay, "/mnt", "overlay", MS_NOATIME, lowerdir)
+>
+> see here:
+> http://nbd.name/gitweb.cgi?p=fstools.git;a=blob;f=libfstools/mount.c;h=81176ce399b4cd8e2d347c0008c13dec92407f55;hb=e6004000ff15d7bd32cf5663e8690fc94d7ec747#l125
+>
+> do you have an idea whats wrong?
+> 1) is it really needed, that we need space for creating dir "/overlay/work"?
+> 2) why does overlay need "/overlay/work/work"?
+
+The work directory is needed for atomic copy-up and similar.  It is not actually
+necessary to mount a read-only overlay.  Post 4.0 it is possible to mount the
+overlay without workdir (but even then it won't happen automatically in case the
+upper fs is full, so this should be fixed in the latest kernel too).
+
+Could you please try the following patch?  If the workdir can't be created it
+will fall back to mounting the overlay read-only.
+
+Thanks,
+Miklos
+
+---
+ fs/overlayfs/copy_up.c |    3 +++
+ fs/overlayfs/dir.c     |    9 +++++++++
+ fs/overlayfs/super.c   |   12 +++++++++---
+ 3 files changed, 21 insertions(+), 3 deletions(-)
+
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -300,6 +300,9 @@ int ovl_copy_up_one(struct dentry *paren
+	struct cred *override_cred;
+	char *link = NULL;
+
++	if (WARN_ON(!workdir))
++		return -EROFS;
++
+	ovl_path_upper(parent, &parentpath);
+	upperdir = parentpath.dentry;
+
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -222,6 +222,9 @@ static struct dentry *ovl_clear_empty(st
+	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(stru
+	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(struc
+	struct dentry *opaquedir = NULL;
+	int err;
+
++	if (WARN_ON(!workdir))
++		return -EROFS;
++
+	if (is_dir) {
+		opaquedir = ovl_check_empty_and_clear(dentry);
+		err = PTR_ERR(opaquedir);
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -740,9 +740,15 @@ static int ovl_fill_super(struct super_b
+	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_lower_mnt;
++		if (err == -ENOSPC || err == -EROFS) {
++			pr_warning("overlayfs: failed to create work directory (%s), mounting read-only\n", err == ENOSPC ? "ENOSPC" : "EROFS");
++			sb->s_flags |= MS_RDONLY;
++			ufs->workdir = NULL;
++		} else {
++			pr_err("overlayfs: failed to create directory %s/%s\n",
++			       ufs->config.workdir, OVL_WORKDIR_NAME);
++			goto out_put_lower_mnt;
++		}
+	}
+
+	/*