cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: Andrew Price <anprice@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [PATCH 06/19] libgfs2: Add functions for finding free extents
Date: Tue,  2 Sep 2014 13:07:23 +0100	[thread overview]
Message-ID: <1409659656-23051-7-git-send-email-anprice@redhat.com> (raw)
In-Reply-To: <1409659656-23051-1-git-send-email-anprice@redhat.com>

Port gfs2_rbm_find and some functions which it depends on from the gfs2
kernel code. This will set the base for allocation of single-extent
files. The functions have been simplified where possible as libgfs2
doesn't have a concept of reservations for the time being.

Signed-off-by: Andrew Price <anprice@redhat.com>
---
 gfs2/libgfs2/rgrp.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gfs2/libgfs2/rgrp.h |   2 +
 2 files changed, 199 insertions(+)

diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 0f36b86..7063288 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -638,3 +638,200 @@ static int lgfs2_rbm_incr(struct lgfs2_rbm *rbm)
 	rbm->bii++;
 	return 0;
 }
+
+/**
+ * lgfs2_testbit - test a bit in the bitmaps
+ * @rbm: The bit to test
+ *
+ * Returns: The two bit block state of the requested bit
+ */
+static inline uint8_t lgfs2_testbit(const struct lgfs2_rbm *rbm)
+{
+	struct gfs2_bitmap *bi = rbm_bi(rbm);
+	const uint8_t *buffer = (uint8_t *)bi->bi_bh->b_data + bi->bi_offset;
+	const uint8_t *byte;
+	unsigned int bit;
+
+	byte = buffer + (rbm->offset / GFS2_NBBY);
+	bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
+
+	return (*byte >> bit) & GFS2_BIT_MASK;
+}
+
+/**
+ * lgfs2_unaligned_extlen - Look for free blocks which are not byte aligned
+ * @rbm: Position to search (value/result)
+ * @n_unaligned: Number of unaligned blocks to check
+ * @len: Decremented for each block found (terminate on zero)
+ *
+ * Returns: true if a non-free block is encountered
+ */
+static int lgfs2_unaligned_extlen(struct lgfs2_rbm *rbm, uint32_t n_unaligned, uint32_t *len)
+{
+	uint32_t n;
+	uint8_t res;
+
+	for (n = 0; n < n_unaligned; n++) {
+		res = lgfs2_testbit(rbm);
+		if (res != GFS2_BLKST_FREE)
+			return 1;
+		(*len)--;
+		if (*len == 0)
+			return 1;
+		if (lgfs2_rbm_incr(rbm))
+			return 1;
+	}
+
+	return 0;
+}
+
+static uint8_t *check_bytes8(const uint8_t *start, uint8_t value, unsigned bytes)
+{
+	while (bytes) {
+		if (*start != value)
+			return (void *)start;
+		start++;
+		bytes--;
+	}
+	return NULL;
+}
+
+/**
+ * lgfs2_free_extlen - Return extent length of free blocks
+ * @rbm: Starting position
+ * @len: Max length to check
+ *
+ * Starting@the block specified by the rbm, see how many free blocks
+ * there are, not reading more than len blocks ahead. This can be done
+ * using check_bytes8 when the blocks are byte aligned, but has to be done
+ * on a block by block basis in case of unaligned blocks. Also this
+ * function can cope with bitmap boundaries (although it must stop on
+ * a resource group boundary)
+ *
+ * Returns: Number of free blocks in the extent
+ */
+static uint32_t lgfs2_free_extlen(const struct lgfs2_rbm *rrbm, uint32_t len)
+{
+	struct lgfs2_rbm rbm = *rrbm;
+	uint32_t n_unaligned = rbm.offset & 3;
+	uint32_t size = len;
+	uint32_t bytes;
+	uint32_t chunk_size;
+	uint8_t *ptr, *start, *end;
+	uint64_t block;
+	struct gfs2_bitmap *bi;
+
+	if (n_unaligned &&
+	    lgfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len))
+		goto out;
+
+	n_unaligned = len & 3;
+	/* Start is now byte aligned */
+	while (len > 3) {
+		bi = rbm_bi(&rbm);
+		start = (uint8_t *)bi->bi_bh->b_data;
+		end = start + bi->bi_bh->sdp->bsize;
+		start += bi->bi_offset;
+		start += (rbm.offset / GFS2_NBBY);
+		bytes = (len / GFS2_NBBY) < (end - start) ? (len / GFS2_NBBY):(end - start);
+		ptr = check_bytes8(start, 0, bytes);
+		chunk_size = ((ptr == NULL) ? bytes : (ptr - start));
+		chunk_size *= GFS2_NBBY;
+		len -= chunk_size;
+		block = lgfs2_rbm_to_block(&rbm);
+		if (lgfs2_rbm_from_block(&rbm, block + chunk_size)) {
+			n_unaligned = 0;
+			break;
+		}
+		if (ptr) {
+			n_unaligned = 3;
+			break;
+		}
+		n_unaligned = len & 3;
+	}
+
+	/* Deal with any bits left over@the end */
+	if (n_unaligned)
+		lgfs2_unaligned_extlen(&rbm, n_unaligned, &len);
+out:
+	return size - len;
+}
+
+/**
+ * gfs2_rbm_find - Look for blocks of a particular state
+ * @rbm: Value/result starting position and final position
+ * @state: The state which we want to find
+ * @minext: Pointer to the requested extent length (NULL for a single block)
+ *          This is updated to be the actual reservation size.
+ *
+ * Returns: 0 on success, non-zero with errno == ENOSPC if there is no block of the requested state
+ */
+int lgfs2_rbm_find(struct lgfs2_rbm *rbm, uint8_t state, uint32_t *minext)
+{
+	int initial_bii;
+	uint32_t offset;
+	int n = 0;
+	int iters = rbm->rgd->ri.ri_length;
+	uint32_t extlen;
+
+	/* If we are not starting at the beginning of a bitmap, then we
+	 * need to add one to the bitmap count to ensure that we search
+	 * the starting bitmap twice.
+	 */
+	if (rbm->offset != 0)
+		iters++;
+
+	for (n = 0; n < iters; n++) {
+		struct gfs2_bitmap *bi = rbm_bi(rbm);
+		struct gfs2_buffer_head *bh = bi->bi_bh;
+		uint8_t *buf = (uint8_t *)bh->b_data + bi->bi_offset;
+		uint64_t block;
+		int ret;
+
+		if ((rbm->rgd->rg.rg_free < *minext) && (state == GFS2_BLKST_FREE))
+			goto next_bitmap;
+
+		offset = gfs2_bitfit(buf, bi->bi_len, rbm->offset, state);
+		if (offset == BFITNOENT)
+			goto next_bitmap;
+
+		rbm->offset = offset;
+		initial_bii = rbm->bii;
+		block = lgfs2_rbm_to_block(rbm);
+		extlen = 1;
+
+		if (*minext != 0)
+			extlen = lgfs2_free_extlen(rbm, *minext);
+
+		if (extlen >= *minext)
+			return 0;
+
+		ret = lgfs2_rbm_from_block(rbm, block + extlen);
+		if (ret == 0) {
+			n += (rbm->bii - initial_bii);
+			continue;
+		}
+
+		if (errno == E2BIG) {
+			rbm->bii = 0;
+			rbm->offset = 0;
+			n += (rbm->bii - initial_bii);
+			goto res_covered_end_of_rgrp;
+		}
+
+		return ret;
+
+next_bitmap:	/* Find next bitmap in the rgrp */
+		rbm->offset = 0;
+		rbm->bii++;
+		if (rbm->bii == rbm->rgd->ri.ri_length)
+			rbm->bii = 0;
+
+res_covered_end_of_rgrp:
+		if (rbm->bii == 0)
+			break;
+	}
+
+	errno = ENOSPC;
+	return 1;
+}
diff --git a/gfs2/libgfs2/rgrp.h b/gfs2/libgfs2/rgrp.h
index 384231e..1634fbc 100644
--- a/gfs2/libgfs2/rgrp.h
+++ b/gfs2/libgfs2/rgrp.h
@@ -44,4 +44,6 @@ static inline int lgfs2_rbm_eq(const struct lgfs2_rbm *rbm1, const struct lgfs2_
 	        (rbm1->offset == rbm2->offset);
 }
 
