On Saturday 13 December 2014 at 00:00:36, Ivan Shapovalov wrote: > [...] > > Ivan Shapovalov (10): > reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space. > reiser4: block_alloc: add a "monotonic_forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction. > reiser4: block_alloc: move block accounting by pre-commit hook into block_alloc.c and document BA_DEFER behavior. > reiser4: txnmgr: free allocated but unneeded atom in atom_begin_and_assign_to_txnh(). > reiser4: txnmgr: add reiser4_create_atom() which creates an empty atom without capturing any nodes. > reiser4: txnmgr: move "empty atom" shortcut slightly below. > reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories. > reiser4: batch discard support: actually implement the FITRIM ioctl handler. > reiser4: block_alloc: add a "min_len" parameter to reiser4_blocknr_hint to limit allocated extent length from below. > reiser4: batch discard support: honor minimal extent length passed from the userspace. > > [...] This is a diff between v3 and v4, for ease of reviewing. diff --git a/fs/reiser4/block_alloc.c b/fs/reiser4/block_alloc.c index 1632f78..549cc0a 100644 --- a/fs/reiser4/block_alloc.c +++ b/fs/reiser4/block_alloc.c @@ -264,7 +264,7 @@ int reiser4_check_block_counters(const struct super_block *super) static int reiser4_grab(reiser4_context * ctx, __u64 count, reiser4_ba_flags_t flags) { - __u64 free_blocks; + __u64 allowed_blocks; int ret = 0, use_reserved = flags & BA_RESERVED; reiser4_super_info_data *sbinfo; @@ -280,15 +280,24 @@ reiser4_grab(reiser4_context * ctx, __u64 count, reiser4_ba_flags_t flags) spin_lock_reiser4_super(sbinfo); - free_blocks = sbinfo->blocks_free; + allowed_blocks = use_reserved ? sbinfo->blocks_free + : sbinfo->blocks_free - sbinfo->blocks_reserved; if (flags & BA_SOME_SPACE) { - /* Reserve 25% of all free space. */ - count = free_blocks >> 2; - } + /* Reserve 25% of all free space */ + if (allowed_blocks == 0) { + /* No space at all */ + ret = RETERR(-ENOSPC); + goto unlock_and_ret; + } - if ((use_reserved && free_blocks < count) || - (!use_reserved && free_blocks < count + sbinfo->blocks_reserved)) { + count = allowed_blocks >> 2; + if (count == 0) { + /* Less than 4 free blocks */ + count = allowed_blocks; + } + } else if (count > allowed_blocks) { + /* Not enough space */ ret = RETERR(-ENOSPC); goto unlock_and_ret; } @@ -989,6 +998,19 @@ reiser4_check_blocks(const reiser4_block_nr * start, /* BA_FORMATTED bit is only used when BA_DEFER in not present: it is used to distinguish blocks allocated for unformatted and formatted nodes */ +/* if BA_DEFER is enabled, @target_stage and other @flags are ignored. + * + * @target_stage is implied to be BLOCK_NOT_COUNTED. + * (assumption is used in reiser4_post_write_back_hook() and apply_dset()) + * + * @flags are implied to have BA_PERMANENT. + * (assumption is used in reiser4_pre_commit_hook() which counts deallocated + * blocks) + * + * That is, if a deferred deallocation is done after reiser4_pre_commit_hook(), + * then BA_PERMANENT is implied to be disabled. + */ + int reiser4_dealloc_blocks(const reiser4_block_nr * start, const reiser4_block_nr * len, @@ -1080,10 +1102,39 @@ reiser4_dealloc_blocks(const reiser4_block_nr * start, return 0; } +/* an actor for counting blocks that are going to be deallocated */ +static int +count_dset_blocks(txn_atom * atom, const reiser4_block_nr * start, + const reiser4_block_nr * len, void *data) +{ + reiser4_block_nr *blocks_freed_p = data; + + if (len != NULL) { + (*blocks_freed_p) += *len; + } else { + (*blocks_freed_p)++; + } + return 0; +} + /* wrappers for block allocator plugin methods */ int reiser4_pre_commit_hook(void) { - assert("zam-502", get_current_super_private() != NULL); + reiser4_block_nr blocks_freed = 0; + reiser4_super_info_data *sbinfo = get_current_super_private(); + txn_atom *atom = get_current_atom_locked(); + + assert("zam-502", sbinfo != NULL); + + assert("zam-876", atom->stage == ASTAGE_PRE_COMMIT); + spin_unlock_atom(atom); + + atom_dset_deferred_apply(atom, count_dset_blocks, &blocks_freed, 0); + + spin_lock_reiser4_super(sbinfo); + sbinfo->blocks_free_committed += blocks_freed - atom->nr_blocks_allocated; + spin_unlock_reiser4_super(sbinfo); + sa_pre_commit_hook(); return 0; } diff --git a/fs/reiser4/block_alloc.h b/fs/reiser4/block_alloc.h index 16f9810..ac1a747 100644 --- a/fs/reiser4/block_alloc.h +++ b/fs/reiser4/block_alloc.h @@ -53,10 +53,10 @@ struct reiser4_blocknr_hint { /* block allocator assumes that blocks, which will be mapped to disk, are in this specified block_stage */ block_stage_t block_stage; - /* Allocate blocks only in backward direction starting from blk. */ + /* allocate blocks in backward direction */ unsigned int backward:1; - /* Allocate blocks only in forward direction starting from blk. */ - unsigned int forward:1; + /* allocate blocks only in forward direction starting from blk */ + unsigned int monotonic_forward:1; }; diff --git a/fs/reiser4/plugin/space/bitmap.c b/fs/reiser4/plugin/space/bitmap.c index 8309cf9..7c0a1e4 100644 --- a/fs/reiser4/plugin/space/bitmap.c +++ b/fs/reiser4/plugin/space/bitmap.c @@ -1129,16 +1129,17 @@ static int alloc_blocks_forward(reiser4_blocknr_hint *hint, int needed, actual_len = bitmap_alloc_forward(&search_start, &search_end, min_len, needed); - /* There is only one bitmap search if max_dist was specified or first - pass was from the beginning of the bitmap. We also do one pass for - scanning bitmap in backward direction. */ + /* There is only one bitmap search if max_dist was specified, first + pass was from the beginning of the bitmap, or if the monotonic flag + has been set. Otherwise we also do one pass for scanning bitmap in + backward direction. */ if (actual_len == 0 && search_start != 0 && - hint->max_dist == 0 && hint->forward == 0) { + hint->max_dist == 0 && !hint->monotonic_forward) { /* next step is a scanning from 0 to search_start */ search_end = search_start; search_start = 0; actual_len = - bitmap_alloc_forward(&search_start, &search_end, 1, needed); + bitmap_alloc_forward(&search_start, &search_end, min_len, needed); } if (actual_len == 0) return RETERR(-ENOSPC); @@ -1331,15 +1332,13 @@ static void cond_add_to_overwrite_set(txn_atom * atom, jnode * node) pages in a single-linked list */ static int apply_dset_to_commit_bmap(txn_atom * atom, const reiser4_block_nr * start, - const reiser4_block_nr * len, void *data) + const reiser4_block_nr * len, void *data UNUSED_ARG) { bmap_nr_t bmap; bmap_off_t offset; int ret; - long long *blocks_freed_p = data; - struct bitmap_node *bnode; struct super_block *sb = reiser4_get_current_sb(); @@ -1375,11 +1374,8 @@ apply_dset_to_commit_bmap(txn_atom * atom, const reiser4_block_nr * start, assert("zam-443", offset + *len <= bmap_bit_count(sb->s_blocksize)); reiser4_clear_bits(data, offset, (bmap_off_t) (offset + *len)); - - (*blocks_freed_p) += *len; } else { reiser4_clear_bit(offset, data); - (*blocks_freed_p)++; } bnode_set_commit_crc(bnode, bnode_calc_crc(bnode, sb->s_blocksize)); @@ -1402,8 +1398,6 @@ int reiser4_pre_commit_hook_bitmap(void) struct super_block *super = reiser4_get_current_sb(); txn_atom *atom; - long long blocks_freed = 0; - atom = get_current_atom_locked(); assert("zam-876", atom->stage == ASTAGE_PRE_COMMIT); spin_unlock_atom(atom); @@ -1469,19 +1463,7 @@ int reiser4_pre_commit_hook_bitmap(void) } } - atom_dset_deferred_apply(atom, apply_dset_to_commit_bmap, &blocks_freed, 0); - - blocks_freed -= atom->nr_blocks_allocated; - - { - reiser4_super_info_data *sbinfo; - - sbinfo = get_super_private(super); - - spin_lock_reiser4_super(sbinfo); - sbinfo->blocks_free_committed += blocks_freed; - spin_unlock_reiser4_super(sbinfo); - } + atom_dset_deferred_apply(atom, apply_dset_to_commit_bmap, NULL, 0); return 0; } diff --git a/fs/reiser4/super_ops.c b/fs/reiser4/super_ops.c index a98b192..2c98959 100644 --- a/fs/reiser4/super_ops.c +++ b/fs/reiser4/super_ops.c @@ -503,7 +503,7 @@ int reiser4_trim_fs(struct super_block *super, struct fstrim_range* range) hint.max_dist = range->len >> super->s_blocksize_bits; hint.min_len = range->minlen >> super->s_blocksize_bits; hint.block_stage = BLOCK_GRABBED; - hint.forward = 1; + hint.monotonic_forward = 1; end = hint.blk + hint.max_dist; @@ -535,14 +535,27 @@ int reiser4_trim_fs(struct super_block *super, struct fstrim_range* range) if (ret != 0) goto out; - while (ctx->grabbed_blocks != 0) { + do { /* * Allocate no more than is grabbed. + * + * NOTE: we do not use BA_PERMANENT in our allocations + * even though we deallocate with BA_DEFER. + * Our atom takes the "shortcut" in commit_current_atom() + * and as such the pre-commit hook is not applied. */ + assert("intelfx-75", ctx->grabbed_blocks != 0); len = ctx->grabbed_blocks; ret = reiser4_alloc_blocks(&hint, &start, &len, 0 /* flags */); - if (ret == -ENOSPC) + if (ret == -ENOSPC) { + /* + * We have reached the end of the filesystem -- + * no more blocks to discard. + */ + ret = 0; + finished = 1; break; + } if (ret != 0) goto out; @@ -557,7 +570,7 @@ int reiser4_trim_fs(struct super_block *super, struct fstrim_range* range) * Mark the newly allocated extent for deallocation. * Discard happens on deallocation. */ - ret = reiser4_dealloc_blocks(&start, &len, BLOCK_NOT_COUNTED, BA_DEFER); + ret = reiser4_dealloc_blocks(&start, &len, 0, BA_DEFER); if (ret != 0) goto out; @@ -571,23 +584,18 @@ int reiser4_trim_fs(struct super_block *super, struct fstrim_range* range) * space. */ discarded_count += len; - } + } while (ctx->grabbed_blocks != 0); - assert("intelfx-64", (ret == 0) || (ret == -ENOSPC)); - - if (ret == -ENOSPC) { - ret = 0; - finished = 1; - } + assert("intelfx-64", ret == 0); /* * Extents marked for deallocation are discarded here, as part * of committing current atom. */ + all_grabbed2free(); atom = get_current_atom_locked(); spin_lock_txnh(ctx->trans); force_commit_atom(ctx->trans); - all_grabbed2free(); grab_space_enable(); } while (!finished); diff --git a/fs/reiser4/txnmgr.c b/fs/reiser4/txnmgr.c index 2efdf85..5084722 100644 --- a/fs/reiser4/txnmgr.c +++ b/fs/reiser4/txnmgr.c @@ -1071,6 +1071,10 @@ static int commit_current_atom(long *nr_submitted, txn_atom ** atom) ON_DEBUG(((*atom)->committer = current)); spin_unlock_atom(*atom); + ret = current_atom_complete_writes(); + if (ret) + return ret; + if ((*atom)->capture_count == 0) { /* Process the atom's delete set. * Even if the atom has no captured nodes, the delete set may @@ -1079,10 +1083,6 @@ static int commit_current_atom(long *nr_submitted, txn_atom ** atom) goto done; } - ret = current_atom_complete_writes(); - if (ret) - return ret; - assert("zam-906", list_empty(ATOM_WB_LIST(*atom))); /* isolate critical code path which should be executed by only one Thanks, -- Ivan Shapovalov / intelfx /
Attachment:
signature.asc
Description: This is a digitally signed message part.