linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: tytso@mit.edu, darrick.wong@oracle.com
Cc: linux-ext4@vger.kernel.org
Subject: [PATCH 23/34] libext2fs: find/alloc a range of empty blocks
Date: Sat, 13 Sep 2014 15:13:44 -0700	[thread overview]
Message-ID: <20140913221344.13646.61680.stgit@birch.djwong.org> (raw)
In-Reply-To: <20140913221112.13646.3873.stgit@birch.djwong.org>

Provide a function that, given a goal pblk and a range, will try to
find a run of free blocks to satisfy the allocation.  By default the
function will look anywhere in the filesystem for the run, though this
can be constrained with optional flags.  One flag indicates that the
range must start at the goal block; the other flag indicates that we
should not return a range shorter than len.

v2: Add a second function to allocate a range of blocks.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/alloc.c  |  141 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/ext2fs/ext2fs.h |   11 ++++
 2 files changed, 152 insertions(+)


diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index e58c01b..7a5245e 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -26,6 +26,16 @@
 #include "ext2_fs.h"
 #include "ext2fs.h"
 
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define dbg_printf(f, a...)  do {printf(f, ## a); fflush(stdout); } while (0)
+#else
+# define dbg_printf(f, a...)
+#endif
+
 /*
  * Clear the uninit block bitmap flag if necessary
  */
@@ -313,3 +323,134 @@ blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino)
 		group = group & ~((1 << (log_flex)) - 1);
 	return ext2fs_group_first_block2(fs, group);
 }
+
+/*
+ * Starting at _goal_, scan around the filesystem to find a run of free blocks
+ * that's at least _len_ blocks long.  Possible flags:
+ * - EXT2_NEWRANGE_EXACT_GOAL: The range of blocks must start at _goal_.
+ * - EXT2_NEWRANGE_MIN_LENGTH: do not return a allocation shorter than _len_.
+ * - EXT2_NEWRANGE_ZERO_BLOCKS: Zero blocks pblk to pblk+plen before returning.
+ *
+ * The starting block is returned in _pblk_ and the length is returned via
+ * _plen_.  The blocks are not marked in the bitmap; the caller must mark
+ * however much of the returned run they actually use, hopefully via
+ * ext2fs_block_alloc_stats_range().
+ *
+ * This function can return a range that is longer than what was requested.
+ */
+errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal,
+			   blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk,
+			   blk64_t *plen)
+{
+	errcode_t retval;
+	blk64_t start, end, b;
+	int looped = 0;
+	blk64_t max_blocks = ext2fs_blocks_count(fs->super);
+
+	dbg_printf("%s: flags=0x%x goal=%llu len=%llu\n", __func__, flags,
+		   goal, len);
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+	if (len == 0 || (flags & ~EXT2_NEWRANGE_ALL_FLAGS))
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (!map)
+		map = fs->block_map;
+	if (!map)
+		return EXT2_ET_NO_BLOCK_BITMAP;
+	if (!goal || goal >= ext2fs_blocks_count(fs->super))
+		goal = fs->super->s_first_data_block;
+
+	start = goal;
+	while (!looped || start <= goal) {
+		retval = ext2fs_find_first_zero_block_bitmap2(map, start,
+							      max_blocks - 1,
+							      &start);
+		if (retval == ENOENT) {
+			/*
+			 * If there are no free blocks beyond the starting
+			 * point, try scanning the whole filesystem, unless the
+			 * user told us only to allocate from _goal_, or if
+			 * we're already scanning the whole filesystem.
+			 */
+			if (flags & EXT2_NEWRANGE_FIXED_GOAL ||
+			    start == fs->super->s_first_data_block)
+				goto fail;
+			start = fs->super->s_first_data_block;
+			continue;
+		} else if (retval)
+			goto errout;
+
+		if (flags & EXT2_NEWRANGE_FIXED_GOAL && start != goal)
+			goto fail;
+
+		b = min(start + len - 1, max_blocks - 1);
+		retval =  ext2fs_find_first_set_block_bitmap2(map, start, b,
+							      &end);
+		if (retval == ENOENT)
+			end = b + 1;
+		else if (retval)
+			goto errout;
+
+		if (!(flags & EXT2_NEWRANGE_MIN_LENGTH) ||
+		    (end - start) >= len) {
+			/* Success! */
+			*pblk = start;
+			*plen = end - start;
+			dbg_printf("%s: new_range goal=%llu--%llu "
+				   "blk=%llu--%llu %llu\n",
+				   __func__, goal, goal + len - 1,
+				   *pblk, *pblk + *plen - 1, *plen);
+
+			for (b = start; b < end;
+			     b += fs->super->s_blocks_per_group)
+				clear_block_uninit(fs,
+						ext2fs_group_of_blk2(fs, b));
+			return 0;
+		}
+
+		if (flags & EXT2_NEWRANGE_FIXED_GOAL)
+			goto fail;
+		start = end;
+		if (start >= max_blocks) {
+			if (looped)
+				goto fail;
+			looped = 1;
+			start = fs->super->s_first_data_block;
+		}
+	}
+
+fail:
+	retval = EXT2_ET_BLOCK_ALLOC_FAIL;
+errout:
+	return retval;
+}
+
+errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal,
+			     blk_t len, blk64_t *ret)
+{
+	int newr_flags = EXT2_NEWRANGE_MIN_LENGTH;
+	errcode_t retval;
+	blk64_t plen;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+	if (len == 0 || (flags & ~EXT2_ALLOCRANGE_ALL_FLAGS))
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	if (flags & EXT2_ALLOCRANGE_FIXED_GOAL)
+		newr_flags |= EXT2_NEWRANGE_FIXED_GOAL;
+
+	retval = ext2fs_new_range(fs, newr_flags, goal, len, NULL, ret, &plen);
+	if (retval)
+		return retval;
+
+	if (plen < len)
+		return EXT2_ET_BLOCK_ALLOC_FAIL;
+
+	if (flags & EXT2_ALLOCRANGE_ZERO_BLOCKS) {
+		retval = ext2fs_zero_blocks2(fs, *ret, len, NULL, NULL);
+		if (retval)
+			return retval;
+	}
+
+	ext2fs_block_alloc_stats_range(fs, *ret, len, +1);
+	return retval;
+}
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index dcc3ec4..8d3ade8 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -697,6 +697,17 @@ extern void ext2fs_set_alloc_block_callback(ext2_filsys fs,
 							      blk64_t goal,
 							      blk64_t *ret));
 blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino);
