aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2009-11-12 04:35:27 -0500
committerChris Mason <chris.mason@oracle.com>2009-12-17 12:33:34 -0500
commitf34f57a3ab4e73304d78c125682f1a53cd3975f2 (patch)
tree359aff6491d3e92b3901ea78dc164d41209d3eea /fs/btrfs
parent8082510e7124cc50d728f1b875639cb4e22312cc (diff)
Btrfs: Pass transaction handle to security and ACL initialization functions
Pass transaction handle down to security and ACL initialization functions, so we can avoid starting nested transactions Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/acl.c23
-rw-r--r--fs/btrfs/ctree.h13
-rw-r--r--fs/btrfs/dir-item.c19
-rw-r--r--fs/btrfs/inode.c15
-rw-r--r--fs/btrfs/xattr.c80
-rw-r--r--fs/btrfs/xattr.h9
6 files changed, 96 insertions, 63 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 361604244271..1898f8555f06 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -94,7 +94,8 @@ static int btrfs_xattr_get_acl(struct inode *inode, int type,
94/* 94/*
95 * Needs to be called with fs_mutex held 95 * Needs to be called with fs_mutex held
96 */ 96 */
97static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 97static int btrfs_set_acl(struct btrfs_trans_handle *trans,
98 struct inode *inode, struct posix_acl *acl, int type)
98{ 99{
99 int ret, size = 0; 100 int ret, size = 0;
100 const char *name; 101 const char *name;
@@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
140 goto out; 141 goto out;
141 } 142 }
142 143
143 ret = __btrfs_setxattr(inode, name, value, size, 0); 144 ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
144
145out: 145out:
146 kfree(value); 146 kfree(value);
147 147
@@ -154,7 +154,7 @@ out:
154static int btrfs_xattr_set_acl(struct inode *inode, int type, 154static int btrfs_xattr_set_acl(struct inode *inode, int type,
155 const void *value, size_t size) 155 const void *value, size_t size)
156{ 156{
157 int ret = 0; 157 int ret;
158 struct posix_acl *acl = NULL; 158 struct posix_acl *acl = NULL;
159 159
160 if (value) { 160 if (value) {
@@ -167,7 +167,7 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type,
167 } 167 }
168 } 168 }
169 169
170 ret = btrfs_set_acl(inode, acl, type); 170 ret = btrfs_set_acl(NULL, inode, acl, type);
171 171
172 posix_acl_release(acl); 172 posix_acl_release(acl);
173 173
@@ -221,7 +221,8 @@ int btrfs_check_acl(struct inode *inode, int mask)
221 * stuff has been fixed to work with that. If the locking stuff changes, we 221 * stuff has been fixed to work with that. If the locking stuff changes, we
222 * need to re-evaluate the acl locking stuff. 222 * need to re-evaluate the acl locking stuff.
223 */ 223 */
224int btrfs_init_acl(struct inode *inode, struct inode *dir) 224int btrfs_init_acl(struct btrfs_trans_handle *trans,
225 struct inode *inode, struct inode *dir)
225{ 226{
226 struct posix_acl *acl = NULL; 227 struct posix_acl *acl = NULL;
227 int ret = 0; 228 int ret = 0;
@@ -246,7 +247,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
246 mode_t mode; 247 mode_t mode;
247 248
248 if (S_ISDIR(inode->i_mode)) { 249 if (S_ISDIR(inode->i_mode)) {
249 ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT); 250 ret = btrfs_set_acl(trans, inode, acl,
251 ACL_TYPE_DEFAULT);
250 if (ret) 252 if (ret)
251 goto failed; 253 goto failed;
252 } 254 }
@@ -261,7 +263,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
261 inode->i_mode = mode; 263 inode->i_mode = mode;
262 if (ret > 0) { 264 if (ret > 0) {
263 /* we need an acl */ 265 /* we need an acl */
264 ret = btrfs_set_acl(inode, clone, 266 ret = btrfs_set_acl(trans, inode, clone,
265 ACL_TYPE_ACCESS); 267 ACL_TYPE_ACCESS);
266 } 268 }
267 } 269 }
@@ -294,7 +296,7 @@ int btrfs_acl_chmod(struct inode *inode)
294 296
295 ret = posix_acl_chmod_masq(clone, inode->i_mode); 297 ret = posix_acl_chmod_masq(clone, inode->i_mode);
296 if (!ret) 298 if (!ret)
297 ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS); 299 ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
298 300
299 posix_acl_release(clone); 301 posix_acl_release(clone);
300 302
@@ -320,7 +322,8 @@ int btrfs_acl_chmod(struct inode *inode)
320 return 0; 322 return 0;
321} 323}
322 324
323int btrfs_init_acl(struct inode *inode, struct inode *dir) 325int btrfs_init_acl(struct btrfs_trans_handle *trans,
326 struct inode *inode, struct inode *dir)
324{ 327{
325 return 0; 328 return 0;
326} 329}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fcfbefbbb685..a7cac2148c7c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -310,6 +310,9 @@ struct btrfs_header {
310#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ 310#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
311 sizeof(struct btrfs_item) - \ 311 sizeof(struct btrfs_item) - \
312 sizeof(struct btrfs_file_extent_item)) 312 sizeof(struct btrfs_file_extent_item))
313#define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
314 sizeof(struct btrfs_item) -\
315 sizeof(struct btrfs_dir_item))
313 316
314 317
315/* 318/*
@@ -2201,9 +2204,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
2201 struct btrfs_path *path, 2204 struct btrfs_path *path,
2202 struct btrfs_dir_item *di); 2205 struct btrfs_dir_item *di);
2203int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, 2206int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
2204 struct btrfs_root *root, const char *name, 2207 struct btrfs_root *root,
2205 u16 name_len, const void *data, u16 data_len, 2208 struct btrfs_path *path, u64 objectid,
2206 u64 dir); 2209 const char *name, u16 name_len,
2210 const void *data, u16 data_len);
2207struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, 2211struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
2208 struct btrfs_root *root, 2212 struct btrfs_root *root,
2209 struct btrfs_path *path, u64 dir, 2213 struct btrfs_path *path, u64 dir,
@@ -2382,7 +2386,8 @@ int btrfs_check_acl(struct inode *inode, int mask);
2382#else 2386#else
2383#define btrfs_check_acl NULL 2387#define btrfs_check_acl NULL
2384#endif 2388#endif
2385int btrfs_init_acl(struct inode *inode, struct inode *dir); 2389int btrfs_init_acl(struct btrfs_trans_handle *trans,
2390 struct inode *inode, struct inode *dir);
2386int btrfs_acl_chmod(struct inode *inode); 2391int btrfs_acl_chmod(struct inode *inode);
2387 2392
2388/* relocation.c */ 2393/* relocation.c */
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index f3a6075519cc..e9103b3baa49 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
68 * into the tree 68 * into the tree
69 */ 69 */
70int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, 70int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
71 struct btrfs_root *root, const char *name, 71 struct btrfs_root *root,
72 u16 name_len, const void *data, u16 data_len, 72 struct btrfs_path *path, u64 objectid,
73 u64 dir) 73 const char *name, u16 name_len,
74 const void *data, u16 data_len)
74{ 75{
75 int ret = 0; 76 int ret = 0;
76 struct btrfs_path *path;
77 struct btrfs_dir_item *dir_item; 77 struct btrfs_dir_item *dir_item;
78 unsigned long name_ptr, data_ptr; 78 unsigned long name_ptr, data_ptr;
79 struct btrfs_key key, location; 79 struct btrfs_key key, location;
@@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
81 struct extent_buffer *leaf; 81 struct extent_buffer *leaf;
82 u32 data_size; 82 u32 data_size;
83 83
84 key.objectid = dir; 84 BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));
85
86 key.objectid = objectid;
85 btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); 87 btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
86 key.offset = btrfs_name_hash(name, name_len); 88 key.offset = btrfs_name_hash(name, name_len);
87 path = btrfs_alloc_path();
88 if (!path)
89 return -ENOMEM;
90 if (name_len + data_len + sizeof(struct btrfs_dir_item) >
91 BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item))
92 return -ENOSPC;
93 89
94 data_size = sizeof(*dir_item) + name_len + data_len; 90 data_size = sizeof(*dir_item) + name_len + data_len;
95 dir_item = insert_with_overflow(trans, root, path, &key, data_size, 91 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
@@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
117 write_extent_buffer(leaf, data, data_ptr, data_len); 113 write_extent_buffer(leaf, data, data_ptr, data_len);
118 btrfs_mark_buffer_dirty(path->nodes[0]); 114 btrfs_mark_buffer_dirty(path->nodes[0]);
119 115
120 btrfs_free_path(path);
121 return ret; 116 return ret;
122} 117}
123 118
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index dcec42ee8cf2..82740a3c628a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -88,13 +88,14 @@ static noinline int cow_file_range(struct inode *inode,
88 u64 start, u64 end, int *page_started, 88 u64 start, u64 end, int *page_started,
89 unsigned long *nr_written, int unlock); 89 unsigned long *nr_written, int unlock);
90 90
91static int btrfs_init_inode_security(struct inode *inode, struct inode *dir) 91static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
92 struct inode *inode, struct inode *dir)
92{ 93{
93 int err; 94 int err;
94 95
95 err = btrfs_init_acl(inode, dir); 96 err = btrfs_init_acl(trans, inode, dir);
96 if (!err) 97 if (!err)
97 err = btrfs_xattr_security_init(inode, dir); 98 err = btrfs_xattr_security_init(trans, inode, dir);
98 return err; 99 return err;
99} 100}
100 101
@@ -4296,7 +4297,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
4296 if (IS_ERR(inode)) 4297 if (IS_ERR(inode))
4297 goto out_unlock; 4298 goto out_unlock;
4298 4299
4299 err = btrfs_init_inode_security(inode, dir); 4300 err = btrfs_init_inode_security(trans, inode, dir);
4300 if (err) { 4301 if (err) {
4301 drop_inode = 1; 4302 drop_inode = 1;
4302 goto out_unlock; 4303 goto out_unlock;
@@ -4367,7 +4368,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
4367 if (IS_ERR(inode)) 4368 if (IS_ERR(inode))
4368 goto out_unlock; 4369 goto out_unlock;
4369 4370
4370 err = btrfs_init_inode_security(inode, dir); 4371 err = btrfs_init_inode_security(trans, inode, dir);
4371 if (err) { 4372 if (err) {
4372 drop_inode = 1; 4373 drop_inode = 1;
4373 goto out_unlock; 4374 goto out_unlock;
@@ -4500,7 +4501,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
4500 4501
4501 drop_on_err = 1; 4502 drop_on_err = 1;
4502 4503
4503 err = btrfs_init_inode_security(inode, dir); 4504 err = btrfs_init_inode_security(trans, inode, dir);
4504 if (err) 4505 if (err)
4505 goto out_fail; 4506 goto out_fail;
4506 4507
@@ -5660,7 +5661,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
5660 if (IS_ERR(inode)) 5661 if (IS_ERR(inode))
5661 goto out_unlock; 5662 goto out_unlock;
5662 5663
5663 err = btrfs_init_inode_security(inode, dir); 5664 err = btrfs_init_inode_security(trans, inode, dir);
5664 if (err) { 5665 if (err) {
5665 drop_inode = 1; 5666 drop_inode = 1;
5666 goto out_unlock; 5667 goto out_unlock;
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index b6dd5967c48a..193b58f7d3f3 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -85,22 +85,23 @@ out:
85 return ret; 85 return ret;
86} 86}
87 87
88int __btrfs_setxattr(struct inode *inode, const char *name, 88static int do_setxattr(struct btrfs_trans_handle *trans,
89 const void *value, size_t size, int flags) 89 struct inode *inode, const char *name,
90 const void *value, size_t size, int flags)
90{ 91{
91 struct btrfs_dir_item *di; 92 struct btrfs_dir_item *di;
92 struct btrfs_root *root = BTRFS_I(inode)->root; 93 struct btrfs_root *root = BTRFS_I(inode)->root;
93 struct btrfs_trans_handle *trans;
94 struct btrfs_path *path; 94 struct btrfs_path *path;
95 int ret = 0, mod = 0; 95 size_t name_len = strlen(name);
96 int ret = 0;
97
98 if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
99 return -ENOSPC;
96 100
97 path = btrfs_alloc_path(); 101 path = btrfs_alloc_path();
98 if (!path) 102 if (!path)
99 return -ENOMEM; 103 return -ENOMEM;
100 104
101 trans = btrfs_join_transaction(root, 1);
102 btrfs_set_trans_block_group(trans, inode);
103
104 /* first lets see if we already have this xattr */ 105 /* first lets see if we already have this xattr */
105 di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name, 106 di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
106 strlen(name), -1); 107 strlen(name), -1);
@@ -118,15 +119,12 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
118 } 119 }
119 120
120 ret = btrfs_delete_one_dir_name(trans, root, path, di); 121 ret = btrfs_delete_one_dir_name(trans, root, path, di);
121 if (ret) 122 BUG_ON(ret);
122 goto out;
123 btrfs_release_path(root, path); 123 btrfs_release_path(root, path);
124 124
125 /* if we don't have a value then we are removing the xattr */ 125 /* if we don't have a value then we are removing the xattr */
126 if (!value) { 126 if (!value)
127 mod = 1;
128 goto out; 127 goto out;
129 }
130 } else { 128 } else {
131 btrfs_release_path(root, path); 129 btrfs_release_path(root, path);
132 130
@@ -138,20 +136,45 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
138 } 136 }
139 137
140 /* ok we have to create a completely new xattr */ 138 /* ok we have to create a completely new xattr */
141 ret = btrfs_insert_xattr_item(trans, root, name, strlen(name), 139 ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
142 value, size, inode->i_ino); 140 name, name_len, value, size);
141 BUG_ON(ret);
142out:
143 btrfs_free_path(path);
144 return ret;
145}
146
147int __btrfs_setxattr(struct btrfs_trans_handle *trans,
148 struct inode *inode, const char *name,
149 const void *value, size_t size, int flags)
150{
151 struct btrfs_root *root = BTRFS_I(inode)->root;
152 int ret;
153
154 if (trans)
155 return do_setxattr(trans, inode, name, value, size, flags);
156
157 ret = btrfs_reserve_metadata_space(root, 2);
143 if (ret) 158 if (ret)
144 goto out; 159 return ret;
145 mod = 1;
146 160
147out: 161 trans = btrfs_start_transaction(root, 1);
148 if (mod) { 162 if (!trans) {
149 inode->i_ctime = CURRENT_TIME; 163 ret = -ENOMEM;
150 ret = btrfs_update_inode(trans, root, inode); 164 goto out;
151 } 165 }
166 btrfs_set_trans_block_group(trans, inode);
152 167
153 btrfs_end_transaction(trans, root); 168 ret = do_setxattr(trans, inode, name, value, size, flags);
154 btrfs_free_path(path); 169 if (ret)
170 goto out;
171
172 inode->i_ctime = CURRENT_TIME;
173 ret = btrfs_update_inode(trans, root, inode);
174 BUG_ON(ret);
175out:
176 btrfs_end_transaction_throttle(trans, root);
177 btrfs_unreserve_metadata_space(root, 2);
155 return ret; 178 return ret;
156} 179}
157 180
@@ -314,7 +337,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
314 337
315 if (size == 0) 338 if (size == 0)
316 value = ""; /* empty EA, do not remove */ 339 value = ""; /* empty EA, do not remove */
317 return __btrfs_setxattr(dentry->d_inode, name, value, size, flags); 340
341 return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
342 flags);
318} 343}
319 344
320int btrfs_removexattr(struct dentry *dentry, const char *name) 345int btrfs_removexattr(struct dentry *dentry, const char *name)
@@ -329,10 +354,13 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
329 354
330 if (!btrfs_is_valid_xattr(name)) 355 if (!btrfs_is_valid_xattr(name))
331 return -EOPNOTSUPP; 356 return -EOPNOTSUPP;
332 return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); 357
358 return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
359 XATTR_REPLACE);
333} 360}
334 361
335int btrfs_xattr_security_init(struct inode *inode, struct inode *dir) 362int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
363 struct inode *inode, struct inode *dir)
336{ 364{
337 int err; 365 int err;
338 size_t len; 366 size_t len;
@@ -354,7 +382,7 @@ int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
354 } else { 382 } else {
355 strcpy(name, XATTR_SECURITY_PREFIX); 383 strcpy(name, XATTR_SECURITY_PREFIX);
356 strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); 384 strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
357 err = __btrfs_setxattr(inode, name, value, len, 0); 385 err = __btrfs_setxattr(trans, inode, name, value, len, 0);
358 kfree(name); 386 kfree(name);
359 } 387 }
360 388
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h
index c71e9c3cf3f7..721efa0346e0 100644
--- a/fs/btrfs/xattr.h
+++ b/fs/btrfs/xattr.h
@@ -27,15 +27,16 @@ extern struct xattr_handler *btrfs_xattr_handlers[];
27 27
28extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name, 28extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
29 void *buffer, size_t size); 29 void *buffer, size_t size);
30extern int __btrfs_setxattr(struct inode *inode, const char *name, 30extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
31 const void *value, size_t size, int flags); 31 struct inode *inode, const char *name,
32 32 const void *value, size_t size, int flags);
33extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, 33extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
34 void *buffer, size_t size); 34 void *buffer, size_t size);
35extern int btrfs_setxattr(struct dentry *dentry, const char *name, 35extern int btrfs_setxattr(struct dentry *dentry, const char *name,
36 const void *value, size_t size, int flags); 36 const void *value, size_t size, int flags);
37extern int btrfs_removexattr(struct dentry *dentry, const char *name); 37extern int btrfs_removexattr(struct dentry *dentry, const char *name);
38 38
39extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir); 39extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
40 struct inode *inode, struct inode *dir);
40 41
41#endif /* __XATTR__ */ 42#endif /* __XATTR__ */