aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2007-04-23 17:41:17 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-24 11:23:09 -0400
commit9b7f375505f5611efb562065b57814b28a81abc3 (patch)
tree3f51e49ca5b70081bf15f4ce9d7ddbd289917932
parent1a641fceb6bb6b0930db1aadbda1aaf5711d65d6 (diff)
reiserfs: fix xattr root locking/refcount bug
The listxattr() and getxattr() operations are only protected by a read lock. As a result, if either of these operations run in parallel, a race condition exists where the xattr_root will end up being cached twice, which results in the leaking of a reference and a BUG() on umount. This patch refactors get_xa_root(), __get_xa_root(), and create_xa_root(), into one get_xa_root() function that takes the appropriate locking around the entire critical section. Reported, diagnosed and tested by Andrea Righi <a.righi@cineca.it> Signed-off-by: Jeff Mahoney <jeffm@suse.com> Cc: Andrea Righi <a.righi@cineca.it> Cc: "Vladimir V. Saveliev" <vs@namesys.com> Cc: Edward Shishkin <edward@namesys.com> Cc: Alex Zarochentsev <zam@namesys.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/reiserfs/xattr.c92
1 files changed, 24 insertions, 68 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index f01389fd162e..c8178b7b9212 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -54,82 +54,48 @@
54static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char 54static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
55 *prefix); 55 *prefix);
56 56
57static struct dentry *create_xa_root(struct super_block *sb) 57/* Returns the dentry referring to the root of the extended attribute
58 * directory tree. If it has already been retrieved, it is used. If it
59 * hasn't been created and the flags indicate creation is allowed, we
60 * attempt to create it. On error, we return a pointer-encoded error.
61 */
62static struct dentry *get_xa_root(struct super_block *sb, int flags)
58{ 63{
59 struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); 64 struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root);
60 struct dentry *xaroot; 65 struct dentry *xaroot;
61 66
62 /* This needs to be created at mount-time */ 67 /* This needs to be created at mount-time */
63 if (!privroot) 68 if (!privroot)
64 return ERR_PTR(-EOPNOTSUPP); 69 return ERR_PTR(-ENODATA);
65 70
66 xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); 71 mutex_lock(&privroot->d_inode->i_mutex);
67 if (IS_ERR(xaroot)) { 72 if (REISERFS_SB(sb)->xattr_root) {
73 xaroot = dget(REISERFS_SB(sb)->xattr_root);
68 goto out; 74 goto out;
69 } else if (!xaroot->d_inode) {
70 int err;
71 mutex_lock(&privroot->d_inode->i_mutex);
72 err =
73 privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot,
74 0700);
75 mutex_unlock(&privroot->d_inode->i_mutex);
76
77 if (err) {
78 dput(xaroot);
79 dput(privroot);
80 return ERR_PTR(err);
81 }
82 REISERFS_SB(sb)->xattr_root = dget(xaroot);
83 } 75 }
84 76
85 out:
86 dput(privroot);
87 return xaroot;
88}
89
90/* This will return a dentry, or error, refering to the xa root directory.
91 * If the xa root doesn't exist yet, the dentry will be returned without
92 * an associated inode. This dentry can be used with ->mkdir to create
93 * the xa directory. */
94static struct dentry *__get_xa_root(struct super_block *s)
95{
96 struct dentry *privroot = dget(REISERFS_SB(s)->priv_root);
97 struct dentry *xaroot = NULL;
98
99 if (IS_ERR(privroot) || !privroot)
100 return privroot;
101
102 xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); 77 xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME));
103 if (IS_ERR(xaroot)) { 78 if (IS_ERR(xaroot)) {
104 goto out; 79 goto out;
105 } else if (!xaroot->d_inode) { 80 } else if (!xaroot->d_inode) {
106 dput(xaroot); 81 int err = -ENODATA;
107 xaroot = NULL; 82 if (flags == 0 || flags & XATTR_CREATE)
108 goto out; 83 err = privroot->d_inode->i_op->mkdir(privroot->d_inode,
84 xaroot, 0700);
85 if (err) {
86 dput(xaroot);
87 xaroot = ERR_PTR(err);
88 goto out;
89 }
109 } 90 }
110 91 REISERFS_SB(sb)->xattr_root = dget(xaroot);
111 REISERFS_SB(s)->xattr_root = dget(xaroot);
112 92
113 out: 93 out:
94 mutex_unlock(&privroot->d_inode->i_mutex);
114 dput(privroot); 95 dput(privroot);
115 return xaroot; 96 return xaroot;
116} 97}
117 98
118/* Returns the dentry (or NULL) referring to the root of the extended
119 * attribute directory tree. If it has already been retrieved, it is used.
120 * Otherwise, we attempt to retrieve it from disk. It may also return
121 * a pointer-encoded error.
122 */
123static inline struct dentry *get_xa_root(struct super_block *s)
124{
125 struct dentry *dentry = dget(REISERFS_SB(s)->xattr_root);
126
127 if (!dentry)
128 dentry = __get_xa_root(s);
129
130 return dentry;
131}
132
133/* Opens the directory corresponding to the inode's extended attribute store. 99/* Opens the directory corresponding to the inode's extended attribute store.
134 * If flags allow, the tree to the directory may be created. If creation is 100 * If flags allow, the tree to the directory may be created. If creation is
135 * prohibited, -ENODATA is returned. */ 101 * prohibited, -ENODATA is returned. */
@@ -138,21 +104,11 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)
138 struct dentry *xaroot, *xadir; 104 struct dentry *xaroot, *xadir;
139 char namebuf[17]; 105 char namebuf[17];
140 106
141 xaroot = get_xa_root(inode->i_sb); 107 xaroot = get_xa_root(inode->i_sb, flags);
142 if (IS_ERR(xaroot)) { 108 if (IS_ERR(xaroot))
143 return xaroot; 109 return xaroot;
144 } else if (!xaroot) {
145 if (flags == 0 || flags & XATTR_CREATE) {
146 xaroot = create_xa_root(inode->i_sb);
147 if (IS_ERR(xaroot))
148 return xaroot;
149 }
150 if (!xaroot)
151 return ERR_PTR(-ENODATA);
152 }
153 110
154 /* ok, we have xaroot open */ 111 /* ok, we have xaroot open */
155
156 snprintf(namebuf, sizeof(namebuf), "%X.%X", 112 snprintf(namebuf, sizeof(namebuf), "%X.%X",
157 le32_to_cpu(INODE_PKEY(inode)->k_objectid), 113 le32_to_cpu(INODE_PKEY(inode)->k_objectid),
158 inode->i_generation); 114 inode->i_generation);
@@ -821,7 +777,7 @@ int reiserfs_delete_xattrs(struct inode *inode)
821 777
822 /* Leftovers besides . and .. -- that's not good. */ 778 /* Leftovers besides . and .. -- that's not good. */
823 if (dir->d_inode->i_nlink <= 2) { 779 if (dir->d_inode->i_nlink <= 2) {
824 root = get_xa_root(inode->i_sb); 780 root = get_xa_root(inode->i_sb, XATTR_REPLACE);
825 reiserfs_write_lock_xattrs(inode->i_sb); 781 reiserfs_write_lock_xattrs(inode->i_sb);
826 err = vfs_rmdir(root->d_inode, dir); 782 err = vfs_rmdir(root->d_inode, dir);
827 reiserfs_write_unlock_xattrs(inode->i_sb); 783 reiserfs_write_unlock_xattrs(inode->i_sb);