]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/reiserfs-simplify-xattr-internal-file-lookups-opens.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / reiserfs-simplify-xattr-internal-file-lookups-opens.diff
1 From: Jeff Mahoney <jeffm@suse.com>
2 Subject: reiserfs: simplify xattr internal file lookups/opens
3
4 The xattr file open/lookup code is needlessly complex. We can use vfs-level
5 operations to perform the same work, and also simplify the locking
6 constraints. The locking advantages will be exploited in future patches.
7
8 Signed-off-by: Jeff Mahoney <jeffm@suse.com>
9
10 ---
11
12 fs/reiserfs/xattr.c | 262 ++++++++++++++++++++++++++--------------------------
13 1 file changed, 135 insertions(+), 127 deletions(-)
14
15 --- a/fs/reiserfs/xattr.c
16 +++ b/fs/reiserfs/xattr.c
17 @@ -44,100 +44,123 @@
18 #include <net/checksum.h>
19 #include <linux/smp_lock.h>
20 #include <linux/stat.h>
21 +#include <linux/quotaops.h>
22
23 -#define FL_READONLY 128
24 -#define FL_DIR_SEM_HELD 256
25 #define PRIVROOT_NAME ".reiserfs_priv"
26 #define XAROOT_NAME "xattrs"
27
28 -/* Returns the dentry referring to the root of the extended attribute
29 - * directory tree. If it has already been retrieved, it is used. If it
30 - * hasn't been created and the flags indicate creation is allowed, we
31 - * attempt to create it. On error, we return a pointer-encoded error.
32 - */
33 -static struct dentry *get_xa_root(struct super_block *sb, int flags)
34 +/* Helpers for inode ops. We do this so that we don't have all the VFS
35 + * overhead and also for proper i_mutex annotation.
36 + * dir->i_mutex must be held for all of them. */
37 +static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)
38 {
39 - struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root);
40 - struct dentry *xaroot;
41 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
42 + DQUOT_INIT(dir);
43 + return dir->i_op->create(dir, dentry, mode, NULL);
44 +}
45
46 - /* This needs to be created at mount-time */
47 - if (!privroot)
48 - return ERR_PTR(-ENODATA);
49 +static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode)
50 +{
51 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
52 + DQUOT_INIT(dir);
53 + return dir->i_op->mkdir(dir, dentry, mode);
54 +}
55
56 - mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR);
57 - if (REISERFS_SB(sb)->xattr_root) {
58 - xaroot = dget(REISERFS_SB(sb)->xattr_root);
59 - goto out;
60 - }
61 +/* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr
62 + * mutation ops aren't called during rename or splace, which are the
63 + * only other users of I_MUTEX_CHILD. It violates the ordering, but that's
64 + * better than allocating another subclass just for this code. */
65 +static int xattr_unlink(struct inode *dir, struct dentry *dentry)
66 +{
67 + int error;
68 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
69 + DQUOT_INIT(dir);
70
71 - xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME));
72 - if (IS_ERR(xaroot)) {
73 - goto out;
74 - } else if (!xaroot->d_inode) {
75 + mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
76 + error = dir->i_op->unlink(dir, dentry);
77 + mutex_unlock(&dentry->d_inode->i_mutex);
78 +
79 + if (!error)
80 + d_delete(dentry);
81 + return error;
82 +}
83 +
84 +static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
85 +{
86 + int error;
87 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
88 + DQUOT_INIT(dir);
89 +
90 + mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
91 + dentry_unhash(dentry);
92 + error = dir->i_op->rmdir(dir, dentry);
93 + if (!error)
94 + dentry->d_inode->i_flags |= S_DEAD;
95 + mutex_unlock(&dentry->d_inode->i_mutex);
96 + if (!error)
97 + d_delete(dentry);
98 + dput(dentry);
99 +
100 + return error;
101 +}
102 +
103 +
104 +#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
105 +
106 +/* Returns and possibly creates the xattr dir. */
107 +static struct dentry *lookup_or_create_dir(struct dentry *parent,
108 + const char *name, int flags)
109 +{
110 + struct dentry *dentry;
111 + BUG_ON(!parent);
112 +
113 + dentry = lookup_one_len(name, parent, strlen(name));
114 + if (IS_ERR(dentry))
115 + return dentry;
116 + else if (!dentry->d_inode) {
117 int err = -ENODATA;
118 - if (flags == 0 || flags & XATTR_CREATE)
119 - err = privroot->d_inode->i_op->mkdir(privroot->d_inode,
120 - xaroot, 0700);
121 +
122 + if (xattr_may_create(flags)) {
123 + mutex_lock_nested(&parent->d_inode->i_mutex,
124 + I_MUTEX_XATTR);
125 + err = xattr_mkdir(parent->d_inode, dentry, 0700);
126 + mutex_unlock(&parent->d_inode->i_mutex);
127 + }
128 +
129 if (err) {
130 - dput(xaroot);
131 - xaroot = ERR_PTR(err);
132 - goto out;
133 + dput(dentry);
134 + dentry = ERR_PTR(err);
135 }
136 }
137 - REISERFS_SB(sb)->xattr_root = dget(xaroot);
138
139 - out:
140 - mutex_unlock(&privroot->d_inode->i_mutex);
141 - dput(privroot);
142 - return xaroot;
143 + return dentry;
144 +}
145 +
146 +static struct dentry *open_xa_root(struct super_block *sb, int flags)
147 +{
148 + struct dentry *privroot = REISERFS_SB(sb)->priv_root;
149 + if (!privroot)
150 + return ERR_PTR(-ENODATA);
151 + return lookup_or_create_dir(privroot, XAROOT_NAME, flags);
152 }
153
154 -/* Opens the directory corresponding to the inode's extended attribute store.
155 - * If flags allow, the tree to the directory may be created. If creation is
156 - * prohibited, -ENODATA is returned. */
157 static struct dentry *open_xa_dir(const struct inode *inode, int flags)
158 {
159 struct dentry *xaroot, *xadir;
160 char namebuf[17];
161
162 - xaroot = get_xa_root(inode->i_sb, flags);
163 + xaroot = open_xa_root(inode->i_sb, flags);
164 if (IS_ERR(xaroot))
165 return xaroot;
166
167 - /* ok, we have xaroot open */
168 snprintf(namebuf, sizeof(namebuf), "%X.%X",
169 le32_to_cpu(INODE_PKEY(inode)->k_objectid),
170 inode->i_generation);
171 - xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
172 - if (IS_ERR(xadir)) {
173 - dput(xaroot);
174 - return xadir;
175 - }
176 -
177 - if (!xadir->d_inode) {
178 - int err;
179 - if (flags == 0 || flags & XATTR_CREATE) {
180 - /* Although there is nothing else trying to create this directory,
181 - * another directory with the same hash may be created, so we need
182 - * to protect against that */
183 - err =
184 - xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir,
185 - 0700);
186 - if (err) {
187 - dput(xaroot);
188 - dput(xadir);
189 - return ERR_PTR(err);
190 - }
191 - }
192 - if (!xadir->d_inode) {
193 - dput(xaroot);
194 - dput(xadir);
195 - return ERR_PTR(-ENODATA);
196 - }
197 - }
198
199 + xadir = lookup_or_create_dir(xaroot, namebuf, flags);
200 dput(xaroot);
201 return xadir;
202 +
203 }
204
205 /*
206 @@ -302,13 +325,11 @@ static
207 int xattr_readdir(struct inode *inode, filldir_t filler, void *buf)
208 {
209 int res = -ENOENT;
210 - mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
211 if (!IS_DEADDIR(inode)) {
212 lock_kernel();
213 res = __xattr_readdir(inode, buf, filler);
214 unlock_kernel();
215 }
216 - mutex_unlock(&inode->i_mutex);
217 return res;
218 }
219
220 @@ -345,9 +366,7 @@ __reiserfs_xattr_del(struct dentry *xadi
221 return -EIO;
222 }
223
224 - err = dir->i_op->unlink(dir, dentry);
225 - if (!err)
226 - d_delete(dentry);
227 + err = xattr_unlink(dir, dentry);
228
229 out_file:
230 dput(dentry);
231 @@ -381,7 +400,7 @@ int reiserfs_delete_xattrs(struct inode
232 return 0;
233
234 reiserfs_read_lock_xattrs(inode->i_sb);
235 - dir = open_xa_dir(inode, FL_READONLY);
236 + dir = open_xa_dir(inode, XATTR_REPLACE);
237 reiserfs_read_unlock_xattrs(inode->i_sb);
238 if (IS_ERR(dir)) {
239 err = PTR_ERR(dir);
240 @@ -391,25 +410,25 @@ int reiserfs_delete_xattrs(struct inode
241 return 0;
242 }
243
244 - lock_kernel();
245 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
246 err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir);
247 - if (err) {
248 - unlock_kernel();
249 + mutex_unlock(&dir->d_inode->i_mutex);
250 + if (err)
251 goto out_dir;
252 - }
253
254 /* Leftovers besides . and .. -- that's not good. */
255 if (dir->d_inode->i_nlink <= 2) {
256 - root = get_xa_root(inode->i_sb, XATTR_REPLACE);
257 + root = open_xa_root(inode->i_sb, XATTR_REPLACE);
258 reiserfs_write_lock_xattrs(inode->i_sb);
259 - err = vfs_rmdir(root->d_inode, dir);
260 + mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_XATTR);
261 + err = xattr_rmdir(root->d_inode, dir);
262 + mutex_unlock(&root->d_inode->i_mutex);
263 reiserfs_write_unlock_xattrs(inode->i_sb);
264 dput(root);
265 } else {
266 reiserfs_warning(inode->i_sb, "jdm-20006",
267 "Couldn't remove all entries in directory");
268 }
269 - unlock_kernel();
270
271 out_dir:
272 dput(dir);
273 @@ -445,8 +464,11 @@ reiserfs_chown_xattrs_filler(void *buf,
274 return -ENODATA;
275 }
276
277 - if (!S_ISDIR(xafile->d_inode->i_mode))
278 + if (!S_ISDIR(xafile->d_inode->i_mode)) {
279 + mutex_lock_nested(&xafile->d_inode->i_mutex, I_MUTEX_CHILD);
280 err = notify_change(xafile, attrs);
281 + mutex_unlock(&xafile->d_inode->i_mutex);
282 + }
283 dput(xafile);
284
285 return err;
286 @@ -464,38 +486,31 @@ int reiserfs_chown_xattrs(struct inode *
287 return 0;
288
289 reiserfs_read_lock_xattrs(inode->i_sb);
290 - dir = open_xa_dir(inode, FL_READONLY);
291 + dir = open_xa_dir(inode, XATTR_REPLACE);
292 reiserfs_read_unlock_xattrs(inode->i_sb);
293 if (IS_ERR(dir)) {
294 if (PTR_ERR(dir) != -ENODATA)
295 err = PTR_ERR(dir);
296 goto out;
297 - } else if (!dir->d_inode) {
298 - dput(dir);
299 - goto out;
300 - }
301 -
302 - lock_kernel();
303 + } else if (!dir->d_inode)
304 + goto out_dir;
305
306 attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
307 buf.xadir = dir;
308 buf.attrs = attrs;
309 buf.inode = inode;
310
311 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
312 err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf);
313 - if (err) {
314 - unlock_kernel();
315 - goto out_dir;
316 - }
317
318 - err = notify_change(dir, attrs);
319 - unlock_kernel();
320 + if (!err)
321 + err = notify_change(dir, attrs);
322 + mutex_unlock(&dir->d_inode->i_mutex);
323
324 + attrs->ia_valid = ia_valid;
325 out_dir:
326 dput(dir);
327 -
328 out:
329 - attrs->ia_valid = ia_valid;
330 return err;
331 }
332
333 @@ -513,47 +528,35 @@ static struct dentry *get_xa_file_dentry
334 int err = 0;
335
336 xadir = open_xa_dir(inode, flags);
337 - if (IS_ERR(xadir)) {
338 + if (IS_ERR(xadir))
339 return ERR_CAST(xadir);
340 - } else if (xadir && !xadir->d_inode) {
341 - dput(xadir);
342 - return ERR_PTR(-ENODATA);
343 - }
344
345 xafile = lookup_one_len(name, xadir, strlen(name));
346 if (IS_ERR(xafile)) {
347 - dput(xadir);
348 - return ERR_CAST(xafile);
349 + err = PTR_ERR(xafile);
350 + goto out;
351 }
352
353 - if (xafile->d_inode) { /* file exists */
354 - if (flags & XATTR_CREATE) {
355 - err = -EEXIST;
356 - dput(xafile);
357 - goto out;
358 - }
359 - } else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
360 - goto out;
361 - } else {
362 - /* inode->i_mutex is down, so nothing else can try to create
363 - * the same xattr */
364 - err = xadir->d_inode->i_op->create(xadir->d_inode, xafile,
365 - 0700 | S_IFREG, NULL);
366 + if (xafile->d_inode && (flags & XATTR_CREATE))
367 + err = -EEXIST;
368
369 - if (err) {
370 - dput(xafile);
371 - goto out;
372 + if (!xafile->d_inode) {
373 + err = -ENODATA;
374 + if (xattr_may_create(flags)) {
375 + mutex_lock_nested(&xadir->d_inode->i_mutex,
376 + I_MUTEX_XATTR);
377 + err = xattr_create(xadir->d_inode, xafile,
378 + 0700|S_IFREG);
379 + mutex_unlock(&xadir->d_inode->i_mutex);
380 }
381 }
382
383 + if (err)
384 + dput(xafile);
385 out:
386 dput(xadir);
387 if (err)
388 - xafile = ERR_PTR(err);
389 - else if (!xafile->d_inode) {
390 - dput(xafile);
391 - xafile = ERR_PTR(-ENODATA);
392 - }
393 + return ERR_PTR(err);
394 return xafile;
395 }
396
397 @@ -633,6 +636,7 @@ reiserfs_xattr_set(struct inode *inode,
398 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
399 mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
400 err = notify_change(dentry, &newattrs);
401 + mutex_unlock(&dentry->d_inode->i_mutex);
402 if (err)
403 goto out_filp;
404
405 @@ -692,7 +696,6 @@ reiserfs_xattr_set(struct inode *inode,
406 }
407
408 out_filp:
409 - mutex_unlock(&dentry->d_inode->i_mutex);
410 dput(dentry);
411
412 out:
413 @@ -722,7 +725,7 @@ reiserfs_xattr_get(const struct inode *i
414 if (get_inode_sd_version(inode) == STAT_DATA_V1)
415 return -EOPNOTSUPP;
416
417 - dentry = get_xa_file_dentry(inode, name, FL_READONLY);
418 + dentry = get_xa_file_dentry(inode, name, XATTR_REPLACE);
419 if (IS_ERR(dentry)) {
420 err = PTR_ERR(dentry);
421 goto out;
422 @@ -806,13 +809,15 @@ int reiserfs_xattr_del(struct inode *ino
423 struct dentry *dir;
424 int err;
425
426 - dir = open_xa_dir(inode, FL_READONLY);
427 + dir = open_xa_dir(inode, XATTR_REPLACE);
428 if (IS_ERR(dir)) {
429 err = PTR_ERR(dir);
430 goto out;
431 }
432
433 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
434 err = __reiserfs_xattr_del(dir, name, strlen(name));
435 + mutex_unlock(&dir->d_inode->i_mutex);
436 dput(dir);
437
438 if (!err) {
439 @@ -826,6 +831,7 @@ int reiserfs_xattr_del(struct inode *ino
440
441 /* Actual operations that are exported to VFS-land */
442
443 +static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *);
444 /*
445 * Inode operation getxattr()
446 * Preliminary locking: we down dentry->d_inode->i_mutex
447 @@ -978,7 +984,7 @@ ssize_t reiserfs_listxattr(struct dentry
448
449 reiserfs_read_lock_xattr_i(dentry->d_inode);
450 reiserfs_read_lock_xattrs(dentry->d_sb);
451 - dir = open_xa_dir(dentry->d_inode, FL_READONLY);
452 + dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE);
453 reiserfs_read_unlock_xattrs(dentry->d_sb);
454 if (IS_ERR(dir)) {
455 err = PTR_ERR(dir);
456 @@ -994,7 +1000,9 @@ ssize_t reiserfs_listxattr(struct dentry
457
458 REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir;
459
460 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
461 err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf);
462 + mutex_unlock(&dir->d_inode->i_mutex);
463 if (err)
464 goto out_dir;
465
466 @@ -1146,7 +1154,7 @@ static int create_privroot(struct dentry
467 int err;
468 struct inode *inode = dentry->d_parent->d_inode;
469 mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
470 - err = inode->i_op->mkdir(inode, dentry, 0700);
471 + err = xattr_mkdir(inode, dentry, 0700);
472 mutex_unlock(&inode->i_mutex);
473 if (err) {
474 dput(dentry);