aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-05-03 06:00:05 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-05-09 10:49:38 -0400
commitedcc37a0478836b4a51eafb1bcec6a52708f681d (patch)
tree95294fa607420d760823401a6c6e7d9deb698bb1
parent5a6059c358d3b3004cb6b8562e3b049b1f8564f9 (diff)
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>
-rw-r--r--fs/reiserfs/super.c6
-rw-r--r--fs/reiserfs/xattr.c86
-rw-r--r--include/linux/reiserfs_xattr.h1
3 files changed, 41 insertions, 52 deletions
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 0ae6486d9046..d444fe0013a4 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1842,7 +1842,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1842 goto error; 1842 goto error;
1843 } 1843 }
1844 1844
1845 if ((errval = reiserfs_xattr_init(s, s->s_flags))) { 1845 if ((errval = reiserfs_lookup_privroot(s)) ||
1846 (errval = reiserfs_xattr_init(s, s->s_flags))) {
1846 dput(s->s_root); 1847 dput(s->s_root);
1847 s->s_root = NULL; 1848 s->s_root = NULL;
1848 goto error; 1849 goto error;
@@ -1855,7 +1856,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1855 reiserfs_info(s, "using 3.5.x disk format\n"); 1856 reiserfs_info(s, "using 3.5.x disk format\n");
1856 } 1857 }
1857 1858
1858 if ((errval = reiserfs_xattr_init(s, s->s_flags))) { 1859 if ((errval = reiserfs_lookup_privroot(s)) ||
1860 (errval = reiserfs_xattr_init(s, s->s_flags))) {
1859 dput(s->s_root); 1861 dput(s->s_root);
1860 s->s_root = NULL; 1862 s->s_root = NULL;
1861 goto error; 1863 goto error;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 31a3dbb120e1..2891f789f545 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -903,16 +903,19 @@ static int create_privroot(struct dentry *dentry)
903 WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); 903 WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
904 904
905 err = xattr_mkdir(inode, dentry, 0700); 905 err = xattr_mkdir(inode, dentry, 0700);
906 if (err) { 906 if (err || !dentry->d_inode) {
907 dput(dentry); 907 reiserfs_warning(dentry->d_sb, "jdm-20006",
908 dentry = NULL; 908 "xattrs/ACLs enabled and couldn't "
909 "find/create .reiserfs_priv. "
910 "Failing mount.");
911 return -EOPNOTSUPP;
909 } 912 }
910 913
911 if (dentry && dentry->d_inode) 914 dentry->d_inode->i_flags |= S_PRIVATE;
912 reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " 915 reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
913 "storage.\n", PRIVROOT_NAME); 916 "storage.\n", PRIVROOT_NAME);
914 917
915 return err; 918 return 0;
916} 919}
917 920
918static int xattr_mount_check(struct super_block *s) 921static int xattr_mount_check(struct super_block *s)
@@ -944,11 +947,9 @@ static int
944xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) 947xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
945{ 948{
946 struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; 949 struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
947 if (name->len == priv_root->d_name.len && 950 if (container_of(q1, struct dentry, d_name) == priv_root)
948 name->hash == priv_root->d_name.hash &&
949 !memcmp(name->name, priv_root->d_name.name, name->len)) {
950 return -ENOENT; 951 return -ENOENT;
951 } else if (q1->len == name->len && 952 if (q1->len == name->len &&
952 !memcmp(q1->name, name->name, name->len)) 953 !memcmp(q1->name, name->name, name->len))
953 return 0; 954 return 0;
954 return 1; 955 return 1;
@@ -958,6 +959,27 @@ static const struct dentry_operations xattr_lookup_poison_ops = {
958 .d_compare = xattr_lookup_poison, 959 .d_compare = xattr_lookup_poison,
959}; 960};
960 961
962int reiserfs_lookup_privroot(struct super_block *s)
963{
964 struct dentry *dentry;
965 int err = 0;
966
967 /* If we don't have the privroot located yet - go find it */
968 mutex_lock(&s->s_root->d_inode->i_mutex);
969 dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
970 strlen(PRIVROOT_NAME));
971 if (!IS_ERR(dentry)) {
972 REISERFS_SB(s)->priv_root = dentry;
973 s->s_root->d_op = &xattr_lookup_poison_ops;
974 if (dentry->d_inode)
975 dentry->d_inode->i_flags |= S_PRIVATE;
976 } else
977 err = PTR_ERR(dentry);
978 mutex_unlock(&s->s_root->d_inode->i_mutex);
979
980 return err;
981}
982
961/* We need to take a copy of the mount flags since things like 983/* We need to take a copy of the mount flags since things like
962 * MS_RDONLY don't get set until *after* we're called. 984 * MS_RDONLY don't get set until *after* we're called.
963 * mount_flags != mount_options */ 985 * mount_flags != mount_options */
@@ -969,48 +991,12 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
969 err = xattr_mount_check(s); 991 err = xattr_mount_check(s);
970 if (err) 992 if (err)
971 goto error; 993 goto error;
972#endif
973 994
974 /* If we don't have the privroot located yet - go find it */ 995 if (!REISERFS_SB(s)->priv_root->d_inode && !(mount_flags & MS_RDONLY)) {
975 if (!REISERFS_SB(s)->priv_root) { 996 mutex_lock(&s->s_root->d_inode->i_mutex);
976 struct dentry *dentry; 997 err = create_privroot(REISERFS_SB(s)->priv_root);
977 mutex_lock_nested(&s->s_root->d_inode->i_mutex, I_MUTEX_CHILD);
978 dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
979 strlen(PRIVROOT_NAME));
980 if (!IS_ERR(dentry)) {
981#ifdef CONFIG_REISERFS_FS_XATTR
982 if (!(mount_flags & MS_RDONLY) && !dentry->d_inode)
983 err = create_privroot(dentry);
984#endif
985 if (!dentry->d_inode) {
986 dput(dentry);
987 dentry = NULL;
988 }
989 } else
990 err = PTR_ERR(dentry);
991 mutex_unlock(&s->s_root->d_inode->i_mutex); 998 mutex_unlock(&s->s_root->d_inode->i_mutex);
992
993 if (!err && dentry) {
994 s->s_root->d_op = &xattr_lookup_poison_ops;
995 dentry->d_inode->i_flags |= S_PRIVATE;
996 REISERFS_SB(s)->priv_root = dentry;
997#ifdef CONFIG_REISERFS_FS_XATTR
998 /* xattrs are unavailable */
999 } else if (!(mount_flags & MS_RDONLY)) {
1000 /* If we're read-only it just means that the dir
1001 * hasn't been created. Not an error -- just no
1002 * xattrs on the fs. We'll check again if we
1003 * go read-write */
1004 reiserfs_warning(s, "jdm-20006",
1005 "xattrs/ACLs enabled and couldn't "
1006 "find/create .reiserfs_priv. "
1007 "Failing mount.");
1008 err = -EOPNOTSUPP;
1009#endif
1010 }
1011 } 999 }
1012
1013#ifdef CONFIG_REISERFS_FS_XATTR
1014 if (!err) 1000 if (!err)
1015 s->s_xattr = reiserfs_xattr_handlers; 1001 s->s_xattr = reiserfs_xattr_handlers;
1016 1002
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index dcae01e63e40..fea1a8e65bef 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -38,6 +38,7 @@ struct nameidata;
38int reiserfs_xattr_register_handlers(void) __init; 38int reiserfs_xattr_register_handlers(void) __init;
39void reiserfs_xattr_unregister_handlers(void); 39void reiserfs_xattr_unregister_handlers(void);
40int reiserfs_xattr_init(struct super_block *sb, int mount_flags); 40int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
41int reiserfs_lookup_privroot(struct super_block *sb);
41int reiserfs_delete_xattrs(struct inode *inode); 42int reiserfs_delete_xattrs(struct inode *inode);
42int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); 43int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
43 44