diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 235 |
1 files changed, 127 insertions, 108 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 2845c6ceecd2..9254b3d58dbe 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/security.h> | 39 | #include <linux/security.h> |
| 40 | #include <linux/xattr.h> | 40 | #include <linux/xattr.h> |
| 41 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
| 42 | #include <linux/slab.h> | ||
| 42 | #include "compat.h" | 43 | #include "compat.h" |
| 43 | #include "ctree.h" | 44 | #include "ctree.h" |
| 44 | #include "disk-io.h" | 45 | #include "disk-io.h" |
| @@ -48,7 +49,6 @@ | |||
| 48 | #include "print-tree.h" | 49 | #include "print-tree.h" |
| 49 | #include "volumes.h" | 50 | #include "volumes.h" |
| 50 | #include "locking.h" | 51 | #include "locking.h" |
| 51 | #include "ctree.h" | ||
| 52 | 52 | ||
| 53 | /* Mask out flags that are inappropriate for the given type of inode. */ | 53 | /* Mask out flags that are inappropriate for the given type of inode. */ |
| 54 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 54 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) |
| @@ -239,23 +239,19 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 239 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | 239 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; |
| 240 | u64 index = 0; | 240 | u64 index = 0; |
| 241 | 241 | ||
| 242 | ret = btrfs_find_free_objectid(NULL, root->fs_info->tree_root, | ||
| 243 | 0, &objectid); | ||
| 244 | if (ret) | ||
| 245 | return ret; | ||
| 242 | /* | 246 | /* |
| 243 | * 1 - inode item | 247 | * 1 - inode item |
| 244 | * 2 - refs | 248 | * 2 - refs |
| 245 | * 1 - root item | 249 | * 1 - root item |
| 246 | * 2 - dir items | 250 | * 2 - dir items |
| 247 | */ | 251 | */ |
| 248 | ret = btrfs_reserve_metadata_space(root, 6); | 252 | trans = btrfs_start_transaction(root, 6); |
| 249 | if (ret) | 253 | if (IS_ERR(trans)) |
| 250 | return ret; | 254 | return PTR_ERR(trans); |
| 251 | |||
| 252 | trans = btrfs_start_transaction(root, 1); | ||
| 253 | BUG_ON(!trans); | ||
| 254 | |||
| 255 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | ||
| 256 | 0, &objectid); | ||
| 257 | if (ret) | ||
| 258 | goto fail; | ||
| 259 | 255 | ||
| 260 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 256 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
| 261 | 0, objectid, NULL, 0, 0, 0); | 257 | 0, objectid, NULL, 0, 0, 0); |
| @@ -345,13 +341,10 @@ fail: | |||
| 345 | err = btrfs_commit_transaction(trans, root); | 341 | err = btrfs_commit_transaction(trans, root); |
| 346 | if (err && !ret) | 342 | if (err && !ret) |
| 347 | ret = err; | 343 | ret = err; |
| 348 | |||
| 349 | btrfs_unreserve_metadata_space(root, 6); | ||
| 350 | return ret; | 344 | return ret; |
| 351 | } | 345 | } |
| 352 | 346 | ||
| 353 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | 347 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry) |
| 354 | char *name, int namelen) | ||
| 355 | { | 348 | { |
| 356 | struct inode *inode; | 349 | struct inode *inode; |
| 357 | struct btrfs_pending_snapshot *pending_snapshot; | 350 | struct btrfs_pending_snapshot *pending_snapshot; |
| @@ -361,40 +354,33 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 361 | if (!root->ref_cows) | 354 | if (!root->ref_cows) |
| 362 | return -EINVAL; | 355 | return -EINVAL; |
| 363 | 356 | ||
| 364 | /* | ||
| 365 | * 1 - inode item | ||
| 366 | * 2 - refs | ||
| 367 | * 1 - root item | ||
| 368 | * 2 - dir items | ||
| 369 | */ | ||
| 370 | ret = btrfs_reserve_metadata_space(root, 6); | ||
| 371 | if (ret) | ||
| 372 | goto fail; | ||
| 373 | |||
| 374 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); | 357 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); |
| 375 | if (!pending_snapshot) { | 358 | if (!pending_snapshot) |
| 376 | ret = -ENOMEM; | 359 | return -ENOMEM; |
| 377 | btrfs_unreserve_metadata_space(root, 6); | 360 | |
| 378 | goto fail; | 361 | btrfs_init_block_rsv(&pending_snapshot->block_rsv); |
| 379 | } | ||
| 380 | pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); | ||
| 381 | if (!pending_snapshot->name) { | ||
| 382 | ret = -ENOMEM; | ||
| 383 | kfree(pending_snapshot); | ||
| 384 | btrfs_unreserve_metadata_space(root, 6); | ||
| 385 | goto fail; | ||
| 386 | } | ||
| 387 | memcpy(pending_snapshot->name, name, namelen); | ||
| 388 | pending_snapshot->name[namelen] = '\0'; | ||
| 389 | pending_snapshot->dentry = dentry; | 362 | pending_snapshot->dentry = dentry; |
| 390 | trans = btrfs_start_transaction(root, 1); | ||
| 391 | BUG_ON(!trans); | ||
| 392 | pending_snapshot->root = root; | 363 | pending_snapshot->root = root; |
| 364 | |||
| 365 | trans = btrfs_start_transaction(root->fs_info->extent_root, 5); | ||
| 366 | if (IS_ERR(trans)) { | ||
| 367 | ret = PTR_ERR(trans); | ||
| 368 | goto fail; | ||
| 369 | } | ||
| 370 | |||
| 371 | ret = btrfs_snap_reserve_metadata(trans, pending_snapshot); | ||
| 372 | BUG_ON(ret); | ||
| 373 | |||
| 393 | list_add(&pending_snapshot->list, | 374 | list_add(&pending_snapshot->list, |
| 394 | &trans->transaction->pending_snapshots); | 375 | &trans->transaction->pending_snapshots); |
| 395 | ret = btrfs_commit_transaction(trans, root); | 376 | ret = btrfs_commit_transaction(trans, root->fs_info->extent_root); |
| 396 | BUG_ON(ret); | 377 | BUG_ON(ret); |
| 397 | btrfs_unreserve_metadata_space(root, 6); | 378 | |
| 379 | ret = pending_snapshot->error; | ||
| 380 | if (ret) | ||
| 381 | goto fail; | ||
| 382 | |||
| 383 | btrfs_orphan_cleanup(pending_snapshot->snap); | ||
| 398 | 384 | ||
| 399 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); | 385 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); |
| 400 | if (IS_ERR(inode)) { | 386 | if (IS_ERR(inode)) { |
| @@ -405,6 +391,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 405 | d_instantiate(dentry, inode); | 391 | d_instantiate(dentry, inode); |
| 406 | ret = 0; | 392 | ret = 0; |
| 407 | fail: | 393 | fail: |
| 394 | kfree(pending_snapshot); | ||
| 408 | return ret; | 395 | return ret; |
| 409 | } | 396 | } |
| 410 | 397 | ||
| @@ -456,8 +443,7 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
| 456 | goto out_up_read; | 443 | goto out_up_read; |
| 457 | 444 | ||
| 458 | if (snap_src) { | 445 | if (snap_src) { |
| 459 | error = create_snapshot(snap_src, dentry, | 446 | error = create_snapshot(snap_src, dentry); |
| 460 | name, namelen); | ||
| 461 | } else { | 447 | } else { |
| 462 | error = create_subvol(BTRFS_I(dir)->root, dentry, | 448 | error = create_subvol(BTRFS_I(dir)->root, dentry, |
| 463 | name, namelen); | 449 | name, namelen); |
| @@ -511,7 +497,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
| 511 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); | 497 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); |
| 512 | unlock_extent(io_tree, start, start + len - 1, GFP_NOFS); | 498 | unlock_extent(io_tree, start, start + len - 1, GFP_NOFS); |
| 513 | 499 | ||
| 514 | if (!em) | 500 | if (IS_ERR(em)) |
| 515 | return 0; | 501 | return 0; |
| 516 | } | 502 | } |
| 517 | 503 | ||
| @@ -601,19 +587,9 @@ static int btrfs_defrag_file(struct file *file, | |||
| 601 | if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) | 587 | if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) |
| 602 | BTRFS_I(inode)->force_compress = 1; | 588 | BTRFS_I(inode)->force_compress = 1; |
| 603 | 589 | ||
| 604 | ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE); | 590 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); |
| 605 | if (ret) { | 591 | if (ret) |
| 606 | ret = -ENOSPC; | 592 | goto err_unlock; |
| 607 | break; | ||
| 608 | } | ||
| 609 | |||
| 610 | ret = btrfs_reserve_metadata_for_delalloc(root, inode, 1); | ||
| 611 | if (ret) { | ||
| 612 | btrfs_free_reserved_data_space(root, inode, | ||
| 613 | PAGE_CACHE_SIZE); | ||
| 614 | ret = -ENOSPC; | ||
| 615 | break; | ||
| 616 | } | ||
| 617 | again: | 593 | again: |
| 618 | if (inode->i_size == 0 || | 594 | if (inode->i_size == 0 || |
| 619 | i > ((inode->i_size - 1) >> PAGE_CACHE_SHIFT)) { | 595 | i > ((inode->i_size - 1) >> PAGE_CACHE_SHIFT)) { |
| @@ -622,8 +598,10 @@ again: | |||
| 622 | } | 598 | } |
| 623 | 599 | ||
| 624 | page = grab_cache_page(inode->i_mapping, i); | 600 | page = grab_cache_page(inode->i_mapping, i); |
| 625 | if (!page) | 601 | if (!page) { |
| 602 | ret = -ENOMEM; | ||
| 626 | goto err_reservations; | 603 | goto err_reservations; |
| 604 | } | ||
| 627 | 605 | ||
| 628 | if (!PageUptodate(page)) { | 606 | if (!PageUptodate(page)) { |
| 629 | btrfs_readpage(NULL, page); | 607 | btrfs_readpage(NULL, page); |
| @@ -631,6 +609,7 @@ again: | |||
| 631 | if (!PageUptodate(page)) { | 609 | if (!PageUptodate(page)) { |
| 632 | unlock_page(page); | 610 | unlock_page(page); |
| 633 | page_cache_release(page); | 611 | page_cache_release(page); |
| 612 | ret = -EIO; | ||
| 634 | goto err_reservations; | 613 | goto err_reservations; |
| 635 | } | 614 | } |
| 636 | } | 615 | } |
| @@ -644,8 +623,7 @@ again: | |||
| 644 | wait_on_page_writeback(page); | 623 | wait_on_page_writeback(page); |
| 645 | 624 | ||
| 646 | if (PageDirty(page)) { | 625 | if (PageDirty(page)) { |
| 647 | btrfs_free_reserved_data_space(root, inode, | 626 | btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); |
| 648 | PAGE_CACHE_SIZE); | ||
| 649 | goto loop_unlock; | 627 | goto loop_unlock; |
| 650 | } | 628 | } |
| 651 | 629 | ||
| @@ -683,7 +661,6 @@ loop_unlock: | |||
| 683 | page_cache_release(page); | 661 | page_cache_release(page); |
| 684 | mutex_unlock(&inode->i_mutex); | 662 | mutex_unlock(&inode->i_mutex); |
| 685 | 663 | ||
| 686 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | ||
| 687 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1); | 664 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1); |
| 688 | i++; | 665 | i++; |
| 689 | } | 666 | } |
| @@ -713,9 +690,9 @@ loop_unlock: | |||
| 713 | return 0; | 690 | return 0; |
| 714 | 691 | ||
| 715 | err_reservations: | 692 | err_reservations: |
| 693 | btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); | ||
| 694 | err_unlock: | ||
| 716 | mutex_unlock(&inode->i_mutex); | 695 | mutex_unlock(&inode->i_mutex); |
| 717 | btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE); | ||
| 718 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | ||
| 719 | return ret; | 696 | return ret; |
| 720 | } | 697 | } |
| 721 | 698 | ||
| @@ -811,7 +788,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
| 811 | device->name, (unsigned long long)new_size); | 788 | device->name, (unsigned long long)new_size); |
| 812 | 789 | ||
| 813 | if (new_size > old_size) { | 790 | if (new_size > old_size) { |
| 814 | trans = btrfs_start_transaction(root, 1); | 791 | trans = btrfs_start_transaction(root, 0); |
| 815 | ret = btrfs_grow_device(trans, device, new_size); | 792 | ret = btrfs_grow_device(trans, device, new_size); |
| 816 | btrfs_commit_transaction(trans, root); | 793 | btrfs_commit_transaction(trans, root); |
| 817 | } else { | 794 | } else { |
| @@ -1212,6 +1189,9 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file, | |||
| 1212 | return -EPERM; | 1189 | return -EPERM; |
| 1213 | 1190 | ||
| 1214 | args = kmalloc(sizeof(*args), GFP_KERNEL); | 1191 | args = kmalloc(sizeof(*args), GFP_KERNEL); |
| 1192 | if (!args) | ||
| 1193 | return -ENOMEM; | ||
| 1194 | |||
| 1215 | if (copy_from_user(args, argp, sizeof(*args))) { | 1195 | if (copy_from_user(args, argp, sizeof(*args))) { |
| 1216 | kfree(args); | 1196 | kfree(args); |
| 1217 | return -EFAULT; | 1197 | return -EFAULT; |
| @@ -1297,7 +1277,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
| 1297 | if (err) | 1277 | if (err) |
| 1298 | goto out_up_write; | 1278 | goto out_up_write; |
| 1299 | 1279 | ||
| 1300 | trans = btrfs_start_transaction(root, 1); | 1280 | trans = btrfs_start_transaction(root, 0); |
| 1281 | if (IS_ERR(trans)) { | ||
| 1282 | err = PTR_ERR(trans); | ||
| 1283 | goto out_up_write; | ||
| 1284 | } | ||
| 1285 | trans->block_rsv = &root->fs_info->global_block_rsv; | ||
| 1286 | |||
| 1301 | ret = btrfs_unlink_subvol(trans, root, dir, | 1287 | ret = btrfs_unlink_subvol(trans, root, dir, |
| 1302 | dest->root_key.objectid, | 1288 | dest->root_key.objectid, |
| 1303 | dentry->d_name.name, | 1289 | dentry->d_name.name, |
| @@ -1311,10 +1297,12 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
| 1311 | dest->root_item.drop_level = 0; | 1297 | dest->root_item.drop_level = 0; |
| 1312 | btrfs_set_root_refs(&dest->root_item, 0); | 1298 | btrfs_set_root_refs(&dest->root_item, 0); |
| 1313 | 1299 | ||
| 1314 | ret = btrfs_insert_orphan_item(trans, | 1300 | if (!xchg(&dest->orphan_item_inserted, 1)) { |
| 1315 | root->fs_info->tree_root, | 1301 | ret = btrfs_insert_orphan_item(trans, |
| 1316 | dest->root_key.objectid); | 1302 | root->fs_info->tree_root, |
| 1317 | BUG_ON(ret); | 1303 | dest->root_key.objectid); |
| 1304 | BUG_ON(ret); | ||
| 1305 | } | ||
| 1318 | 1306 | ||
| 1319 | ret = btrfs_commit_transaction(trans, root); | 1307 | ret = btrfs_commit_transaction(trans, root); |
| 1320 | BUG_ON(ret); | 1308 | BUG_ON(ret); |
| @@ -1355,8 +1343,10 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
| 1355 | ret = -EPERM; | 1343 | ret = -EPERM; |
| 1356 | goto out; | 1344 | goto out; |
| 1357 | } | 1345 | } |
| 1358 | btrfs_defrag_root(root, 0); | 1346 | ret = btrfs_defrag_root(root, 0); |
| 1359 | btrfs_defrag_root(root->fs_info->extent_root, 0); | 1347 | if (ret) |
| 1348 | goto out; | ||
| 1349 | ret = btrfs_defrag_root(root->fs_info->extent_root, 0); | ||
| 1360 | break; | 1350 | break; |
| 1361 | case S_IFREG: | 1351 | case S_IFREG: |
| 1362 | if (!(file->f_mode & FMODE_WRITE)) { | 1352 | if (!(file->f_mode & FMODE_WRITE)) { |
| @@ -1375,6 +1365,7 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
| 1375 | sizeof(*range))) { | 1365 | sizeof(*range))) { |
| 1376 | ret = -EFAULT; | 1366 | ret = -EFAULT; |
| 1377 | kfree(range); | 1367 | kfree(range); |
| 1368 | goto out; | ||
| 1378 | } | 1369 | } |
| 1379 | /* compression requires us to start the IO */ | 1370 | /* compression requires us to start the IO */ |
| 1380 | if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) { | 1371 | if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) { |
| @@ -1385,9 +1376,11 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
| 1385 | /* the rest are all set to zero by kzalloc */ | 1376 | /* the rest are all set to zero by kzalloc */ |
| 1386 | range->len = (u64)-1; | 1377 | range->len = (u64)-1; |
| 1387 | } | 1378 | } |
| 1388 | btrfs_defrag_file(file, range); | 1379 | ret = btrfs_defrag_file(file, range); |
| 1389 | kfree(range); | 1380 | kfree(range); |
| 1390 | break; | 1381 | break; |
| 1382 | default: | ||
| 1383 | ret = -EINVAL; | ||
| 1391 | } | 1384 | } |
| 1392 | out: | 1385 | out: |
| 1393 | mnt_drop_write(file->f_path.mnt); | 1386 | mnt_drop_write(file->f_path.mnt); |
| @@ -1465,7 +1458,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1465 | */ | 1458 | */ |
| 1466 | 1459 | ||
| 1467 | /* the destination must be opened for writing */ | 1460 | /* the destination must be opened for writing */ |
| 1468 | if (!(file->f_mode & FMODE_WRITE)) | 1461 | if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) |
| 1469 | return -EINVAL; | 1462 | return -EINVAL; |
| 1470 | 1463 | ||
| 1471 | ret = mnt_want_write(file->f_path.mnt); | 1464 | ret = mnt_want_write(file->f_path.mnt); |
| @@ -1477,12 +1470,17 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1477 | ret = -EBADF; | 1470 | ret = -EBADF; |
| 1478 | goto out_drop_write; | 1471 | goto out_drop_write; |
| 1479 | } | 1472 | } |
| 1473 | |||
| 1480 | src = src_file->f_dentry->d_inode; | 1474 | src = src_file->f_dentry->d_inode; |
| 1481 | 1475 | ||
| 1482 | ret = -EINVAL; | 1476 | ret = -EINVAL; |
| 1483 | if (src == inode) | 1477 | if (src == inode) |
| 1484 | goto out_fput; | 1478 | goto out_fput; |
| 1485 | 1479 | ||
| 1480 | /* the src must be open for reading */ | ||
| 1481 | if (!(src_file->f_mode & FMODE_READ)) | ||
| 1482 | goto out_fput; | ||
| 1483 | |||
| 1486 | ret = -EISDIR; | 1484 | ret = -EISDIR; |
| 1487 | if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) | 1485 | if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) |
| 1488 | goto out_fput; | 1486 | goto out_fput; |
| @@ -1513,7 +1511,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1513 | 1511 | ||
| 1514 | /* determine range to clone */ | 1512 | /* determine range to clone */ |
| 1515 | ret = -EINVAL; | 1513 | ret = -EINVAL; |
| 1516 | if (off >= src->i_size || off + len > src->i_size) | 1514 | if (off + len > src->i_size || off + len < off) |
| 1517 | goto out_unlock; | 1515 | goto out_unlock; |
| 1518 | if (len == 0) | 1516 | if (len == 0) |
| 1519 | olen = len = src->i_size - off; | 1517 | olen = len = src->i_size - off; |
| @@ -1541,12 +1539,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1541 | btrfs_wait_ordered_range(src, off, off+len); | 1539 | btrfs_wait_ordered_range(src, off, off+len); |
| 1542 | } | 1540 | } |
| 1543 | 1541 | ||
| 1544 | trans = btrfs_start_transaction(root, 1); | ||
| 1545 | BUG_ON(!trans); | ||
| 1546 | |||
| 1547 | /* punch hole in destination first */ | ||
| 1548 | btrfs_drop_extents(trans, inode, off, off + len, &hint_byte, 1); | ||
| 1549 | |||
| 1550 | /* clone data */ | 1542 | /* clone data */ |
| 1551 | key.objectid = src->i_ino; | 1543 | key.objectid = src->i_ino; |
| 1552 | key.type = BTRFS_EXTENT_DATA_KEY; | 1544 | key.type = BTRFS_EXTENT_DATA_KEY; |
| @@ -1557,7 +1549,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1557 | * note the key will change type as we walk through the | 1549 | * note the key will change type as we walk through the |
| 1558 | * tree. | 1550 | * tree. |
| 1559 | */ | 1551 | */ |
| 1560 | ret = btrfs_search_slot(trans, root, &key, path, 0, 0); | 1552 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 1561 | if (ret < 0) | 1553 | if (ret < 0) |
| 1562 | goto out; | 1554 | goto out; |
| 1563 | 1555 | ||
| @@ -1586,6 +1578,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1586 | u64 disko = 0, diskl = 0; | 1578 | u64 disko = 0, diskl = 0; |
| 1587 | u64 datao = 0, datal = 0; | 1579 | u64 datao = 0, datal = 0; |
| 1588 | u8 comp; | 1580 | u8 comp; |
| 1581 | u64 endoff; | ||
| 1589 | 1582 | ||
| 1590 | size = btrfs_item_size_nr(leaf, slot); | 1583 | size = btrfs_item_size_nr(leaf, slot); |
| 1591 | read_extent_buffer(leaf, buf, | 1584 | read_extent_buffer(leaf, buf, |
| @@ -1620,12 +1613,31 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1620 | new_key.objectid = inode->i_ino; | 1613 | new_key.objectid = inode->i_ino; |
| 1621 | new_key.offset = key.offset + destoff - off; | 1614 | new_key.offset = key.offset + destoff - off; |
| 1622 | 1615 | ||
| 1616 | trans = btrfs_start_transaction(root, 1); | ||
| 1617 | if (IS_ERR(trans)) { | ||
| 1618 | ret = PTR_ERR(trans); | ||
| 1619 | goto out; | ||
| 1620 | } | ||
| 1621 | |||
| 1623 | if (type == BTRFS_FILE_EXTENT_REG || | 1622 | if (type == BTRFS_FILE_EXTENT_REG || |
| 1624 | type == BTRFS_FILE_EXTENT_PREALLOC) { | 1623 | type == BTRFS_FILE_EXTENT_PREALLOC) { |
| 1624 | if (off > key.offset) { | ||
| 1625 | datao += off - key.offset; | ||
| 1626 | datal -= off - key.offset; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | if (key.offset + datal > off + len) | ||
| 1630 | datal = off + len - key.offset; | ||
| 1631 | |||
| 1632 | ret = btrfs_drop_extents(trans, inode, | ||
| 1633 | new_key.offset, | ||
| 1634 | new_key.offset + datal, | ||
| 1635 | &hint_byte, 1); | ||
| 1636 | BUG_ON(ret); | ||
| 1637 | |||
| 1625 | ret = btrfs_insert_empty_item(trans, root, path, | 1638 | ret = btrfs_insert_empty_item(trans, root, path, |
| 1626 | &new_key, size); | 1639 | &new_key, size); |
| 1627 | if (ret) | 1640 | BUG_ON(ret); |
| 1628 | goto out; | ||
| 1629 | 1641 | ||
| 1630 | leaf = path->nodes[0]; | 1642 | leaf = path->nodes[0]; |
| 1631 | slot = path->slots[0]; | 1643 | slot = path->slots[0]; |
| @@ -1636,14 +1648,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1636 | extent = btrfs_item_ptr(leaf, slot, | 1648 | extent = btrfs_item_ptr(leaf, slot, |
| 1637 | struct btrfs_file_extent_item); | 1649 | struct btrfs_file_extent_item); |
| 1638 | 1650 | ||
| 1639 | if (off > key.offset) { | ||
| 1640 | datao += off - key.offset; | ||
| 1641 | datal -= off - key.offset; | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | if (key.offset + datal > off + len) | ||
| 1645 | datal = off + len - key.offset; | ||
| 1646 | |||
| 1647 | /* disko == 0 means it's a hole */ | 1651 | /* disko == 0 means it's a hole */ |
| 1648 | if (!disko) | 1652 | if (!disko) |
| 1649 | datao = 0; | 1653 | datao = 0; |
| @@ -1674,14 +1678,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1674 | 1678 | ||
| 1675 | if (comp && (skip || trim)) { | 1679 | if (comp && (skip || trim)) { |
| 1676 | ret = -EINVAL; | 1680 | ret = -EINVAL; |
| 1681 | btrfs_end_transaction(trans, root); | ||
| 1677 | goto out; | 1682 | goto out; |
| 1678 | } | 1683 | } |
| 1679 | size -= skip + trim; | 1684 | size -= skip + trim; |
| 1680 | datal -= skip + trim; | 1685 | datal -= skip + trim; |
| 1686 | |||
| 1687 | ret = btrfs_drop_extents(trans, inode, | ||
| 1688 | new_key.offset, | ||
| 1689 | new_key.offset + datal, | ||
| 1690 | &hint_byte, 1); | ||
| 1691 | BUG_ON(ret); | ||
| 1692 | |||
| 1681 | ret = btrfs_insert_empty_item(trans, root, path, | 1693 | ret = btrfs_insert_empty_item(trans, root, path, |
| 1682 | &new_key, size); | 1694 | &new_key, size); |
| 1683 | if (ret) | 1695 | BUG_ON(ret); |
| 1684 | goto out; | ||
| 1685 | 1696 | ||
| 1686 | if (skip) { | 1697 | if (skip) { |
| 1687 | u32 start = | 1698 | u32 start = |
| @@ -1699,8 +1710,26 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1699 | } | 1710 | } |
| 1700 | 1711 | ||
| 1701 | btrfs_mark_buffer_dirty(leaf); | 1712 | btrfs_mark_buffer_dirty(leaf); |
| 1702 | } | 1713 | btrfs_release_path(root, path); |
| 1714 | |||
| 1715 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 1703 | 1716 | ||
| 1717 | /* | ||
| 1718 | * we round up to the block size at eof when | ||
| 1719 | * determining which extents to clone above, | ||
| 1720 | * but shouldn't round up the file size | ||
| 1721 | */ | ||
| 1722 | endoff = new_key.offset + datal; | ||
| 1723 | if (endoff > off+olen) | ||
| 1724 | endoff = off+olen; | ||
| 1725 | if (endoff > inode->i_size) | ||
| 1726 | btrfs_i_size_write(inode, endoff); | ||
| 1727 | |||
| 1728 | BTRFS_I(inode)->flags = BTRFS_I(src)->flags; | ||
| 1729 | ret = btrfs_update_inode(trans, root, inode); | ||
| 1730 | BUG_ON(ret); | ||
| 1731 | btrfs_end_transaction(trans, root); | ||
| 1732 | } | ||
| 1704 | next: | 1733 | next: |
| 1705 | btrfs_release_path(root, path); | 1734 | btrfs_release_path(root, path); |
| 1706 | key.offset++; | 1735 | key.offset++; |
| @@ -1708,17 +1737,7 @@ next: | |||
| 1708 | ret = 0; | 1737 | ret = 0; |
| 1709 | out: | 1738 | out: |
| 1710 | btrfs_release_path(root, path); | 1739 | btrfs_release_path(root, path); |
| 1711 | if (ret == 0) { | ||
| 1712 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 1713 | if (destoff + olen > inode->i_size) | ||
| 1714 | btrfs_i_size_write(inode, destoff + olen); | ||
| 1715 | BTRFS_I(inode)->flags = BTRFS_I(src)->flags; | ||
| 1716 | ret = btrfs_update_inode(trans, root, inode); | ||
| 1717 | } | ||
| 1718 | btrfs_end_transaction(trans, root); | ||
| 1719 | unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS); | 1740 | unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS); |
| 1720 | if (ret) | ||
| 1721 | vmtruncate(inode, 0); | ||
| 1722 | out_unlock: | 1741 | out_unlock: |
| 1723 | mutex_unlock(&src->i_mutex); | 1742 | mutex_unlock(&src->i_mutex); |
| 1724 | mutex_unlock(&inode->i_mutex); | 1743 | mutex_unlock(&inode->i_mutex); |
| @@ -1836,7 +1855,7 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
| 1836 | dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); | 1855 | dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); |
| 1837 | di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path, | 1856 | di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path, |
| 1838 | dir_id, "default", 7, 1); | 1857 | dir_id, "default", 7, 1); |
| 1839 | if (!di) { | 1858 | if (IS_ERR_OR_NULL(di)) { |
| 1840 | btrfs_free_path(path); | 1859 | btrfs_free_path(path); |
| 1841 | btrfs_end_transaction(trans, root); | 1860 | btrfs_end_transaction(trans, root); |
| 1842 | printk(KERN_ERR "Umm, you don't have the default dir item, " | 1861 | printk(KERN_ERR "Umm, you don't have the default dir item, " |