+#define EXT2_NEWRANGE_FIXED_GOAL	(0x1)
+#define EXT2_NEWRANGE_MIN_LENGTH	(0x2)
+#define EXT2_NEWRANGE_ALL_FLAGS		(0x3)
+errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal,
+			   blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk,
+			   blk64_t *plen);
+#define EXT2_ALLOCRANGE_FIXED_GOAL	(0x1)
+#define EXT2_ALLOCRANGE_ZERO_BLOCKS	(0x2)
+#define EXT2_ALLOCRANGE_ALL_FLAGS	(0x3)
+errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal,
+			     blk_t len, blk64_t *ret);
 
 /* alloc_sb.c */
 extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,


  parent reply	other threads:[~2014-09-13 22:13 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-13 22:11 [PATCH 00/34] e2fsprogs Summer 2014 patchbomb, part 6 Darrick J. Wong
2014-09-13 22:11 ` [PATCH 01/34] e2fsck: offer to clear overlapping extents Darrick J. Wong
2014-09-19  1:45   ` Theodore Ts'o
2014-09-13 22:11 ` [PATCH 02/34] e2fsck: fix sliding the directory block down on bigalloc Darrick J. Wong
2014-09-19  1:45   ` Theodore Ts'o
2014-09-13 22:11 ` [PATCH 03/34] misc: zero s_jnl_blocks when adding journal online or removing external journal Darrick J. Wong
2014-09-19  1:45   ` Theodore Ts'o
2014-09-13 22:11 ` [PATCH 04/34] libext2fs: ext2fs_new_block2() should call alloc_block hook Darrick J. Wong
2014-09-13 22:11 ` [PATCH 05/34] debugfs: manage needs_recover feature when messing with the journal Darrick J. Wong
2014-09-19  6:01   ` Theodore Ts'o
2014-09-13 22:11 ` [PATCH 06/34] debugfs: add LIBINTL to debugfs link command Darrick J. Wong
2014-09-19  4:46   ` Theodore Ts'o
2014-10-17 21:07     ` Darrick J. Wong
2014-10-18 16:10       ` Theodore Ts'o
2014-09-13 22:11 ` [PATCH 07/34] ext2fs: add readahead method to improve scanning Darrick J. Wong
2014-09-19 16:15   ` Theodore Ts'o
2014-09-13 22:12 ` [PATCH 08/34] libext2fs/e2fsck: provide routines to read-ahead metadata Darrick J. Wong
2014-09-13 22:12 ` [PATCH 09/34] e2fsck: read-ahead metadata during passes 1, 2, and 4 Darrick J. Wong
2014-09-13 22:12 ` [PATCH 10/34] dumpe2fs: provide a machine-readable group-only mode Darrick J. Wong
2014-09-19 16:17   ` Theodore Ts'o
2014-09-13 22:12 ` [PATCH 11/34] dumpe2fs: output cleanup Darrick J. Wong
2014-09-19 16:22   ` Theodore Ts'o
2014-09-19 20:00     ` Darrick J. Wong
2014-10-13 18:04       ` Darrick J. Wong
2014-09-13 22:12 ` [PATCH 12/34] misc: move check_plausibility into a separate file Darrick J. Wong
2014-09-19 22:16   ` Theodore Ts'o
2014-09-13 22:12 ` [PATCH 13/34] misc: add plausibility checks to debugfs/tune2fs/dumpe2fs/e2fsck Darrick J. Wong
2014-09-19 23:00   ` Theodore Ts'o
2014-09-13 22:12 ` [PATCH 14/34] misc: use libmagic when libblkid can't identify something Darrick J. Wong
2014-09-21  5:29   ` Theodore Ts'o
2014-09-13 22:12 ` [PATCH 15/34] libext2fs: support BLKZEROOUT/FALLOC_FL_ZERO_RANGE in ext2fs_zero_blocks Darrick J. Wong
2014-09-22  2:51   ` Theodore Ts'o
2014-09-29 18:58     ` Darrick J. Wong
2014-10-14  2:58   ` Darrick J. Wong
2014-10-18 16:32   ` Theodore Ts'o
2014-10-20 23:37     ` Darrick J. Wong
2014-09-13 22:12 ` [PATCH 16/34] libext2fs/e2fsck: refactor everyone who writes zero blocks to disk Darrick J. Wong
2014-10-13 10:09   ` Theodore Ts'o
2014-10-13 17:09     ` Darrick J. Wong
2014-09-13 22:13 ` [PATCH 17/34] libext2fs: support allocating uninit blocks in bmap2() Darrick J. Wong
2014-10-13 14:35   ` Theodore Ts'o
2014-10-13 16:56     ` Darrick J. Wong
2014-10-13 18:34       ` Darrick J. Wong
2014-09-13 22:13 ` [PATCH 18/34] libext2fs: file IO routines should handle uninit blocks Darrick J. Wong
2014-09-13 22:13 ` [PATCH 19/34] resize2fs: convert fs to and from 64bit mode Darrick J. Wong
2014-09-14 17:34   ` TR Reardon
2014-09-14 17:50     ` Darrick J. Wong
2014-09-13 22:13 ` [PATCH 20/34] resize2fs: adjust reserved_gdt_blocks when changing group descriptor size Darrick J. Wong
2014-09-13 22:13 ` [PATCH 21/34] tests: test resize2fs 32->64 and 64->32bit conversion code Darrick J. Wong
2014-09-13 22:13 ` [PATCH 22/34] libext2fs: find inode goal when allocating blocks Darrick J. Wong
2014-09-13 22:13 ` Darrick J. Wong [this message]
2014-09-13 22:13 ` [PATCH 24/34] libext2fs: add new hooks to support large allocations Darrick J. Wong
2014-09-13 22:14 ` [PATCH 25/34] libext2fs: implement fallocate Darrick J. Wong
2014-09-13 22:14 ` [PATCH 26/34] libext2fs: use fallocate for creating journals and hugefiles Darrick J. Wong
2014-09-13 22:14 ` [PATCH 27/34] debugfs: implement fallocate Darrick J. Wong
2014-09-13 22:14 ` [PATCH 28/34] tests: test debugfs punch command Darrick J. Wong
2014-09-19 16:26   ` Theodore Ts'o
2014-09-19 20:01     ` Darrick J. Wong
2014-09-13 22:14 ` [PATCH 30/34] fuse2fs: translate ACL structures Darrick J. Wong
2014-09-13 22:14 ` [PATCH 31/34] fuse2fs: handle 64-bit dates correctly Darrick J. Wong
2014-09-13 22:14 ` [PATCH 32/34] fuse2fs: implement fallocate Darrick J. Wong
2014-09-13 22:15 ` [PATCH 34/34] tests: enable using fuse2fs with metadata checksum test Darrick J. Wong
2014-09-14 17:19 ` [PATCH 35/34] e2fsck: free bh when descriptor block checksum fails Darrick J. Wong
2014-09-14 19:11   ` Eric Sandeen
2014-09-19  1:46     ` Theodore Ts'o
2014-09-18 19:09 ` [PATCH 36/34] misc: fix Coverity complaints Darrick J. Wong
2014-09-19  1:47   ` Theodore Ts'o

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=20140913221344.13646.61680.stgit@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /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).