From: Michael Labriola <michael.d.labriola@gmail.com>
To: Amir Goldstein <amir73il@gmail.com>
Cc: overlayfs <linux-unionfs@vger.kernel.org>,
Miklos Szeredi <miklos@szeredi.hu>
Subject: Re: failed open: No data available
Date: Thu, 17 Dec 2020 16:56:53 -0500 [thread overview]
Message-ID: <CAOQxz3wbqnUxSL-Ks=7USUZU1+04Uvqi-FnTZFGRL9uqQvvNfA@mail.gmail.com> (raw)
In-Reply-To: <CAOQ4uxg++DkgcO9K6wkSn0p6QvvkwK0nvxBzSpNE6RdaCH3aQg@mail.gmail.com>
On Thu, Dec 17, 2020 at 3:25 PM Amir Goldstein <amir73il@gmail.com> wrote:
>
> On Thu, Dec 17, 2020 at 9:46 PM Michael Labriola
> <michael.d.labriola@gmail.com> wrote:
> >
> > On Thu, Dec 17, 2020 at 1:07 PM Amir Goldstein <amir73il@gmail.com> wrote:
> > >
> > > On Thu, Dec 17, 2020 at 6:22 PM Michael Labriola
> > *snip*
> > > > On Thu, Dec 17, 2020 at 7:00 AM Amir Goldstein <amir73il@gmail.com> wrote:
> > > > Thanks, Amir. I didn't have CONFIG_DYNAMIC_DEBUG enabled, so
> > >
> > > I honestly don't expect to find much in the existing overlay debug prints
> > > but you never know..
> > > I suspect you will have to add debug prints to find the problem.
> >
> > Ok, here goes. I had to setup a new virtual machine that doesn't use
> > overlayfs for its root filesystem because turning on dynamic debug
> > gave way too much output for a nice controlled test. It's exhibiting
> > the same behavior as my previous tests (5.8 good, 5.9 bad). The is
> > with a freshly compiled 5.9.15 w/ CONFIG_OVERLAY_FS_XINO_AUTO turned
> > off and CONFIG_DYNAMIC_DEBUG turned on. Here's what we get:
> >
> > echo "file fs/overlayfs/* +p" > /sys/kernel/debug/dynamic_debug/control
> > mount borky2.sqsh t
> > mount -t tmpfs tmp tt
> > mkdir -p tt/upper/{upper,work}
> > mount -t overlay -o \
> > lowerdir=t,upperdir=tt/upper/upper,workdir=tt/upper/work blarg ttt
> > [ 164.505193] overlayfs: mkdir(work/work, 040000) = 0
> > [ 164.505204] overlayfs: tmpfile(work/work, 0100000) = 0
> > [ 164.505209] overlayfs: create(work/#3, 0100000) = 0
> > [ 164.505210] overlayfs: rename(work/#3, work/#4, 0x4)
> > [ 164.505216] overlayfs: unlink(work/#3) = 0
> > [ 164.505217] overlayfs: unlink(work/#4) = 0
> > [ 164.505221] overlayfs: setxattr(work/work,
> > "trusted.overlay.opaque", "0", 1, 0x0) = 0
> >
> > touch ttt/FOO
> > touch: cannot touch 'ttt/FOO': No data available
> > [ 191.919498] overlayfs: setxattr(upper/upper,
> > "trusted.overlay.impure", "y", 1, 0x0) = 0
> > [ 191.919523] overlayfs: tmpfile(work/work, 0100644) = 0
> > [ 191.919788] overlayfs: tmpfile(work/work, 0100644) = 0
> >
> > That give you any hints? I'll start reading through the overlayfs
> > code. I've never actually looked at it, so I'll be planting printk
> > calls at random. ;-)
>
> We have seen that open("FOO", O_WRONLY) fails
> We know that FOO is lower at that time so that brings us to
>
> ovl_open
> ovl_maybe_copy_up
> ovl_copy_up_flags
> ovl_copy_up_one
> ovl_do_copy_up
> ovl_set_impure
> [ 191.919498] overlayfs: setxattr(upper/upper,
> "trusted.overlay.impure", "y", 1, 0x0) = 0
> ovl_copy_up_tmpfile
> ovl_do_tmpfile
> [ 191.919523] overlayfs: tmpfile(work/work, 0100644) = 0
> ovl_copy_up_inode
> This must be were we fail and likely in:
> ovl_copy_xattr
> vfs_getxattr
> which can return -ENODATA, but it is not expected because the
> xattrs returned by vfs_listxattr should exist...
>
> So first guess would be to add a debug print for xattr 'name'
> and return value of vfs_getxattr().
Ok, here we go. I've added a bunch of printks all over the place.
Here's what we've got. Things are unchanged during mount. Trying to
touch FOO now gives me this:
[ 114.365444] ovl_open: start
[ 114.365450] ovl_maybe_copy_up: start
[ 114.365452] ovl_maybe_copy_up: need copy up
[ 114.365454] ovl_maybe_copy_up: ovl_want_write succeeded
[ 114.365459] ovl_copy_up_one: calling ovl_do_copy_up()
[ 114.365460] ovl_do_copy_up: start
[ 114.365462] ovl_do_copy_up: impure
[ 114.365464] ovl_set_impure: start
[ 114.365484] overlayfs: setxattr(upper/upper,
"trusted.overlay.impure", "y", 1, 0x0) = 0
[ 114.365486] ovl_copy_up_tmpfile: start
[ 114.365507] overlayfs: tmpfile(work/work, 0100644) = 0
[ 114.365510] ovl_copy_up_inode: start
[ 114.365511] ovl_copy_up_inode: ISREG && !metacopy
[ 114.365625] ovl_copy_xattr: start
[ 114.365630] ovl_copy_xattr: vfs_listxattr() returned 17
[ 114.365632] ovl_copy_xattr: buf allocated good
[ 114.365634] ovl_copy_xattr: vfs_listxattr() returned 17
[ 114.365636] ovl_copy_xattr: slen=17
[ 114.365638] ovl_copy_xattr: name='security.selinux'
[ 114.365643] ovl_copy_xattr: vfs_getxattr returned size=-61
[ 114.365644] ovl_copy_xattr: cleaning up
[ 114.365647] ovl_copy_up_inode: ovl_copy_xattr error=-61
[ 114.365649] ovl_copy_up_one: error=-61
[ 114.365651] ovl_copy_up_one: calling ovl_copy_up_end()
[ 114.365653] ovl_copy_up_flags: ovl_copy_up_one error=-61
[ 114.365655] ovl_maybe_copy_up: ovl_copy_up_flags error=-61
[ 114.365658] ovl_open: ovl_maybe_copy_up error=-61
[ 114.365728] ovl_copy_up_one: calling ovl_do_copy_up()
[ 114.365730] ovl_do_copy_up: start
[ 114.365731] ovl_do_copy_up: impure
[ 114.365733] ovl_set_impure: start
[ 114.365735] ovl_copy_up_tmpfile: start
[ 114.365748] overlayfs: tmpfile(work/work, 0100644) = 0
[ 114.365750] ovl_copy_up_inode: start
[ 114.365752] ovl_copy_up_inode: ISREG && !metacopy
[ 114.365770] ovl_copy_xattr: start
[ 114.365773] ovl_copy_xattr: vfs_listxattr() returned 17
[ 114.365774] ovl_copy_xattr: buf allocated good
[ 114.365776] ovl_copy_xattr: vfs_listxattr() returned 17
[ 114.365778] ovl_copy_xattr: slen=17
[ 114.365780] ovl_copy_xattr: name='security.selinux'
[ 114.365784] ovl_copy_xattr: vfs_getxattr returned size=-61
[ 114.365785] ovl_copy_xattr: cleaning up
[ 114.365787] ovl_copy_up_inode: ovl_copy_xattr error=-61
[ 114.365789] ovl_copy_up_one: error=-61
[ 114.365790] ovl_copy_up_one: calling ovl_copy_up_end()
[ 114.365792] ovl_copy_up_flags: ovl_copy_up_one error=-61
And so you can decode my splattering of debug, here's my diff
(although I'm sure gmail will line-wrap it to death):
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index d07fb92b7253..f3f25c1bf13e 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -50,11 +50,13 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
int error = 0;
size_t slen;
+ printk("%s: start\n", __func__);
if (!(old->d_inode->i_opflags & IOP_XATTR) ||
!(new->d_inode->i_opflags & IOP_XATTR))
return 0;
- list_size = vfs_listxattr(old, NULL, 0);
+ list_size = vfs_listxattr(old, NULL, 0);
+ printk("%s: vfs_listxattr() returned %ld\n", __func__, list_size);
if (list_size <= 0) {
if (list_size == -EOPNOTSUPP)
return 0;
@@ -64,8 +66,10 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
buf = kzalloc(list_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
+ printk("%s: buf allocated good\n", __func__);
list_size = vfs_listxattr(old, buf, list_size);
+ printk("%s: vfs_listxattr() returned %ld\n", __func__, list_size);
if (list_size <= 0) {
error = list_size;
goto out;
@@ -73,7 +77,9 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
for (name = buf; list_size; name += slen) {
slen = strnlen(name, list_size) + 1;
-
+ printk("%s: slen=%ld\n", __func__, slen);
+ printk("%s: name='%s'\n", __func__, name);
+
/* underlying fs providing us with an broken xattr list? */
if (WARN_ON(slen > list_size)) {
error = -EIO;
@@ -81,24 +87,34 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
}
list_size -= slen;
- if (ovl_is_private_xattr(name))
+ if (ovl_is_private_xattr(name)) {
+ printk("%s: ovl_is_private_xattr, continue\n", __func__);
continue;
+ }
retry:
size = vfs_getxattr(old, name, value, value_size);
- if (size == -ERANGE)
+ printk("%s: vfs_getxattr returned size=%ld\n", __func__, size);
+
+ if (size == -ERANGE) {
+ printk("%s: ERANGE, trying again\n", __func__);
size = vfs_getxattr(old, name, NULL, 0);
+ printk("%s: 2nd try size=%ld\n", __func__, size);
+ }
if (size < 0) {
error = size;
break;
}
+ printk("%s: value_size=%ld\n", __func__, value_size);
if (size > value_size) {
void *new;
+ printk("%s: reallocating\n", __func__);
new = krealloc(value, size, GFP_KERNEL);
if (!new) {
error = -ENOMEM;
+ printk("%s: krealloc error\n", __func__);
break;
}
value = new;
@@ -107,6 +123,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
}
error = security_inode_copy_up_xattr(name);
+ printk("%s: security_inode_copy_up_xattr() error=%d\n",
__func__, error);
if (error < 0 && error != -EOPNOTSUPP)
break;
if (error == 1) {
@@ -114,6 +131,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
continue; /* Discard */
}
error = vfs_setxattr(new, name, value, size, 0);
+ printk("%s: vfs_setxattr() error=%d\n", __func__, error);
if (error) {
if (error != -EOPNOTSUPP || ovl_must_copy_xattr(name))
break;
@@ -122,6 +140,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
error = 0;
}
}
+ printk("%s: cleaning up", __func__);
kfree(value);
out:
kfree(buf);
@@ -485,6 +504,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
{
int err;
+ printk("%s: start\n", __func__);
/*
* Copy up data first and then xattrs. Writing data after
@@ -492,6 +512,7 @@ static int ovl_copy_up_inode(struct
ovl_copy_up_ctx *c, struct dentry *temp)
*/
if (S_ISREG(c->stat.mode) && !c->metacopy) {
struct path upperpath, datapath;
+ printk("%s: ISREG && !metacopy\n", __func__);
ovl_path_upper(c->dentry, &upperpath);
if (WARN_ON(upperpath.dentry != NULL))
@@ -500,13 +521,17 @@ static int ovl_copy_up_inode(struct
ovl_copy_up_ctx *c, struct dentry *temp)
ovl_path_lowerdata(c->dentry, &datapath);
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
- if (err)
+ if (err) {
+ printk("%s: ovl_copy_up_data error=%d\n", __func__, err);
return err;
+ }
}
err = ovl_copy_xattr(c->lowerpath.dentry, temp);
- if (err)
+ if (err) {
+ printk("%s: ovl_copy_xattr error=%d\n", __func__, err);
return err;
+ }
/*
* Store identifier of lower inode in upper inode xattr to
@@ -516,23 +541,36 @@ static int ovl_copy_up_inode(struct
ovl_copy_up_ctx *c, struct dentry *temp)
* hard link.
*/
if (c->origin) {
+ printk("%s: origin\n", __func__);
err = ovl_set_origin(c->dentry, c->lowerpath.dentry, temp);
- if (err)
+ if (err) {
+ printk("%s: ovl_set_origin error=%d\n", __func__, err);
return err;
+ }
}
if (c->metacopy) {
+ printk("%s: metacopy\n", __func__);
err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
NULL, 0, -EOPNOTSUPP);
- if (err)
+ if (err) {
+ printk("%s: ovl_check_setxattr error=%d\n", __func__, err);
return err;
+ }
}
inode_lock(temp->d_inode);
- if (S_ISREG(c->stat.mode))
+ if (S_ISREG(c->stat.mode)) {
+ printk("%s: ISREG\n", __func__);
err = ovl_set_size(temp, &c->stat);
- if (!err)
+ if (err)
+ printk("%s: ovl_set_size error=%d\n", __func__, err);
+ }
+ if (!err) {
err = ovl_set_attr(temp, &c->stat);
+ if (err)
+ printk("%s: ovl_set_attr error=%d\n", __func__, err);
+ }
inode_unlock(temp->d_inode);
return err;
@@ -645,6 +683,8 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
struct ovl_cu_creds cc;
int err;
+ printk("%s: start\n", __func__);
+
err = ovl_prep_cu_creds(c->dentry, &cc);
if (err)
return err;
@@ -698,6 +738,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
struct ovl_fs *ofs = c->dentry->d_sb->s_fs_info;
bool to_index = false;
+ printk("%s: start\n", __func__);
+
/*
* Indexed non-dir is copied up directly to the index entry and then
* hardlinked to upper dir. Indexed dir is copied up to indexdir,
@@ -705,6 +747,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
* Copying dir up to indexdir instead of workdir simplifies locking.
*/
if (ovl_need_index(c->dentry)) {
+ printk("%s: need index\n", __func__);
c->indexed = true;
if (S_ISDIR(c->stat.mode))
c->workdir = ovl_indexdir(c->dentry->d_sb);
@@ -716,6 +759,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
c->origin = true;
if (to_index) {
+ printk("%s: to_index\n", __func__);
c->destdir = ovl_indexdir(c->dentry->d_sb);
err = ovl_get_index_name(c->lowerpath.dentry, &c->destname);
if (err)
@@ -724,6 +768,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
/* Disconnected dentry must be copied up to index dir */
return -EIO;
} else {
+ printk("%s: impure\n", __func__);
/*
* Mark parent "impure" because it may now contain non-pure
* upper
@@ -882,12 +927,25 @@ static int ovl_copy_up_one(struct dentry
*parent, struct dentry *dentry,
if (err > 0)
err = 0;
} else {
- if (!ovl_dentry_upper(dentry))
+ if (!ovl_dentry_upper(dentry)) {
+ printk("%s: calling ovl_do_copy_up()\n", __func__);
err = ovl_do_copy_up(&ctx);
- if (!err && parent && !ovl_dentry_has_upper_alias(dentry))
+ if (err)
+ printk("%s: error=%d\n", __func__, err);
+ }
+ if (!err && parent && !ovl_dentry_has_upper_alias(dentry)) {
+ printk("%s: calling ovl_link_up()\n", __func__);
err = ovl_link_up(&ctx);
- if (!err && ovl_dentry_needs_data_copy_up_locked(dentry, flags))
+ if (err)
+ printk("%s: error=%d\n", __func__, err);
+ }
+ if (!err && ovl_dentry_needs_data_copy_up_locked(dentry, flags)) {
+ printk("%s: calling ovl_copy_up_meta_inode_data()\n", __func__);
err = ovl_copy_up_meta_inode_data(&ctx);
+ if (err)
+ printk("%s: error=%d\n", __func__, err);
+ }
+ printk("%s: calling ovl_copy_up_end()\n", __func__);
ovl_copy_up_end(dentry);
}
do_delayed_call(&done);
@@ -929,6 +987,8 @@ static int ovl_copy_up_flags(struct dentry
*dentry, int flags)
}
err = ovl_copy_up_one(parent, next, flags);
+ if (err)
+ printk("%s: ovl_copy_up_one error=%d\n", __func__, err);
dput(parent);
dput(next);
@@ -957,10 +1017,15 @@ int ovl_maybe_copy_up(struct dentry *dentry, int flags)
{
int err = 0;
+ printk("%s: start\n", __func__);
if (ovl_open_need_copy_up(dentry, flags)) {
+ printk("%s: need copy up\n", __func__);
err = ovl_want_write(dentry);
if (!err) {
+ printk("%s: ovl_want_write succeeded\n", __func__);
err = ovl_copy_up_flags(dentry, flags);
+ if (err)
+ printk("%s: ovl_copy_up_flags error=%d\n", __func__, err);
ovl_drop_write(dentry);
}
}
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 0d940e29d62b..b9de23a17268 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -144,19 +144,25 @@ static int ovl_open(struct inode *inode, struct
file *file)
struct file *realfile;
int err;
+ printk("%s: start\n", __func__);
err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
- if (err)
+ if (err) {
+ printk("%s: ovl_maybe_copy_up error=%d\n", __func__, err);
return err;
+ }
/* No longer need these flags, so don't pass them on to underlying fs */
file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
- if (IS_ERR(realfile))
+ if (IS_ERR(realfile)) {
+ printk("%s: ovl_open_realfile error=%ld\n", __func__,
PTR_ERR(realfile));
return PTR_ERR(realfile);
+ }
file->private_data = realfile;
+ printk("%s: done\n", __func__);
return 0;
}
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 56c1f89f20c9..2f0071595ed7 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -597,6 +597,7 @@ int ovl_set_impure(struct dentry *dentry, struct
dentry *upperdentry)
{
int err;
+ printk("%s: start\n", __func__);
if (ovl_test_flag(OVL_IMPURE, d_inode(dentry)))
return 0;
--
Michael D Labriola
21 Rip Van Winkle Cir
Warwick, RI 02886
401-316-9844 (cell)
next prev parent reply other threads:[~2020-12-17 21:57 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-14 23:06 failed open: No data available Michael D Labriola
2020-12-15 15:32 ` Michael D Labriola
2020-12-15 16:31 ` Amir Goldstein
2020-12-15 19:29 ` Michael Labriola
2020-12-16 6:04 ` Amir Goldstein
2020-12-16 19:49 ` Michael Labriola
2020-12-16 23:01 ` Michael Labriola
2020-12-17 12:00 ` Amir Goldstein
2020-12-17 16:22 ` Michael Labriola
2020-12-17 18:06 ` Amir Goldstein
2020-12-17 19:46 ` Michael Labriola
2020-12-17 20:25 ` Amir Goldstein
2020-12-17 21:56 ` Michael Labriola [this message]
2020-12-17 23:47 ` Michael Labriola
2020-12-18 7:02 ` Amir Goldstein
2020-12-18 20:47 ` Michael Labriola
2020-12-18 22:55 ` Paul Moore
2020-12-19 9:52 ` Amir Goldstein
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAOQxz3wbqnUxSL-Ks=7USUZU1+04Uvqi-FnTZFGRL9uqQvvNfA@mail.gmail.com' \
--to=michael.d.labriola@gmail.com \
--cc=amir73il@gmail.com \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).