diff options
author | Josef Bacik <josef@redhat.com> | 2011-05-27 12:06:11 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-07-11 09:58:45 -0400 |
commit | fa09200b8334f9a6af3f656edae924a98d85630f (patch) | |
tree | 9213ac48212f70d86fb60834beb464d68be332ba /fs/btrfs/xattr.c | |
parent | 149e2d76b4886c4c7ff5e077646a8ba3563c8026 (diff) |
Btrfs: try to only do one btrfs_search_slot in do_setxattr
I've been watching how many btrfs_search_slot()'s we do and I noticed that when
we create a file with selinux enabled we were doing 2 each time we initialize
the security context. That's because we lookup the xattr first so we can delete
it if we're setting a new value to an existing xattr. But in the create case we
don't have any xattrs, so it is completely useless to have the extra lookup. So
re-arrange things so that we only lookup first if we specifically have
XATTR_REPLACE. That way in the basic case we only do 1 search, and in the more
complicated case we do the normal 2 lookups. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/xattr.c')
-rw-r--r-- | fs/btrfs/xattr.c | 66 |
1 files changed, 40 insertions, 26 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 5366fe452ab0..d733b9cfea34 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -102,43 +102,57 @@ static int do_setxattr(struct btrfs_trans_handle *trans, | |||
102 | if (!path) | 102 | if (!path) |
103 | return -ENOMEM; | 103 | return -ENOMEM; |
104 | 104 | ||
105 | /* first lets see if we already have this xattr */ | 105 | if (flags & XATTR_REPLACE) { |
106 | di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name, | 106 | di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name, |
107 | strlen(name), -1); | 107 | name_len, -1); |
108 | if (IS_ERR(di)) { | 108 | if (IS_ERR(di)) { |
109 | ret = PTR_ERR(di); | 109 | ret = PTR_ERR(di); |
110 | goto out; | 110 | goto out; |
111 | } | 111 | } else if (!di) { |
112 | 112 | ret = -ENODATA; | |
113 | /* ok we already have this xattr, lets remove it */ | ||
114 | if (di) { | ||
115 | /* if we want create only exit */ | ||
116 | if (flags & XATTR_CREATE) { | ||
117 | ret = -EEXIST; | ||
118 | goto out; | 113 | goto out; |
119 | } | 114 | } |
120 | |||
121 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | 115 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
122 | BUG_ON(ret); | 116 | if (ret) |
117 | goto out; | ||
123 | btrfs_release_path(path); | 118 | btrfs_release_path(path); |
119 | } | ||
124 | 120 | ||
125 | /* if we don't have a value then we are removing the xattr */ | 121 | again: |
126 | if (!value) | 122 | ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), |
123 | name, name_len, value, size); | ||
124 | if (ret == -EEXIST) { | ||
125 | if (flags & XATTR_CREATE) | ||
127 | goto out; | 126 | goto out; |
128 | } else { | 127 | /* |
128 | * We can't use the path we already have since we won't have the | ||
129 | * proper locking for a delete, so release the path and | ||
130 | * re-lookup to delete the thing. | ||
131 | */ | ||
129 | btrfs_release_path(path); | 132 | btrfs_release_path(path); |
133 | di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), | ||
134 | name, name_len, -1); | ||
135 | if (IS_ERR(di)) { | ||
136 | ret = PTR_ERR(di); | ||
137 | goto out; | ||
138 | } else if (!di) { | ||
139 | /* Shouldn't happen but just in case... */ | ||
140 | btrfs_release_path(path); | ||
141 | goto again; | ||
142 | } | ||
130 | 143 | ||
131 | if (flags & XATTR_REPLACE) { | 144 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
132 | /* we couldn't find the attr to replace */ | 145 | if (ret) |
133 | ret = -ENODATA; | ||
134 | goto out; | 146 | goto out; |
147 | |||
148 | /* | ||
149 | * We have a value to set, so go back and try to insert it now. | ||
150 | */ | ||
151 | if (value) { | ||
152 | btrfs_release_path(path); | ||
153 | goto again; | ||
135 | } | 154 | } |
136 | } | 155 | } |
137 | |||
138 | /* ok we have to create a completely new xattr */ | ||
139 | ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), | ||
140 | name, name_len, value, size); | ||
141 | BUG_ON(ret); | ||
142 | out: | 156 | out: |
143 | btrfs_free_path(path); | 157 | btrfs_free_path(path); |
144 | return ret; | 158 | return ret; |