aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
commitb4a45f5fe8078bfc10837dbd5b98735058bc4698 (patch)
treedf6f13a27610a3ec7eb4a661448cd779a8f84c79 /fs/gfs2
parent01539ba2a706ab7d35fc0667dff919ade7f87d63 (diff)
parentb3e19d924b6eaf2ca7d22cba99a517c5171007b6 (diff)
Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin
* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin: (57 commits) fs: scale mntget/mntput fs: rename vfsmount counter helpers fs: implement faster dentry memcmp fs: prefetch inode data in dcache lookup fs: improve scalability of pseudo filesystems fs: dcache per-inode inode alias locking fs: dcache per-bucket dcache hash locking bit_spinlock: add required includes kernel: add bl_list xfs: provide simple rcu-walk ACL implementation btrfs: provide simple rcu-walk ACL implementation ext2,3,4: provide simple rcu-walk ACL implementation fs: provide simple rcu-walk generic_check_acl implementation fs: provide rcu-walk aware permission i_ops fs: rcu-walk aware d_revalidate method fs: cache optimise dentry and inode for rcu-walk fs: dcache reduce branches in lookup path fs: dcache remove d_mounted fs: fs_struct use seqlock fs: rcu-walk for path lookup ...
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/acl.c5
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/gfs2/dentry.c22
-rw-r--r--fs/gfs2/export.c4
-rw-r--r--fs/gfs2/file.c2
-rw-r--r--fs/gfs2/inode.c4
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/ops_fstype.c2
-rw-r--r--fs/gfs2/ops_inode.c20
-rw-r--r--fs/gfs2/super.c9
10 files changed, 48 insertions, 24 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 48171f4c943d..7118f1a780a9 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -75,11 +75,14 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
75 * Returns: errno 75 * Returns: errno
76 */ 76 */
77 77
78int gfs2_check_acl(struct inode *inode, int mask) 78int gfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
79{ 79{
80 struct posix_acl *acl; 80 struct posix_acl *acl;
81 int error; 81 int error;
82 82
83 if (flags & IPERM_FLAG_RCU)
84 return -ECHILD;
85
83 acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); 86 acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
84 if (IS_ERR(acl)) 87 if (IS_ERR(acl))
85 return PTR_ERR(acl); 88 return PTR_ERR(acl);
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index b522b0cb39ea..a93907c8159b 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -16,7 +16,7 @@
16#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" 16#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default"
17#define GFS2_ACL_MAX_ENTRIES 25 17#define GFS2_ACL_MAX_ENTRIES 25
18 18
19extern int gfs2_check_acl(struct inode *inode, int mask); 19extern int gfs2_check_acl(struct inode *inode, int mask, unsigned int);
20extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); 20extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode);
21extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); 21extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
22extern const struct xattr_handler gfs2_xattr_system_handler; 22extern const struct xattr_handler gfs2_xattr_system_handler;
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c
index 6798755b3858..4a456338b873 100644
--- a/fs/gfs2/dentry.c
+++ b/fs/gfs2/dentry.c
@@ -11,6 +11,7 @@
11#include <linux/completion.h> 11#include <linux/completion.h>
12#include <linux/buffer_head.h> 12#include <linux/buffer_head.h>
13#include <linux/gfs2_ondisk.h> 13#include <linux/gfs2_ondisk.h>
14#include <linux/namei.h>
14#include <linux/crc32.h> 15#include <linux/crc32.h>
15 16
16#include "gfs2.h" 17#include "gfs2.h"
@@ -34,15 +35,23 @@
34 35
35static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) 36static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
36{ 37{
37 struct dentry *parent = dget_parent(dentry); 38 struct dentry *parent;
38 struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode); 39 struct gfs2_sbd *sdp;
39 struct gfs2_inode *dip = GFS2_I(parent->d_inode); 40 struct gfs2_inode *dip;
40 struct inode *inode = dentry->d_inode; 41 struct inode *inode;
41 struct gfs2_holder d_gh; 42 struct gfs2_holder d_gh;
42 struct gfs2_inode *ip = NULL; 43 struct gfs2_inode *ip = NULL;
43 int error; 44 int error;
44 int had_lock = 0; 45 int had_lock = 0;
45 46
47 if (nd->flags & LOOKUP_RCU)
48 return -ECHILD;
49
50 parent = dget_parent(dentry);
51 sdp = GFS2_SB(parent->d_inode);
52 dip = GFS2_I(parent->d_inode);
53 inode = dentry->d_inode;
54
46 if (inode) { 55 if (inode) {
47 if (is_bad_inode(inode)) 56 if (is_bad_inode(inode))
48 goto invalid; 57 goto invalid;
@@ -100,13 +109,14 @@ fail:
100 return 0; 109 return 0;
101} 110}
102 111
103static int gfs2_dhash(struct dentry *dentry, struct qstr *str) 112static int gfs2_dhash(const struct dentry *dentry, const struct inode *inode,
113 struct qstr *str)
104{ 114{
105 str->hash = gfs2_disk_hash(str->name, str->len); 115 str->hash = gfs2_disk_hash(str->name, str->len);
106 return 0; 116 return 0;
107} 117}
108 118
109static int gfs2_dentry_delete(struct dentry *dentry) 119static int gfs2_dentry_delete(const struct dentry *dentry)
110{ 120{
111 struct gfs2_inode *ginode; 121 struct gfs2_inode *ginode;
112 122
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c
index 5ab3839dfcb9..97012ecff560 100644
--- a/fs/gfs2/export.c
+++ b/fs/gfs2/export.c
@@ -130,7 +130,7 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
130 130
131 dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1)); 131 dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
132 if (!IS_ERR(dentry)) 132 if (!IS_ERR(dentry))
133 dentry->d_op = &gfs2_dops; 133 d_set_d_op(dentry, &gfs2_dops);
134 return dentry; 134 return dentry;
135} 135}
136 136
@@ -158,7 +158,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
158out_inode: 158out_inode:
159 dentry = d_obtain_alias(inode); 159 dentry = d_obtain_alias(inode);
160 if (!IS_ERR(dentry)) 160 if (!IS_ERR(dentry))
161 dentry->d_op = &gfs2_dops; 161 d_set_d_op(dentry, &gfs2_dops);
162 return dentry; 162 return dentry;
163} 163}
164 164
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index aa996471ec5c..fca6689e12e6 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -241,7 +241,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
241 !capable(CAP_LINUX_IMMUTABLE)) 241 !capable(CAP_LINUX_IMMUTABLE))
242 goto out; 242 goto out;
243 if (!IS_IMMUTABLE(inode)) { 243 if (!IS_IMMUTABLE(inode)) {
244 error = gfs2_permission(inode, MAY_WRITE); 244 error = gfs2_permission(inode, MAY_WRITE, 0);
245 if (error) 245 if (error)
246 goto out; 246 goto out;
247 } 247 }
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 14e682dbe8bf..2232b3c780bd 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -509,7 +509,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
509 } 509 }
510 510
511 if (!is_root) { 511 if (!is_root) {
512 error = gfs2_permission(dir, MAY_EXEC); 512 error = gfs2_permission(dir, MAY_EXEC, 0);
513 if (error) 513 if (error)
514 goto out; 514 goto out;
515 } 515 }
@@ -539,7 +539,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
539{ 539{
540 int error; 540 int error;
541 541
542 error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC); 542 error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
543 if (error) 543 if (error)
544 return error; 544 return error;
545 545
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index d8499fadcc53..732a183efdb3 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -113,7 +113,7 @@ extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
113extern struct inode *gfs2_createi(struct gfs2_holder *ghs, 113extern struct inode *gfs2_createi(struct gfs2_holder *ghs,
114 const struct qstr *name, 114 const struct qstr *name,
115 unsigned int mode, dev_t dev); 115 unsigned int mode, dev_t dev);
116extern int gfs2_permission(struct inode *inode, int mask); 116extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags);
117extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); 117extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
118extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); 118extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
119extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); 119extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 3eb1393f7b81..2aeabd4218cc 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -440,7 +440,7 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr,
440 iput(inode); 440 iput(inode);
441 return -ENOMEM; 441 return -ENOMEM;
442 } 442 }
443 dentry->d_op = &gfs2_dops; 443 d_set_d_op(dentry, &gfs2_dops);
444 *dptr = dentry; 444 *dptr = dentry;
445 return 0; 445 return 0;
446} 446}
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 1db6b7343229..1501db4f0e6d 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -106,7 +106,7 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
106{ 106{
107 struct inode *inode = NULL; 107 struct inode *inode = NULL;
108 108
109 dentry->d_op = &gfs2_dops; 109 d_set_d_op(dentry, &gfs2_dops);
110 110
111 inode = gfs2_lookupi(dir, &dentry->d_name, 0); 111 inode = gfs2_lookupi(dir, &dentry->d_name, 0);
112 if (inode && IS_ERR(inode)) 112 if (inode && IS_ERR(inode))
@@ -166,7 +166,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
166 if (error) 166 if (error)
167 goto out_child; 167 goto out_child;
168 168
169 error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC); 169 error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0);
170 if (error) 170 if (error)
171 goto out_gunlock; 171 goto out_gunlock;
172 172
@@ -289,7 +289,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
289 if (IS_APPEND(&dip->i_inode)) 289 if (IS_APPEND(&dip->i_inode))
290 return -EPERM; 290 return -EPERM;
291 291
292 error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC); 292 error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
293 if (error) 293 if (error)
294 return error; 294 return error;
295 295
@@ -822,7 +822,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
822 } 822 }
823 } 823 }
824 } else { 824 } else {
825 error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC); 825 error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0);
826 if (error) 826 if (error)
827 goto out_gunlock; 827 goto out_gunlock;
828 828
@@ -857,7 +857,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
857 /* Check out the dir to be renamed */ 857 /* Check out the dir to be renamed */
858 858
859 if (dir_rename) { 859 if (dir_rename) {
860 error = gfs2_permission(odentry->d_inode, MAY_WRITE); 860 error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0);
861 if (error) 861 if (error)
862 goto out_gunlock; 862 goto out_gunlock;
863 } 863 }
@@ -1041,13 +1041,17 @@ static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1041 * Returns: errno 1041 * Returns: errno
1042 */ 1042 */
1043 1043
1044int gfs2_permission(struct inode *inode, int mask) 1044int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
1045{ 1045{
1046 struct gfs2_inode *ip = GFS2_I(inode); 1046 struct gfs2_inode *ip;
1047 struct gfs2_holder i_gh; 1047 struct gfs2_holder i_gh;
1048 int error; 1048 int error;
1049 int unlock = 0; 1049 int unlock = 0;
1050 1050
1051 if (flags & IPERM_FLAG_RCU)
1052 return -ECHILD;
1053
1054 ip = GFS2_I(inode);
1051 if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { 1055 if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
1052 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); 1056 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
1053 if (error) 1057 if (error)
@@ -1058,7 +1062,7 @@ int gfs2_permission(struct inode *inode, int mask)
1058 if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) 1062 if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
1059 error = -EACCES; 1063 error = -EACCES;
1060 else 1064 else
1061 error = generic_permission(inode, mask, gfs2_check_acl); 1065 error = generic_permission(inode, mask, flags, gfs2_check_acl);
1062 if (unlock) 1066 if (unlock)
1063 gfs2_glock_dq_uninit(&i_gh); 1067 gfs2_glock_dq_uninit(&i_gh);
1064 1068
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 2b2c4997430b..16c2ecac7eb7 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1405,11 +1405,18 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
1405 return &ip->i_inode; 1405 return &ip->i_inode;
1406} 1406}
1407 1407
1408static void gfs2_destroy_inode(struct inode *inode) 1408static void gfs2_i_callback(struct rcu_head *head)
1409{ 1409{
1410 struct inode *inode = container_of(head, struct inode, i_rcu);
1411 INIT_LIST_HEAD(&inode->i_dentry);
1410 kmem_cache_free(gfs2_inode_cachep, inode); 1412 kmem_cache_free(gfs2_inode_cachep, inode);
1411} 1413}
1412 1414
1415static void gfs2_destroy_inode(struct inode *inode)
1416{
1417 call_rcu(&inode->i_rcu, gfs2_i_callback);
1418}
1419
1413const struct super_operations gfs2_super_ops = { 1420const struct super_operations gfs2_super_ops = {
1414 .alloc_inode = gfs2_alloc_inode, 1421 .alloc_inode = gfs2_alloc_inode,
1415 .destroy_inode = gfs2_destroy_inode, 1422 .destroy_inode = gfs2_destroy_inode,