| .. | .. |
|---|
| 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; |
|---|