Re: [PATCHv4 00/10] reiser4: batch discard support (FITRIM ioctl): initial implementation.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.


[Index of Archives]     [Linux File System Development]     [Linux BTRFS]     [Linux NFS]     [Linux Filesystems]     [Ext4 Filesystem]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Resources]

  Powered by Linux