]> git.ipfire.org Git - ipfire-2.x.git/blame - 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.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / reiserfs-simplify-xattr-internal-file-lookups-opens.diff
CommitLineData
6a930a95
BS
1From: Jeff Mahoney <jeffm@suse.com>
2Subject: 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
8Signed-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);