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

Commit 1afaba1e authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

ovl: make path-type a bitmap



OVL_PATH_PURE_UPPER -> __OVL_PATH_UPPER | __OVL_PATH_PURE
OVL_PATH_UPPER      -> __OVL_PATH_UPPER
OVL_PATH_MERGE      -> __OVL_PATH_UPPER | __OVL_PATH_MERGE
OVL_PATH_LOWER      -> 0

Multiple R/O layers will allow __OVL_PATH_MERGE without __OVL_PATH_UPPER.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
parent 49c21e1c
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -385,7 +385,7 @@ int ovl_copy_up(struct dentry *dentry)
		struct kstat stat;
		struct kstat stat;
		enum ovl_path_type type = ovl_path_type(dentry);
		enum ovl_path_type type = ovl_path_type(dentry);


		if (type != OVL_PATH_LOWER)
		if (OVL_TYPE_UPPER(type))
			break;
			break;


		next = dget(dentry);
		next = dget(dentry);
@@ -394,7 +394,7 @@ int ovl_copy_up(struct dentry *dentry)
			parent = dget_parent(next);
			parent = dget_parent(next);


			type = ovl_path_type(parent);
			type = ovl_path_type(parent);
			if (type != OVL_PATH_LOWER)
			if (OVL_TYPE_UPPER(type))
				break;
				break;


			dput(next);
			dput(next);
+11 −11
Original line number Original line Diff line number Diff line
@@ -152,7 +152,7 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
	 * correct link count.  nlink=1 seems to pacify 'find' and
	 * correct link count.  nlink=1 seems to pacify 'find' and
	 * other utilities.
	 * other utilities.
	 */
	 */
	if (type == OVL_PATH_MERGE)
	if (OVL_TYPE_MERGE(type))
		stat->nlink = 1;
		stat->nlink = 1;


	return 0;
	return 0;
@@ -630,7 +630,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
		goto out_drop_write;
		goto out_drop_write;


	type = ovl_path_type(dentry);
	type = ovl_path_type(dentry);
	if (type == OVL_PATH_PURE_UPPER) {
	if (OVL_TYPE_PURE_UPPER(type)) {
		err = ovl_remove_upper(dentry, is_dir);
		err = ovl_remove_upper(dentry, is_dir);
	} else {
	} else {
		const struct cred *old_cred;
		const struct cred *old_cred;
@@ -712,7 +712,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
	/* Don't copy up directory trees */
	/* Don't copy up directory trees */
	old_type = ovl_path_type(old);
	old_type = ovl_path_type(old);
	err = -EXDEV;
	err = -EXDEV;
	if ((old_type == OVL_PATH_LOWER || old_type == OVL_PATH_MERGE) && is_dir)
	if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir)
		goto out;
		goto out;


	if (new->d_inode) {
	if (new->d_inode) {
@@ -725,25 +725,25 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,


		new_type = ovl_path_type(new);
		new_type = ovl_path_type(new);
		err = -EXDEV;
		err = -EXDEV;
		if (!overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir)
		if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir)
			goto out;
			goto out;


		err = 0;
		err = 0;
		if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) {
		if (!OVL_TYPE_UPPER(new_type) && !OVL_TYPE_UPPER(old_type)) {
			if (ovl_dentry_lower(old)->d_inode ==
			if (ovl_dentry_lower(old)->d_inode ==
			    ovl_dentry_lower(new)->d_inode)
			    ovl_dentry_lower(new)->d_inode)
				goto out;
				goto out;
		}
		}
		if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) {
		if (OVL_TYPE_UPPER(new_type) && OVL_TYPE_UPPER(old_type)) {
			if (ovl_dentry_upper(old)->d_inode ==
			if (ovl_dentry_upper(old)->d_inode ==
			    ovl_dentry_upper(new)->d_inode)
			    ovl_dentry_upper(new)->d_inode)
				goto out;
				goto out;
		}
		}
	} else {
	} else {
		if (ovl_dentry_is_opaque(new))
		if (ovl_dentry_is_opaque(new))
			new_type = OVL_PATH_UPPER;
			new_type = __OVL_PATH_UPPER;
		else
		else
			new_type = OVL_PATH_PURE_UPPER;
			new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE;
	}
	}


	err = ovl_want_write(old);
	err = ovl_want_write(old);
