summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2015-10-12 04:05:40 -0400
committerChris Mason <clm@fb.com>2015-10-21 21:37:45 -0400
commit524725537023bb25a371722b1329446e5a2adcdb (patch)
tree40e4d0798939f7a6c9f4ee27c7bf3225c3aa5bb0
parentfefdc55702a5f9f99778b6bdce4c4e1185ff943f (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.h1
-rw-r--r--fs/btrfs/qgroup.c49
-rw-r--r--fs/btrfs/qgroup.h2
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 */
2501int 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
2528cleanup:
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 */
85int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len);
84#endif /* __BTRFS_QGROUP__ */ 86#endif /* __BTRFS_QGROUP__ */