Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9678e630 authored by Amir Goldstein's avatar Amir Goldstein Committed by Miklos Szeredi
Browse files

ovl: fix inconsistent d_ino for legacy merge dir



For a merge dir that was copied up before v4.12 or that was hand crafted
offline (e.g. mkdir {upper/lower}/dir), upper dir does not contain the
'trusted.overlay.origin' xattr.  In that case, stat(2) on the merge dir
returns the lower dir st_ino, but getdents(2) returns the upper dir d_ino.

After this change, on merge dir lookup, missing origin xattr on upper
dir will be fixed and 'impure' xattr will be fixed on parent of the legacy
merge dir.

Suggested-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent a5a927a7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -288,7 +288,7 @@ struct ovl_fh *ovl_encode_fh(struct dentry *lower, bool is_upper)
	return fh;
}

static int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
		   struct dentry *upper)
{
	const struct ovl_fh *fh = NULL;
+33 −0
Original line number Diff line number Diff line
@@ -584,6 +584,27 @@ static int ovl_find_layer(struct ovl_fs *ofs, struct ovl_path *path)
	return i;
}

/* Fix missing 'origin' xattr */
static int ovl_fix_origin(struct dentry *dentry, struct dentry *lower,
			  struct dentry *upper)
{
	int err;

	if (ovl_check_origin_xattr(upper))
		return 0;

	err = ovl_want_write(dentry);
	if (err)
		return err;

	err = ovl_set_origin(dentry, lower, upper);
	if (!err)
		err = ovl_set_impure(dentry->d_parent, upper->d_parent);

	ovl_drop_write(dentry);
	return err;
}

struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
			  unsigned int flags)
{
@@ -674,6 +695,18 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
		if (!this)
			continue;

		/*
		 * If no origin fh is stored in upper of a merge dir, store fh
		 * of lower dir and set upper parent "impure".
		 */
		if (upperdentry && !ctr && !ofs->noxattr) {
			err = ovl_fix_origin(dentry, this, upperdentry);
			if (err) {
				dput(this);
				goto out_put;
			}
		}

		stack[ctr].dentry = this;
		stack[ctr].layer = lower.layer;
		ctr++;
+2 −0
Original line number Diff line number Diff line
@@ -322,3 +322,5 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags);
int ovl_copy_xattr(struct dentry *old, struct dentry *new);
int ovl_set_attr(struct dentry *upper, struct kstat *stat);
struct ovl_fh *ovl_encode_fh(struct dentry *lower, bool is_upper);
int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
		   struct dentry *upper);