@@ -763,8 +763,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
			goto out_drop_write;
			goto out_drop_write;
	}
	}


	old_opaque = old_type != OVL_PATH_PURE_UPPER;
	old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
	new_opaque = new_type != OVL_PATH_PURE_UPPER;
	new_opaque = !OVL_TYPE_PURE_UPPER(new_type);


	if (old_opaque || new_opaque) {
	if (old_opaque || new_opaque) {
		err = -ENOMEM;
		err = -ENOMEM;
@@ -787,7 +787,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
		old_cred = override_creds(override_cred);
		old_cred = override_creds(override_cred);
	}
	}


	if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) {
	if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
		opaquedir = ovl_check_empty_and_clear(new);
		opaquedir = ovl_check_empty_and_clear(new);
		err = PTR_ERR(opaquedir);
		err = PTR_ERR(opaquedir);
		if (IS_ERR(opaquedir)) {
		if (IS_ERR(opaquedir)) {
+6 −3
Original line number Original line Diff line number Diff line
@@ -238,7 +238,10 @@ int ovl_setxattr(struct dentry *dentry, const char *name,
static bool ovl_need_xattr_filter(struct dentry *dentry,
static bool ovl_need_xattr_filter(struct dentry *dentry,
				  enum ovl_path_type type)
				  enum ovl_path_type type)
{
{
	return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode);
	if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
		return S_ISDIR(dentry->d_inode->i_mode);
	else
		return false;
}
}


ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
@@ -299,7 +302,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
		goto out_drop_write;
		goto out_drop_write;


	if (type == OVL_PATH_LOWER) {
	if (!OVL_TYPE_UPPER(type)) {
		err = vfs_getxattr(realpath.dentry, name, NULL, 0);
		err = vfs_getxattr(realpath.dentry, name, NULL, 0);
		if (err < 0)
		if (err < 0)
			goto out_drop_write;
			goto out_drop_write;
@@ -321,7 +324,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
				  struct dentry *realdentry)
				  struct dentry *realdentry)
{
{
	if (type != OVL_PATH_LOWER)
	if (OVL_TYPE_UPPER(type))
		return false;
		return false;


	if (special_file(realdentry->d_inode->i_mode))
	if (special_file(realdentry->d_inode->i_mode))
+9 −4
Original line number Original line Diff line number Diff line
@@ -12,12 +12,17 @@
struct ovl_entry;
struct ovl_entry;


enum ovl_path_type {
enum ovl_path_type {
	OVL_PATH_PURE_UPPER,
	__OVL_PATH_PURE		= (1 << 0),
	OVL_PATH_UPPER,
	__OVL_PATH_UPPER	= (1 << 1),
	OVL_PATH_MERGE,
	__OVL_PATH_MERGE	= (1 << 2),
	OVL_PATH_LOWER,
};
};


#define OVL_TYPE_UPPER(type)	((type) & __OVL_PATH_UPPER)
#define OVL_TYPE_MERGE(type)	((type) & __OVL_PATH_MERGE)
#define OVL_TYPE_PURE_UPPER(type) ((type) & __OVL_PATH_PURE)
#define OVL_TYPE_MERGE_OR_LOWER(type) \
	(OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type))

extern const char *ovl_opaque_xattr;
extern const char *ovl_opaque_xattr;


static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
+5 −5
Original line number Original line Diff line number Diff line
@@ -253,8 +253,8 @@ static void ovl_dir_reset(struct file *file)
		ovl_cache_put(od, dentry);
		ovl_cache_put(od, dentry);
		od->cache = NULL;
		od->cache = NULL;
	}
	}
	WARN_ON(!od->is_real && type != OVL_PATH_MERGE);
	WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
	if (od->is_real && type == OVL_PATH_MERGE)
	if (od->is_real && OVL_TYPE_MERGE(type))
		od->is_real = false;
		od->is_real = false;
}
}


@@ -429,7 +429,7 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
	/*
	/*
	 * Need to check if we started out being a lower dir, but got copied up
	 * Need to check if we started out being a lower dir, but got copied up
	 */
	 */
	if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) {
	if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) {
		struct inode *inode = file_inode(file);
		struct inode *inode = file_inode(file);


		realfile = lockless_dereference(od->upperfile);
		realfile = lockless_dereference(od->upperfile);
@@ -495,8 +495,8 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
	}
	}
	INIT_LIST_HEAD(&od->cursor.l_node);
	INIT_LIST_HEAD(&od->cursor.l_node);
	od->realfile = realfile;
	od->realfile = realfile;
	od->is_real = (type != OVL_PATH_MERGE);
	od->is_real = !OVL_TYPE_MERGE(type);
	od->is_upper = (type != OVL_PATH_LOWER);
	od->is_upper = OVL_TYPE_UPPER(type);
	od->cursor.is_cursor = true;
	od->cursor.is_cursor = true;
	file->private_data = od;
	file->private_data = od;


Loading