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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
5a6059c358
Коммит
edcc37a047
|
@ -1842,7 +1842,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
||||||
goto error;
|
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);
|
dput(s->s_root);
|
||||||
s->s_root = NULL;
|
s->s_root = NULL;
|
||||||
goto error;
|
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");
|
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);
|
dput(s->s_root);
|
||||||
s->s_root = NULL;
|
s->s_root = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -903,16 +903,19 @@ static int create_privroot(struct dentry *dentry)
|
||||||
WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
|
WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
|
||||||
|
|
||||||
err = xattr_mkdir(inode, dentry, 0700);
|
err = xattr_mkdir(inode, dentry, 0700);
|
||||||
if (err) {
|
if (err || !dentry->d_inode) {
|
||||||
dput(dentry);
|
reiserfs_warning(dentry->d_sb, "jdm-20006",
|
||||||
dentry = NULL;
|
"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 "
|
reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
|
||||||
"storage.\n", PRIVROOT_NAME);
|
"storage.\n", PRIVROOT_NAME);
|
||||||
|
|
||||||
return err;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xattr_mount_check(struct super_block *s)
|
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)
|
xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
|
||||||
{
|
{
|
||||||
struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
|
struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
|
||||||
if (name->len == priv_root->d_name.len &&
|
if (container_of(q1, struct dentry, d_name) == priv_root)
|
||||||
name->hash == priv_root->d_name.hash &&
|
|
||||||
!memcmp(name->name, priv_root->d_name.name, name->len)) {
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
} else if (q1->len == name->len &&
|
if (q1->len == name->len &&
|
||||||
!memcmp(q1->name, name->name, name->len))
|
!memcmp(q1->name, name->name, name->len))
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -958,6 +959,27 @@ static const struct dentry_operations xattr_lookup_poison_ops = {
|
||||||
.d_compare = xattr_lookup_poison,
|
.d_compare = xattr_lookup_poison,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int reiserfs_lookup_privroot(struct super_block *s)
|
||||||
|
{
|
||||||
|
struct dentry *dentry;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
/* If we don't have the privroot located yet - go find it */
|
||||||
|
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)) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to take a copy of the mount flags since things like
|
/* We need to take a copy of the mount flags since things like
|
||||||
* MS_RDONLY don't get set until *after* we're called.
|
* MS_RDONLY don't get set until *after* we're called.
|
||||||
* mount_flags != mount_options */
|
* mount_flags != mount_options */
|
||||||
|
@ -969,48 +991,12 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
|
||||||
err = xattr_mount_check(s);
|
err = xattr_mount_check(s);
|
||||||
if (err)
|
if (err)
|
||||||
goto error;
|
goto error;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we don't have the privroot located yet - go find it */
|
if (!REISERFS_SB(s)->priv_root->d_inode && !(mount_flags & MS_RDONLY)) {
|
||||||
if (!REISERFS_SB(s)->priv_root) {
|
mutex_lock(&s->s_root->d_inode->i_mutex);
|
||||||
struct dentry *dentry;
|
err = create_privroot(REISERFS_SB(s)->priv_root);
|
||||||
mutex_lock_nested(&s->s_root->d_inode->i_mutex, I_MUTEX_CHILD);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
err = PTR_ERR(dentry);
|
|
||||||
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
|
||||||
if (!err)
|
if (!err)
|
||||||
s->s_xattr = reiserfs_xattr_handlers;
|
s->s_xattr = reiserfs_xattr_handlers;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct nameidata;
|
||||||
int reiserfs_xattr_register_handlers(void) __init;
|
int reiserfs_xattr_register_handlers(void) __init;
|
||||||
void reiserfs_xattr_unregister_handlers(void);
|
void reiserfs_xattr_unregister_handlers(void);
|
||||||
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
|
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_delete_xattrs(struct inode *inode);
|
||||||
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
|
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче