1 From: Jeff Mahoney <jeffm@suse.com>
2 Subject: reiserfs: simplify xattr internal file lookups/opens
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.
8 Signed-off-by: Jeff Mahoney <jeffm@suse.com>
12 fs/reiserfs/xattr.c | 262 ++++++++++++++++++++++++++--------------------------
13 1 file changed, 135 insertions(+), 127 deletions(-)
15 --- a/fs/reiserfs/xattr.c
16 +++ b/fs/reiserfs/xattr.c
18 #include <net/checksum.h>
19 #include <linux/smp_lock.h>
20 #include <linux/stat.h>
21 +#include <linux/quotaops.h>
23 -#define FL_READONLY 128
24 -#define FL_DIR_SEM_HELD 256
25 #define PRIVROOT_NAME ".reiserfs_priv"
26 #define XAROOT_NAME "xattrs"
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.
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)
39 - struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root);
40 - struct dentry *xaroot;
41 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
43 + return dir->i_op->create(dir, dentry, mode, NULL);
46 - /* This needs to be created at mount-time */
48 - return ERR_PTR(-ENODATA);
49 +static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode)
51 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
53 + return dir->i_op->mkdir(dir, dentry, mode);
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);
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)
68 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
71 - xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME));
72 - if (IS_ERR(xaroot)) {
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);
84 +static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
87 + BUG_ON(!mutex_is_locked(&dir->i_mutex));
90 + mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
91 + dentry_unhash(dentry);
92 + error = dir->i_op->rmdir(dir, dentry);
94 + dentry->d_inode->i_flags |= S_DEAD;
95 + mutex_unlock(&dentry->d_inode->i_mutex);
104 +#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
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)
110 + struct dentry *dentry;
113 + dentry = lookup_one_len(name, parent, strlen(name));
114 + if (IS_ERR(dentry))
116 + else if (!dentry->d_inode) {
118 - if (flags == 0 || flags & XATTR_CREATE)
119 - err = privroot->d_inode->i_op->mkdir(privroot->d_inode,
122 + if (xattr_may_create(flags)) {
123 + mutex_lock_nested(&parent->d_inode->i_mutex,
125 + err = xattr_mkdir(parent->d_inode, dentry, 0700);
126 + mutex_unlock(&parent->d_inode->i_mutex);
131 - xaroot = ERR_PTR(err);
134 + dentry = ERR_PTR(err);
137 - REISERFS_SB(sb)->xattr_root = dget(xaroot);
140 - mutex_unlock(&privroot->d_inode->i_mutex);
146 +static struct dentry *open_xa_root(struct super_block *sb, int flags)
148 + struct dentry *privroot = REISERFS_SB(sb)->priv_root;
150 + return ERR_PTR(-ENODATA);
151 + return lookup_or_create_dir(privroot, XAROOT_NAME, flags);
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)
159 struct dentry *xaroot, *xadir;
162 - xaroot = get_xa_root(inode->i_sb, flags);
163 + xaroot = open_xa_root(inode->i_sb, flags);
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)) {
177 - if (!xadir->d_inode) {
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 */
184 - xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir,
189 - return ERR_PTR(err);
192 - if (!xadir->d_inode) {
195 - return ERR_PTR(-ENODATA);
199 + xadir = lookup_or_create_dir(xaroot, namebuf, flags);
206 @@ -302,13 +325,11 @@ static
207 int xattr_readdir(struct inode *inode, filldir_t filler, void *buf)
210 - mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
211 if (!IS_DEADDIR(inode)) {
213 res = __xattr_readdir(inode, buf, filler);
216 - mutex_unlock(&inode->i_mutex);
220 @@ -345,9 +366,7 @@ __reiserfs_xattr_del(struct dentry *xadi
224 - err = dir->i_op->unlink(dir, dentry);
227 + err = xattr_unlink(dir, dentry);
231 @@ -381,7 +400,7 @@ int reiserfs_delete_xattrs(struct inode
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);
240 @@ -391,25 +410,25 @@ int reiserfs_delete_xattrs(struct inode
245 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
246 err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir);
249 + mutex_unlock(&dir->d_inode->i_mutex);
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);
266 reiserfs_warning(inode->i_sb, "jdm-20006",
267 "Couldn't remove all entries in directory");
273 @@ -445,8 +464,11 @@ reiserfs_chown_xattrs_filler(void *buf,
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);
286 @@ -464,38 +486,31 @@ int reiserfs_chown_xattrs(struct inode *
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);
294 if (PTR_ERR(dir) != -ENODATA)
297 - } else if (!dir->d_inode) {
303 + } else if (!dir->d_inode)
306 attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
311 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
312 err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf);
318 - err = notify_change(dir, attrs);
321 + err = notify_change(dir, attrs);
322 + mutex_unlock(&dir->d_inode->i_mutex);
324 + attrs->ia_valid = ia_valid;
329 - attrs->ia_valid = ia_valid;
333 @@ -513,47 +528,35 @@ static struct dentry *get_xa_file_dentry
336 xadir = open_xa_dir(inode, flags);
337 - if (IS_ERR(xadir)) {
339 return ERR_CAST(xadir);
340 - } else if (xadir && !xadir->d_inode) {
342 - return ERR_PTR(-ENODATA);
345 xafile = lookup_one_len(name, xadir, strlen(name));
346 if (IS_ERR(xafile)) {
348 - return ERR_CAST(xafile);
349 + err = PTR_ERR(xafile);
353 - if (xafile->d_inode) { /* file exists */
354 - if (flags & XATTR_CREATE) {
359 - } else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
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))
372 + if (!xafile->d_inode) {
374 + if (xattr_may_create(flags)) {
375 + mutex_lock_nested(&xadir->d_inode->i_mutex,
377 + err = xattr_create(xadir->d_inode, xafile,
379 + mutex_unlock(&xadir->d_inode->i_mutex);
388 - xafile = ERR_PTR(err);
389 - else if (!xafile->d_inode) {
391 - xafile = ERR_PTR(-ENODATA);
393 + return ERR_PTR(err);
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);
405 @@ -692,7 +696,6 @@ reiserfs_xattr_set(struct inode *inode,
409 - mutex_unlock(&dentry->d_inode->i_mutex);
413 @@ -722,7 +725,7 @@ reiserfs_xattr_get(const struct inode *i
414 if (get_inode_sd_version(inode) == STAT_DATA_V1)
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);
422 @@ -806,13 +809,15 @@ int reiserfs_xattr_del(struct inode *ino
426 - dir = open_xa_dir(inode, FL_READONLY);
427 + dir = open_xa_dir(inode, XATTR_REPLACE);
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);
439 @@ -826,6 +831,7 @@ int reiserfs_xattr_del(struct inode *ino
441 /* Actual operations that are exported to VFS-land */
443 +static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char *);
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
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);
456 @@ -994,7 +1000,9 @@ ssize_t reiserfs_listxattr(struct dentry
458 REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir;
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);
466 @@ -1146,7 +1154,7 @@ static int create_privroot(struct dentry
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);