All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qu Wenruo <quwenruo@cn.fujitsu.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 07/19] btrfs: qgroup: Introduce function to release reserved range
Date: Tue,  8 Sep 2015 16:37:24 +0800	[thread overview]
Message-ID: <1441701456-8034-8-git-send-email-quwenruo@cn.fujitsu.com> (raw)
In-Reply-To: <1441701456-8034-1-git-send-email-quwenruo@cn.fujitsu.com>

Introduce new function release_data_range() to release reserved ranges.
It will iterate through all existing ranges and remove/shrink them.

Note this function will not free reserved space, as the range can be
released in the following conditions:
1) The dirty range gets written to disk.
   In this case, reserved range will be released but reserved bytes
   will not be freed until the delayed_ref is run.

2) Truncate
   In this case, dirty ranges will be released and reserved bytes will
   also be freed.

So the new function won't free reserved space, but record them into
parameter if called needs.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
 fs/btrfs/qgroup.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 337b784..e24c10d 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -2849,6 +2849,136 @@ int btrfs_qgroup_reserve_data(struct inode *inode, u64 start, u64 len)
 	return ret;
 }
 
+/* Small helper used in release_data_range() to update rsv map */
+static inline void __update_rsv(struct btrfs_qgroup_data_rsv_map *map,
+				u64 *reserved, u64 cur_rsv)
+{
+	if (reserved)
+		*reserved += cur_rsv;
+	if (WARN_ON(map->reserved < cur_rsv))
+		map->reserved = 0;
+	else
+		map->reserved -= cur_rsv;
+}
+
+/*
+ * Release the range [start, start + len) from rsv map.
+ *
+ * The behavior should be much like reserve_data_range().
+ * @tmp: the allocated memory for case which need to split existing
+ *       range into two.
+ * @reserved: the number of bytes that may need to free
+ * Return > 0 if 'tmp' memory is used and release range successfully
+ * Return 0 if 'tmp' memory is not used and release range successfully
+ * Return < 0 for error
+ */
+static int release_data_range(struct btrfs_qgroup_data_rsv_map *map,
+			      struct data_rsv_range *tmp,
+			      u64 start, u64 len, u64 *reserved)
+{
+	struct data_rsv_range *range;
+	u64 cur_rsv = 0;
+	int ret = 0;
+
+	range = find_reserve_range(map, start);
+	/* empty tree, just return */
+	if (!range)
+		return 0;
+	/*
+	 * For split case
+	 *		|<----desired---->|
+	 * |////////////////////////////////////////////|
+	 * In this case, we need to insert one new range.
+	 */
+	if (range->start < start && range->start + range->len > start + len) {
+		u64 new_start = start + len;
+		u64 new_len = range->start + range->len - start - len;
+
+		cur_rsv = len;
+		if (reserved)
+			*reserved += cur_rsv;
+		map->reserved -= cur_rsv;
+
+		range->len = start - range->start;
+		ret = insert_data_range(map, tmp, new_start, new_len);
+		WARN_ON(ret <= 0);
+		return 1;
+	}
+
+	/*
+	 * Iterate until the end of the range and free release all
+	 * reserved data from map.
+	 * We iterate by existing range, as that will makes codes a
+	 * little more clean.
+	 *
+	 *	|<---------desired------------------------>|
+	 * |//1//|	|//2//|		|//3//|		|//4//|
+	 */
+	while (range->start < start + len) {
+		struct rb_node *next = NULL;
+		int range_freed = 0;
+
+		/*
+		 *		|<---desired---->|
+		 * |///////|
+		 */
+		if (unlikely(range->start + range->len <= start))
+			goto next;
+
+		/*
+		 *	|<----desired---->|
+		 * |///////|
+		 */
+		if (range->start < start &&
+		    range->start + range->len > start) {
+			cur_rsv = range->start + range->len - start;
+
+			range->len = start - range->start;
+			goto next;
+		}
+
+		/*
+		 *	|<--desired-->|
+		 *	    |/////|
+		 * Including same start/end case, so other case don't need
+		 * to check start/end equal case and don't need bother
+		 * deleting range.
+		 */
+		if (range->start >= start &&
+		    range->start + range->len <= start + len) {
+			cur_rsv = range->len;
+
+			range_freed = 1;
+			next = rb_next(&range->node);
+			rb_erase(&range->node, &map->root);
+			kfree(range);
+			goto next;
+
+		}
+
+		/*
+		 *	|<--desired-->|
+		 *		  |///////|
+		 */
+		if (range->start < start + len &&
+		    range->start + range->len > start + len) {
+			cur_rsv = start + len - range->start;
+
+			range->len = range->start + range->len - start - len;
+			range->start = start + len;
+			goto next;
+		}
+next:
+		__update_rsv(map, reserved, cur_rsv);
+		if (!range_freed)
+			next = rb_next(&range->node);
+		if (!next)
+			break;
+		range = rb_entry(next, struct data_rsv_range, node);
+	}
+	return 0;
+}
+
 /*
  * Init data_rsv_map for a given inode.
  *
-- 
2.5.1


  parent reply	other threads:[~2015-09-09  5:05 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-08  8:37 [PATCH RFC 00/14] Accurate qgroup reserve framework Qu Wenruo
2015-09-08  8:37 ` [PATCH 01/19] btrfs: qgroup: New function declaration for new reserve implement Qu Wenruo
2015-09-08  8:37 ` [PATCH 02/19] btrfs: qgroup: Implement data_rsv_map init/free functions Qu Wenruo
2015-09-08  8:37 ` [PATCH 03/19] btrfs: qgroup: Introduce new function to search most left reserve range Qu Wenruo
2015-09-08  8:37 ` [PATCH 04/19] btrfs: qgroup: Introduce function to insert non-overlap " Qu Wenruo
2015-09-08  8:37 ` [PATCH 05/19] btrfs: qgroup: Introduce function to reserve data range per inode Qu Wenruo
2015-09-08  8:37 ` [PATCH 06/19] btrfs: qgroup: Introduce btrfs_qgroup_reserve_data function Qu Wenruo
2015-09-08  8:37 ` Qu Wenruo [this message]
2015-09-08  8:37 ` [PATCH 08/19] btrfs: qgroup: Introduce function to release/free reserved data range Qu Wenruo
2015-09-08  8:37 ` [PATCH 09/19] btrfs: delayed_ref: Add new function to record reserved space into delayed ref Qu Wenruo
2015-09-08  8:37 ` [PATCH 10/19] btrfs: delayed_ref: release and free qgroup reserved at proper timing Qu Wenruo
2015-09-08  8:37 ` [PATCH 11/19] btrfs: qgroup: Introduce new functions to reserve/free metadata Qu Wenruo
2015-09-08  8:37 ` [PATCH 12/19] btrfs: qgroup: Use new metadata reservation Qu Wenruo
2015-09-08  8:37 ` [PATCH 13/19] btrfs: extent-tree: Add new verions of btrfs_check_data_free_space Qu Wenruo
2015-09-08  8:37 ` [PATCH 14/19] btrfs: Switch to new check_data_free_space Qu Wenruo
2015-09-08  8:37 ` [PATCH 15/19] btrfs: fallocate: Add support to accurate qgroup reserve Qu Wenruo
2015-09-08  8:37 ` [PATCH 16/19] btrfs: extent-tree: Add new version of btrfs_delalloc_reserve_space Qu Wenruo
2015-09-08  8:37 ` [PATCH 17/19] btrfs: extent-tree: Use new __btrfs_delalloc_reserve_space function Qu Wenruo
2015-09-08  8:37 ` [PATCH 18/19] btrfs: qgroup: Cleanup old inaccurate facilities Qu Wenruo
2015-09-08  8:37 ` [PATCH 19/19] btrfs: qgroup: Add handler for NOCOW and inline Qu Wenruo
2015-09-08  8:56 [PATCH RFC 00/14] Accurate qgroup reserve framework Qu Wenruo
2015-09-08  9:02 ` [PATCH 07/19] btrfs: qgroup: Introduce function to release reserved range Qu Wenruo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1441701456-8034-8-git-send-email-quwenruo@cn.fujitsu.com \
    --to=quwenruo@cn.fujitsu.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.