.. | .. |
---|
76 | 76 | return ret; |
---|
77 | 77 | } |
---|
78 | 78 | |
---|
79 | | -static int do_setxattr(struct btrfs_trans_handle *trans, |
---|
80 | | - struct inode *inode, const char *name, |
---|
81 | | - const void *value, size_t size, int flags) |
---|
| 79 | +int btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode, |
---|
| 80 | + const char *name, const void *value, size_t size, int flags) |
---|
82 | 81 | { |
---|
83 | 82 | struct btrfs_dir_item *di = NULL; |
---|
84 | 83 | struct btrfs_root *root = BTRFS_I(inode)->root; |
---|
.. | .. |
---|
86 | 85 | struct btrfs_path *path; |
---|
87 | 86 | size_t name_len = strlen(name); |
---|
88 | 87 | int ret = 0; |
---|
| 88 | + |
---|
| 89 | + ASSERT(trans); |
---|
89 | 90 | |
---|
90 | 91 | if (name_len + size > BTRFS_MAX_XATTR_SIZE(root->fs_info)) |
---|
91 | 92 | return -ENOSPC; |
---|
.. | .. |
---|
174 | 175 | char *ptr; |
---|
175 | 176 | |
---|
176 | 177 | if (size > old_data_len) { |
---|
177 | | - if (btrfs_leaf_free_space(fs_info, leaf) < |
---|
| 178 | + if (btrfs_leaf_free_space(leaf) < |
---|
178 | 179 | (size - old_data_len)) { |
---|
179 | 180 | ret = -ENOSPC; |
---|
180 | 181 | goto out; |
---|
.. | .. |
---|
184 | 185 | if (old_data_len + name_len + sizeof(*di) == item_size) { |
---|
185 | 186 | /* No other xattrs packed in the same leaf item. */ |
---|
186 | 187 | if (size > old_data_len) |
---|
187 | | - btrfs_extend_item(fs_info, path, |
---|
188 | | - size - old_data_len); |
---|
| 188 | + btrfs_extend_item(path, size - old_data_len); |
---|
189 | 189 | else if (size < old_data_len) |
---|
190 | | - btrfs_truncate_item(fs_info, path, |
---|
191 | | - data_size, 1); |
---|
| 190 | + btrfs_truncate_item(path, data_size, 1); |
---|
192 | 191 | } else { |
---|
193 | 192 | /* There are other xattrs packed in the same item. */ |
---|
194 | 193 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
---|
195 | 194 | if (ret) |
---|
196 | 195 | goto out; |
---|
197 | | - btrfs_extend_item(fs_info, path, data_size); |
---|
| 196 | + btrfs_extend_item(path, data_size); |
---|
198 | 197 | } |
---|
199 | 198 | |
---|
200 | 199 | item = btrfs_item_nr(slot); |
---|
.. | .. |
---|
214 | 213 | } |
---|
215 | 214 | out: |
---|
216 | 215 | btrfs_free_path(path); |
---|
| 216 | + if (!ret) { |
---|
| 217 | + set_bit(BTRFS_INODE_COPY_EVERYTHING, |
---|
| 218 | + &BTRFS_I(inode)->runtime_flags); |
---|
| 219 | + clear_bit(BTRFS_INODE_NO_XATTRS, &BTRFS_I(inode)->runtime_flags); |
---|
| 220 | + } |
---|
217 | 221 | return ret; |
---|
218 | 222 | } |
---|
219 | 223 | |
---|
220 | 224 | /* |
---|
221 | 225 | * @value: "" makes the attribute to empty, NULL removes it |
---|
222 | 226 | */ |
---|
223 | | -int btrfs_setxattr(struct btrfs_trans_handle *trans, |
---|
224 | | - struct inode *inode, const char *name, |
---|
225 | | - const void *value, size_t size, int flags) |
---|
| 227 | +int btrfs_setxattr_trans(struct inode *inode, const char *name, |
---|
| 228 | + const void *value, size_t size, int flags) |
---|
226 | 229 | { |
---|
227 | 230 | struct btrfs_root *root = BTRFS_I(inode)->root; |
---|
| 231 | + struct btrfs_trans_handle *trans; |
---|
| 232 | + const bool start_trans = (current->journal_info == NULL); |
---|
228 | 233 | int ret; |
---|
229 | 234 | |
---|
230 | | - if (btrfs_root_readonly(root)) |
---|
231 | | - return -EROFS; |
---|
| 235 | + if (start_trans) { |
---|
| 236 | + /* |
---|
| 237 | + * 1 unit for inserting/updating/deleting the xattr |
---|
| 238 | + * 1 unit for the inode item update |
---|
| 239 | + */ |
---|
| 240 | + trans = btrfs_start_transaction(root, 2); |
---|
| 241 | + if (IS_ERR(trans)) |
---|
| 242 | + return PTR_ERR(trans); |
---|
| 243 | + } else { |
---|
| 244 | + /* |
---|
| 245 | + * This can happen when smack is enabled and a directory is being |
---|
| 246 | + * created. It happens through d_instantiate_new(), which calls |
---|
| 247 | + * smack_d_instantiate(), which in turn calls __vfs_setxattr() to |
---|
| 248 | + * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the |
---|
| 249 | + * inode. We have already reserved space for the xattr and inode |
---|
| 250 | + * update at btrfs_mkdir(), so just use the transaction handle. |
---|
| 251 | + * We don't join or start a transaction, as that will reset the |
---|
| 252 | + * block_rsv of the handle and trigger a warning for the start |
---|
| 253 | + * case. |
---|
| 254 | + */ |
---|
| 255 | + ASSERT(strncmp(name, XATTR_SECURITY_PREFIX, |
---|
| 256 | + XATTR_SECURITY_PREFIX_LEN) == 0); |
---|
| 257 | + trans = current->journal_info; |
---|
| 258 | + } |
---|
232 | 259 | |
---|
233 | | - if (trans) |
---|
234 | | - return do_setxattr(trans, inode, name, value, size, flags); |
---|
235 | | - |
---|
236 | | - trans = btrfs_start_transaction(root, 2); |
---|
237 | | - if (IS_ERR(trans)) |
---|
238 | | - return PTR_ERR(trans); |
---|
239 | | - |
---|
240 | | - ret = do_setxattr(trans, inode, name, value, size, flags); |
---|
| 260 | + ret = btrfs_setxattr(trans, inode, name, value, size, flags); |
---|
241 | 261 | if (ret) |
---|
242 | 262 | goto out; |
---|
243 | 263 | |
---|
244 | 264 | inode_inc_iversion(inode); |
---|
245 | 265 | inode->i_ctime = current_time(inode); |
---|
246 | | - set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags); |
---|
247 | 266 | ret = btrfs_update_inode(trans, root, inode); |
---|
248 | 267 | BUG_ON(ret); |
---|
249 | 268 | out: |
---|
250 | | - btrfs_end_transaction(trans); |
---|
| 269 | + if (start_trans) |
---|
| 270 | + btrfs_end_transaction(trans); |
---|
251 | 271 | return ret; |
---|
252 | 272 | } |
---|
253 | 273 | |
---|
.. | .. |
---|
358 | 378 | |
---|
359 | 379 | static int btrfs_xattr_handler_get(const struct xattr_handler *handler, |
---|
360 | 380 | struct dentry *unused, struct inode *inode, |
---|
361 | | - const char *name, void *buffer, size_t size) |
---|
| 381 | + const char *name, void *buffer, size_t size, |
---|
| 382 | + int flags) |
---|
362 | 383 | { |
---|
363 | 384 | name = xattr_full_name(handler, name); |
---|
364 | 385 | return btrfs_getxattr(inode, name, buffer, size); |
---|
.. | .. |
---|
369 | 390 | const char *name, const void *buffer, |
---|
370 | 391 | size_t size, int flags) |
---|
371 | 392 | { |
---|
| 393 | + if (btrfs_root_readonly(BTRFS_I(inode)->root)) |
---|
| 394 | + return -EROFS; |
---|
| 395 | + |
---|
372 | 396 | name = xattr_full_name(handler, name); |
---|
373 | | - return btrfs_setxattr(NULL, inode, name, buffer, size, flags); |
---|
| 397 | + return btrfs_setxattr_trans(inode, name, buffer, size, flags); |
---|
374 | 398 | } |
---|
375 | 399 | |
---|
376 | 400 | static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler, |
---|
.. | .. |
---|
378 | 402 | const char *name, const void *value, |
---|
379 | 403 | size_t size, int flags) |
---|
380 | 404 | { |
---|
| 405 | + int ret; |
---|
| 406 | + struct btrfs_trans_handle *trans; |
---|
| 407 | + struct btrfs_root *root = BTRFS_I(inode)->root; |
---|
| 408 | + |
---|
381 | 409 | name = xattr_full_name(handler, name); |
---|
382 | | - return btrfs_set_prop(inode, name, value, size, flags); |
---|
| 410 | + ret = btrfs_validate_prop(name, value, size); |
---|
| 411 | + if (ret) |
---|
| 412 | + return ret; |
---|
| 413 | + |
---|
| 414 | + trans = btrfs_start_transaction(root, 2); |
---|
| 415 | + if (IS_ERR(trans)) |
---|
| 416 | + return PTR_ERR(trans); |
---|
| 417 | + |
---|
| 418 | + ret = btrfs_set_prop(trans, inode, name, value, size, flags); |
---|
| 419 | + if (!ret) { |
---|
| 420 | + inode_inc_iversion(inode); |
---|
| 421 | + inode->i_ctime = current_time(inode); |
---|
| 422 | + ret = btrfs_update_inode(trans, root, inode); |
---|
| 423 | + BUG_ON(ret); |
---|
| 424 | + } |
---|
| 425 | + |
---|
| 426 | + btrfs_end_transaction(trans); |
---|
| 427 | + |
---|
| 428 | + return ret; |
---|
383 | 429 | } |
---|
384 | 430 | |
---|
385 | 431 | static const struct xattr_handler btrfs_security_xattr_handler = { |
---|
.. | .. |
---|
419 | 465 | }; |
---|
420 | 466 | |
---|
421 | 467 | static int btrfs_initxattrs(struct inode *inode, |
---|
422 | | - const struct xattr *xattr_array, void *fs_info) |
---|
| 468 | + const struct xattr *xattr_array, void *fs_private) |
---|
423 | 469 | { |
---|
| 470 | + struct btrfs_trans_handle *trans = fs_private; |
---|
424 | 471 | const struct xattr *xattr; |
---|
425 | | - struct btrfs_trans_handle *trans = fs_info; |
---|
426 | 472 | unsigned int nofs_flag; |
---|
427 | 473 | char *name; |
---|
428 | 474 | int err = 0; |
---|
.. | .. |
---|
442 | 488 | strcpy(name, XATTR_SECURITY_PREFIX); |
---|
443 | 489 | strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); |
---|
444 | 490 | err = btrfs_setxattr(trans, inode, name, xattr->value, |
---|
445 | | - xattr->value_len, 0); |
---|
| 491 | + xattr->value_len, 0); |
---|
446 | 492 | kfree(name); |
---|
447 | 493 | if (err < 0) |
---|
448 | 494 | break; |
---|