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

Commit edcc37a0 authored by Al Viro's avatar Al Viro
Browse files

Always lookup priv_root on reiserfs mount and keep it



... even if it's a negative dentry.  That way we can set ->d_op on
root before anyone could race with us.  Simplify d_compare(), while
we are at it.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 5a6059c3
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1842,7 +1842,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
			goto error;
		}

		if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
		if ((errval = reiserfs_lookup_privroot(s)) ||
		    (errval = reiserfs_xattr_init(s, s->s_flags))) {
			dput(s->s_root);
			s->s_root = NULL;
			goto error;
@@ -1855,7 +1856,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
			reiserfs_info(s, "using 3.5.x disk format\n");
		}

		if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
		if ((errval = reiserfs_lookup_privroot(s)) ||
		    (errval = reiserfs_xattr_init(s, s->s_flags))) {
			dput(s->s_root);
			s->s_root = NULL;
			goto error;
+36 −50
Original line number Diff line number Diff line
@@ -903,16 +903,19 @@ static int create_privroot(struct dentry *dentry)
	WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));

	err = xattr_mkdir(inode, dentry, 0700);
	if (err) {
		dput(dentry);
		dentry = NULL;
	if (err || !dentry->d_inode) {
		reiserfs_warning(dentry->d_sb, "jdm-20006",
				 "xattrs/ACLs enabled and couldn't "
				 "find/create .reiserfs_priv. "
				 "Failing mount.");
		return -EOPNOTSUPP;
	}

	if (dentry && dentry->d_inode)
	dentry->d_inode->i_flags |= S_PRIVATE;
	reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
		      "storage.\n", PRIVROOT_NAME);

	return err;
	return 0;
}

static int xattr_mount_check(struct super_block *s)
@@ -944,11 +947,9 @@ static int
xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
{
	struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
	if (name->len == priv_root->d_name.len &&
	    name->hash == priv_root->d_name.hash &&
	    !memcmp(name->name, priv_root->d_name.name, name->len)) {
	if (container_of(q1, struct dentry, d_name) == priv_root)
		return -ENOENT;
	} else if (q1->len == name->len &&
	if (q1->len == name->len &&
		   !memcmp(q1->name, name->name, name->len))
		return 0;
	return 1;
@@ -958,59 +959,44 @@ static const struct dentry_operations xattr_lookup_poison_ops = {
	.d_compare = xattr_lookup_poison,
};

/* We need to take a copy of the mount flags since things like
 * MS_RDONLY don't get set until *after* we're called.
 * mount_flags != mount_options */
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
int reiserfs_lookup_privroot(struct super_block *s)
{
	struct dentry *dentry;
	int err = 0;

#ifdef CONFIG_REISERFS_FS_XATTR
	err = xattr_mount_check(s);
	if (err)
		goto error;
#endif

	/* If we don't have the privroot located yet - go find it */
	if (!REISERFS_SB(s)->priv_root) {
		struct dentry *dentry;
		mutex_lock_nested(&s->s_root->d_inode->i_mutex, I_MUTEX_CHILD);
	mutex_lock(&s->s_root->d_inode->i_mutex);
	dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
				strlen(PRIVROOT_NAME));
	if (!IS_ERR(dentry)) {
#ifdef CONFIG_REISERFS_FS_XATTR
			if (!(mount_flags & MS_RDONLY) && !dentry->d_inode)
				err = create_privroot(dentry);
#endif
			if (!dentry->d_inode) {
				dput(dentry);
				dentry = NULL;
			}
		REISERFS_SB(s)->priv_root = dentry;
		s->s_root->d_op = &xattr_lookup_poison_ops;
		if (dentry->d_inode)
			dentry->d_inode->i_flags |= S_PRIVATE;
	} else
		err = PTR_ERR(dentry);
	mutex_unlock(&s->s_root->d_inode->i_mutex);

		if (!err && dentry) {
			s->s_root->d_op = &xattr_lookup_poison_ops;
			dentry->d_inode->i_flags |= S_PRIVATE;
			REISERFS_SB(s)->priv_root = dentry;
#ifdef CONFIG_REISERFS_FS_XATTR
		/* xattrs are unavailable */
		} else if (!(mount_flags & MS_RDONLY)) {
			/* If we're read-only it just means that the dir
			 * hasn't been created. Not an error -- just no
			 * xattrs on the fs. We'll check again if we
			 * go read-write */
			reiserfs_warning(s, "jdm-20006",
					 "xattrs/ACLs enabled and couldn't "
					 "find/create .reiserfs_priv. "
					 "Failing mount.");
			err = -EOPNOTSUPP;
#endif
		}
	return err;
}

/* We need to take a copy of the mount flags since things like
 * MS_RDONLY don't get set until *after* we're called.
 * mount_flags != mount_options */
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
{
	int err = 0;

#ifdef CONFIG_REISERFS_FS_XATTR
	err = xattr_mount_check(s);
	if (err)
		goto error;

	if (!REISERFS_SB(s)->priv_root->d_inode && !(mount_flags & MS_RDONLY)) {
		mutex_lock(&s->s_root->d_inode->i_mutex);
		err = create_privroot(REISERFS_SB(s)->priv_root);
		mutex_unlock(&s->s_root->d_inode->i_mutex);
	}
	if (!err)
		s->s_xattr = reiserfs_xattr_handlers;

+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ struct nameidata;
int reiserfs_xattr_register_handlers(void) __init;
void reiserfs_xattr_unregister_handlers(void);
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
int reiserfs_lookup_privroot(struct super_block *sb);
int reiserfs_delete_xattrs(struct inode *inode);
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);