+extern int lgfs2_rbm_find(struct lgfs2_rbm *rbm, uint8_t state, uint32_t *minext);
+
 #endif /* __RGRP_DOT_H__ */
-- 
1.9.3



  parent reply	other threads:[~2014-09-02 12:07 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-02 12:07 [Cluster-devel] [PATCH 00/19] gfs2-utils: Introduce extent allocation and speed up journal creation Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 01/19] libgfs2: Keep a pointer to the sbd in lgfs2_rgrps_t Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 02/19] libgfs2: Move bitmap buffers inside struct gfs2_bitmap Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 03/19] libgfs2: Fix an impossible loop condition in gfs2_rgrp_read Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 04/19] libgfs2: Introduce struct lgfs2_rbm Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 05/19] libgfs2: Move struct _lgfs2_rgrps into rgrp.h Andrew Price
2014-09-02 12:07 ` Andrew Price [this message]
2014-09-03 10:17   ` [Cluster-devel] [PATCH 06/19] libgfs2: Add functions for finding free extents Steven Whitehouse
2014-09-03 12:13     ` Andrew Price
2014-09-03 12:24       ` Steven Whitehouse
2014-09-02 12:07 ` [Cluster-devel] [PATCH 07/19] tests: Add unit tests for the new extent search functions Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 08/19] libgfs2: Ignore an empty rgrp plan if a length is specified Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 09/19] libgfs2: Add back-pointer to rgrps in lgfs2_rgrp_t Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 10/19] libgfs2: Const-ify the parameters of print functions Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 11/19] libgfs2: Allow init_dinode to accept a preallocated bh Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 12/19] libgfs2: Add extent allocation functions Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 13/19] libgfs2: Add support for allocating entire rgrp headers Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 14/19] libgfs2: Write file metadata sequentially Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 15/19] libgfs2: Fix alignment in lgfs2_rgsize_for_data Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 16/19] libgfs2: Handle non-zero bitmaps in lgfs2_rgrp_write Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 17/19] libgfs2: Add a speedier journal data block writing function Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 18/19] libgfs2: Create jindex directory separately from journals Andrew Price
2014-09-02 12:07 ` [Cluster-devel] [PATCH 19/19] mkfs.gfs2: Improve journal creation performance Andrew Price
2014-09-02 14:06 ` [Cluster-devel] [PATCH 00/19] gfs2-utils: Introduce extent allocation and speed up journal creation Bob Peterson
2014-09-03 10:20 ` Steven Whitehouse

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=1409659656-23051-7-git-send-email-anprice@redhat.com \
    --to=anprice@redhat.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).