This allows to allocate exact count of blocks at exact position. In particular, 'precise discard' implementation will need this interface to perform padding of the discard extents. Signed-off-by: Ivan Shapovalov <intelfx100@xxxxxxxxx> --- fs/reiser4/block_alloc.c | 36 ++++++++++++ fs/reiser4/block_alloc.h | 3 + fs/reiser4/plugin/space/bitmap.c | 94 +++++++++++++++++++++++-------- fs/reiser4/plugin/space/bitmap.h | 3 + fs/reiser4/plugin/space/space_allocator.h | 10 +++- 5 files changed, 120 insertions(+), 26 deletions(-) diff --git a/fs/reiser4/block_alloc.c b/fs/reiser4/block_alloc.c index be1a795..fc4cf04 100644 --- a/fs/reiser4/block_alloc.c +++ b/fs/reiser4/block_alloc.c @@ -759,6 +759,42 @@ int reiser4_alloc_blocks(reiser4_blocknr_hint * hint, reiser4_block_nr * blk, return ret; } +/* This is a version of reiser4_alloc_blocks() for use in special conditions, + * where an allocation must have exact length and position. + * + * It does not use reiser4_blocknr_hint; instead, all parameters are passed + * directly. + */ +int reiser4_alloc_blocks_exact(const reiser4_block_nr * blk, + const reiser4_block_nr * len, + block_stage_t stage, reiser4_ba_flags_t flags) +{ + int ret; + reiser4_context *ctx; + + assert("intelfx-70", blk != NULL); + assert("intelfx-71", len != NULL); + + ctx = get_current_context(); + + ret = reiser4_alloc_blocks_pre(*len, stage, flags); + + if (ret != 0) { + return ret; + } + + ret = sa_alloc_blocks_exact(reiser4_get_space_allocator(ctx->super), + blk, len); + + if (ret == 0) { + reiser4_alloc_blocks_post_success(*blk, *len, stage, flags); + } else { + reiser4_alloc_blocks_post_failure(*len, stage); + } + + return ret; +} + /** * ask block allocator for some unformatted blocks */ diff --git a/fs/reiser4/block_alloc.h b/fs/reiser4/block_alloc.h index a4e98af..a09be1d 100644 --- a/fs/reiser4/block_alloc.h +++ b/fs/reiser4/block_alloc.h @@ -109,6 +109,9 @@ int reiser4_alloc_blocks(reiser4_blocknr_hint * hint, int reiser4_dealloc_blocks(const reiser4_block_nr *, const reiser4_block_nr *, block_stage_t, reiser4_ba_flags_t flags); +int reiser4_alloc_blocks_exact(const reiser4_block_nr * start, + const reiser4_block_nr * len, + block_stage_t stage, reiser4_ba_flags_t flags); static inline int reiser4_alloc_block(reiser4_blocknr_hint * hint, reiser4_block_nr * start, diff --git a/fs/reiser4/plugin/space/bitmap.c b/fs/reiser4/plugin/space/bitmap.c index 3da3f6b..7d15619 100644 --- a/fs/reiser4/plugin/space/bitmap.c +++ b/fs/reiser4/plugin/space/bitmap.c @@ -1222,8 +1222,14 @@ void reiser4_dealloc_blocks_bitmap(reiser4_space_allocator * allocator, release_and_unlock_bnode(bnode); } +typedef enum { + CHECK_FREE, + CHECK_FREE_AND_ALLOC, + CHECK_BUSY +} check_blocks_mode; + static int check_blocks_one_bitmap(bmap_nr_t bmap, bmap_off_t start_offset, - bmap_off_t end_offset, int desired) + bmap_off_t end_offset, check_blocks_mode mode) { struct super_block *super = reiser4_get_current_sb(); struct bitmap_node *bnode = get_bnode(super, bmap); @@ -1236,14 +1242,29 @@ static int check_blocks_one_bitmap(bmap_nr_t bmap, bmap_off_t start_offset, assert("nikita-2216", jnode_is_loaded(bnode->wjnode)); - if (desired) { + switch (mode) { + case CHECK_BUSY: ret = reiser4_find_next_zero_bit(bnode_working_data(bnode), - end_offset, start_offset) - >= end_offset; - } else { - ret = reiser4_find_next_set_bit(bnode_working_data(bnode), end_offset, start_offset) >= end_offset; + + break; + + case CHECK_FREE: + case CHECK_FREE_AND_ALLOC: + ret = reiser4_find_next_set_bit(bnode_working_data(bnode), + end_offset, start_offset) + >= end_offset; + + if (mode == CHECK_FREE_AND_ALLOC && ret) { + reiser4_set_bits(bnode_working_data(bnode), + start_offset, end_offset); + } + + break; + + default: + impossible("intelfx-67", "wrong block check/alloc mode: %d", mode); } release_and_unlock_bnode(bnode); @@ -1251,9 +1272,8 @@ static int check_blocks_one_bitmap(bmap_nr_t bmap, bmap_off_t start_offset, return ret; } -/* plugin->u.space_allocator.check_blocks(). */ -int reiser4_check_blocks_bitmap(const reiser4_block_nr * start, - const reiser4_block_nr * len, int desired) +static int check_blocks_bitmap(reiser4_block_nr start, reiser4_block_nr len, + check_blocks_mode mode) { struct super_block *super = reiser4_get_current_sb(); @@ -1262,21 +1282,13 @@ int reiser4_check_blocks_bitmap(const reiser4_block_nr * start, bmap_off_t offset, end_offset; const bmap_off_t max_offset = bmap_bit_count(super->s_blocksize); - assert("intelfx-9", start != NULL); - assert("intelfx-10", ergo(len != NULL, *len > 0)); + assert("intelfx-10", len > 0); - if (len != NULL) { - check_block_range(start, len); - end = *start + *len - 1; - } else { - /* on next line, end is used as temporary len for check_block_range() */ - end = 1; check_block_range(start, &end); - end = *start; - } + check_block_range(&start, &len); + parse_blocknr(&start, &bmap, &offset); - parse_blocknr(start, &bmap, &offset); - - if (end == *start) { + end = start + len - 1; + if (end == start) { end_bmap = bmap; end_offset = offset; } else { @@ -1288,11 +1300,45 @@ int reiser4_check_blocks_bitmap(const reiser4_block_nr * start, assert("intelfx-5", ergo(end_bmap == bmap, end_offset >= offset)); for (; bmap < end_bmap; bmap++, offset = 0) { - if (!check_blocks_one_bitmap(bmap, offset, max_offset, desired)) { + if (!check_blocks_one_bitmap(bmap, offset, max_offset, mode)) { return 0; } } - return check_blocks_one_bitmap(bmap, offset, end_offset, desired); + return check_blocks_one_bitmap(bmap, offset, end_offset, mode); +} + +/* plugin->u.space_allocator.alloc_blocks_exact() */ +int reiser4_alloc_blocks_exact_bitmap(reiser4_space_allocator * allocator, + const reiser4_block_nr * start, + const reiser4_block_nr * len) +{ + int ret; + + assert("intelfx-66", start != NULL); + + if (len != NULL) + ret = check_blocks_bitmap(*start, *len, CHECK_FREE_AND_ALLOC); + else + ret = check_blocks_bitmap(*start, 1, CHECK_FREE_AND_ALLOC); + + if (ret == 0) + return RETERR(-ENOSPC); + else + return 0; +} + +/* plugin->u.space_allocator.check_blocks(). */ +int reiser4_check_blocks_bitmap(const reiser4_block_nr * start, + const reiser4_block_nr * len, int desired) +{ + check_blocks_mode mode = desired ? CHECK_BUSY : CHECK_FREE; + + assert("intelfx-9", start != NULL); + + if (len != NULL) + return check_blocks_bitmap (*start, *len, mode); + else + return check_blocks_bitmap (*start, 1, mode); } /* conditional insertion of @node into atom's overwrite set if it was not there */ diff --git a/fs/reiser4/plugin/space/bitmap.h b/fs/reiser4/plugin/space/bitmap.h index 4590498..9679f3c 100644 --- a/fs/reiser4/plugin/space/bitmap.h +++ b/fs/reiser4/plugin/space/bitmap.h @@ -19,6 +19,9 @@ extern int reiser4_alloc_blocks_bitmap(reiser4_space_allocator *, reiser4_blocknr_hint *, int needed, reiser4_block_nr * start, reiser4_block_nr * len); +extern int reiser4_alloc_blocks_exact_bitmap(reiser4_space_allocator *, + const reiser4_block_nr * start, + const reiser4_block_nr * len); extern int reiser4_check_blocks_bitmap(const reiser4_block_nr *, const reiser4_block_nr *, int); extern void reiser4_dealloc_blocks_bitmap(reiser4_space_allocator *, diff --git a/fs/reiser4/plugin/space/space_allocator.h b/fs/reiser4/plugin/space/space_allocator.h index 71bfd11..7567bda 100644 --- a/fs/reiser4/plugin/space/space_allocator.h +++ b/fs/reiser4/plugin/space/space_allocator.h @@ -29,9 +29,15 @@ static inline void sa_dealloc_blocks (reiser4_space_allocator * al, reiser4_bloc reiser4_dealloc_blocks_##allocator (al, start, len); \ } \ \ -static inline int sa_check_blocks (const reiser4_block_nr * start, const reiser4_block_nr * end, int desired) \ +static inline int sa_check_blocks (const reiser4_block_nr * start, const reiser4_block_nr * end, int desired) \ { \ - return reiser4_check_blocks_##allocator (start, end, desired); \ + return reiser4_check_blocks_##allocator (start, end, desired); \ +} \ + \ +static inline int sa_alloc_blocks_exact (reiser4_space_allocator * al, const reiser4_block_nr * start, \ + const reiser4_block_nr * len) \ +{ \ + return reiser4_alloc_blocks_exact_##allocator (al, start, len); \ } \ \ static inline void sa_pre_commit_hook (void) \ -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe reiserfs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html