diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-05-03 06:00:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-05-09 10:49:38 -0400 |
commit | edcc37a0478836b4a51eafb1bcec6a52708f681d (patch) | |
tree | 95294fa607420d760823401a6c6e7d9deb698bb1 | |
parent | 5a6059c358d3b3004cb6b8562e3b049b1f8564f9 (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.c | 6 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 86 | ||||
-rw-r--r-- | include/linux/reiserfs_xattr.h | 1 |
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 | ||
918 | static int xattr_mount_check(struct super_block *s) | 921 | static int xattr_mount_check(struct super_block *s) |
@@ -944,11 +947,9 @@ static int | |||
944 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | 947 | xattr_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 | ||
962 | int 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; | |||
38 | int reiserfs_xattr_register_handlers(void) __init; | 38 | int reiserfs_xattr_register_handlers(void) __init; |
39 | void reiserfs_xattr_unregister_handlers(void); | 39 | void reiserfs_xattr_unregister_handlers(void); |
40 | int reiserfs_xattr_init(struct super_block *sb, int mount_flags); | 40 | int reiserfs_xattr_init(struct super_block *sb, int mount_flags); |
41 | int reiserfs_lookup_privroot(struct super_block *sb); | ||
41 | int reiserfs_delete_xattrs(struct inode *inode); | 42 | int reiserfs_delete_xattrs(struct inode *inode); |
42 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); | 43 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); |
43 | 44 | ||