diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-10-12 04:05:40 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-10-21 21:37:45 -0400 |
commit | 524725537023bb25a371722b1329446e5a2adcdb (patch) | |
tree | 40e4d0798939f7a6c9f4ee27c7bf3225c3aa5bb0 | |
parent | fefdc55702a5f9f99778b6bdce4c4e1185ff943f (diff) |
btrfs: qgroup: Introduce btrfs_qgroup_reserve_data function
Introduce a new function, btrfs_qgroup_reserve_data(), which will use
io_tree to accurate qgroup reserve, to avoid reserved space leaking.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r-- | fs/btrfs/extent_io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/qgroup.c | 49 | ||||
-rw-r--r-- | fs/btrfs/qgroup.h | 2 |
3 files changed, 52 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 51e1b7143256..f4c1ae11855f 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #define EXTENT_NEED_WAIT (1U << 13) | 19 | #define EXTENT_NEED_WAIT (1U << 13) |
20 | #define EXTENT_DAMAGED (1U << 14) | 20 | #define EXTENT_DAMAGED (1U << 14) |
21 | #define EXTENT_NORESERVE (1U << 15) | 21 | #define EXTENT_NORESERVE (1U << 15) |
22 | #define EXTENT_QGROUP_RESERVED (1U << 16) | ||
22 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) | 23 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) |
23 | #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC) | 24 | #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC) |
24 | 25 | ||
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index d904ee1c5349..50662748532a 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -2486,3 +2486,52 @@ btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info) | |||
2486 | btrfs_queue_work(fs_info->qgroup_rescan_workers, | 2486 | btrfs_queue_work(fs_info->qgroup_rescan_workers, |
2487 | &fs_info->qgroup_rescan_work); | 2487 | &fs_info->qgroup_rescan_work); |
2488 | } | 2488 | } |
2489 | |||
2490 | /* | ||
2491 | * Reserve qgroup space for range [start, start + len). | ||
2492 | * | ||
2493 | * This function will either reserve space from related qgroups or doing | ||
2494 | * nothing if the range is already reserved. | ||
2495 | * | ||
2496 | * Return 0 for successful reserve | ||
2497 | * Return <0 for error (including -EQUOT) | ||
2498 | * | ||
2499 | * NOTE: this function may sleep for memory allocation. | ||
2500 | */ | ||
2501 | int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len) | ||
2502 | { | ||
2503 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
2504 | struct extent_changeset changeset; | ||
2505 | struct ulist_node *unode; | ||
2506 | struct ulist_iterator uiter; | ||
2507 | int ret; | ||
2508 | |||
2509 | if (!root->fs_info->quota_enabled || !is_fstree(root->objectid) || | ||
2510 | len == 0) | ||
2511 | return 0; | ||
2512 | |||
2513 | changeset.bytes_changed = 0; | ||
2514 | changeset.range_changed = ulist_alloc(GFP_NOFS); | ||
2515 | |||
2516 | ret = set_record_extent_bits(&BTRFS_I(inode)->io_tree, start, | ||
2517 | start + len -1, EXTENT_QGROUP_RESERVED, GFP_NOFS, | ||
2518 | &changeset); | ||
2519 | if (ret < 0) | ||
2520 | goto cleanup; | ||
2521 | ret = btrfs_qgroup_reserve(root, changeset.bytes_changed); | ||
2522 | if (ret < 0) | ||
2523 | goto cleanup; | ||
2524 | |||
2525 | ulist_free(changeset.range_changed); | ||
2526 | return ret; | ||
2527 | |||
2528 | cleanup: | ||
2529 | /* cleanup already reserved ranges */ | ||
2530 | ULIST_ITER_INIT(&uiter); | ||
2531 | while ((unode = ulist_next(changeset.range_changed, &uiter))) | ||
2532 | clear_extent_bit(&BTRFS_I(inode)->io_tree, unode->val, | ||
2533 | unode->aux, EXTENT_QGROUP_RESERVED, 0, 0, NULL, | ||
2534 | GFP_NOFS); | ||
2535 | ulist_free(changeset.range_changed); | ||
2536 | return ret; | ||
2537 | } | ||
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h index 6387dcfa354c..bd17cc24335c 100644 --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h | |||
@@ -81,4 +81,6 @@ int btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid, | |||
81 | u64 rfer, u64 excl); | 81 | u64 rfer, u64 excl); |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | /* New io_tree based accurate qgroup reserve API */ | ||
85 | int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len); | ||
84 | #endif /* __BTRFS_QGROUP__ */ | 86 | #endif /* __BTRFS_QGROUP__ */ |