* [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation.
@ 2014-08-17 16:26 Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 1/7] reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space Ivan Shapovalov
` (7 more replies)
0 siblings, 8 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
This patch series implements FITRIM ioctl support in reiser4.
The FITRIM ioctl is supposed to be applied to any directory inside the target
filesystem. At least, this can be deduced from `fstrim` utility behavior on
mainstream filesystems (e. g. ext2/3/4).
The idea of implementation is per Edward's advices: FITRIM handler iteratively
grabs a portion of disk space, sequentially allocates extents within grabbed
space and commits the resulting atom. This way we avoid starving concurrent
processes of the disk space. This process is repeated until the partition has
been fully scanned and processed.
Points I'm really uncertain of:
- grabbing fixed amount of space (new BA_SOME_SPACE flag, grabs 25% of disk space)
- creation of empty atoms (reiser4_create_atom())
- handling of empty atoms in commit_current_atom()
v2: - fix PATCH 5/7 "reiser4: txnmgr: call reiser4_post_write_back_hook() for empty atoms."
* fix a typo
* release atom spinlock before calling reiser4_post_write_back_hook()
Ivan Shapovalov (7):
reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space.
reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction.
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: call reiser4_post_write_back_hook() for empty atoms.
reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories.
reiser4: batch discard support: actually implement the FITRIM ioctl handler.
fs/reiser4/block_alloc.c | 6 ++
fs/reiser4/block_alloc.h | 10 ++-
fs/reiser4/plugin/dir/dir.h | 2 +
fs/reiser4/plugin/file_ops.c | 62 ++++++++++++++++++
fs/reiser4/plugin/object.c | 6 +-
fs/reiser4/plugin/space/bitmap.c | 3 +-
fs/reiser4/super_ops.c | 131 +++++++++++++++++++++++++++++++++++++++
fs/reiser4/txnmgr.c | 57 +++++++++++------
fs/reiser4/txnmgr.h | 2 +
9 files changed, 255 insertions(+), 24 deletions(-)
--
2.0.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 1/7] reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 2/7] reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction Ivan Shapovalov
` (6 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
This is used for FITRIM ioctl which will iteratively grab, allocate and trim disk space
bit by bit to avoid starving the rest of system.
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/block_alloc.c | 6 ++++++
fs/reiser4/block_alloc.h | 5 ++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/fs/reiser4/block_alloc.c b/fs/reiser4/block_alloc.c
index d3d730c..8797b43 100644
--- a/fs/reiser4/block_alloc.c
+++ b/fs/reiser4/block_alloc.c
@@ -276,6 +276,12 @@ reiser4_grab(reiser4_context * ctx, __u64 count, reiser4_ba_flags_t flags)
free_blocks = sbinfo->blocks_free;
+ if (flags & BA_SOME_SPACE) {
+ /* Reserve 25% of all free space. */
+ count = free_blocks;
+ do_div(count, 4);
+ }
+
if ((use_reserved && free_blocks < count) ||
(!use_reserved && free_blocks < count + sbinfo->blocks_reserved)) {
ret = RETERR(-ENOSPC);
diff --git a/fs/reiser4/block_alloc.h b/fs/reiser4/block_alloc.h
index a4e98af..bfc6be9 100644
--- a/fs/reiser4/block_alloc.h
+++ b/fs/reiser4/block_alloc.h
@@ -79,7 +79,10 @@ enum reiser4_ba_flags {
BA_FORCE = (1 << 5),
/* use default start value for free blocks search. */
- BA_USE_DEFAULT_SEARCH_START = (1 << 6)
+ BA_USE_DEFAULT_SEARCH_START = (1 << 6),
+
+ /* reserve some fixed amount of space */
+ BA_SOME_SPACE = (1 << 7),
};
typedef enum reiser4_ba_flags reiser4_ba_flags_t;
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 2/7] reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 1/7] reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 3/7] reiser4: txnmgr: free allocated but unneeded atom in atom_begin_and_assign_to_txnh() Ivan Shapovalov
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/block_alloc.h | 5 +++--
fs/reiser4/plugin/space/bitmap.c | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/reiser4/block_alloc.h b/fs/reiser4/block_alloc.h
index bfc6be9..08b3941 100644
--- a/fs/reiser4/block_alloc.h
+++ b/fs/reiser4/block_alloc.h
@@ -51,9 +51,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;
- /* If direction = 1 allocate blocks in backward direction from the end
- * of disk to the beginning of disk. */
+ /* Allocate blocks only in backward direction starting from blk. */
unsigned int backward:1;
+ /* Allocate blocks only in forward direction starting from blk. */
+ unsigned int forward:1;
};
diff --git a/fs/reiser4/plugin/space/bitmap.c b/fs/reiser4/plugin/space/bitmap.c
index 3da3f6b..9beaf66 100644
--- a/fs/reiser4/plugin/space/bitmap.c
+++ b/fs/reiser4/plugin/space/bitmap.c
@@ -1127,7 +1127,8 @@ static int alloc_blocks_forward(reiser4_blocknr_hint *hint, int 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. */
- if (!(actual_len != 0 || hint->max_dist != 0 || search_start == 0)) {
+ if (actual_len == 0 && search_start != 0 &&
+ hint->max_dist == 0 && hint->forward == 0) {
/* next step is a scanning from 0 to search_start */
search_end = search_start;
search_start = 0;
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 3/7] reiser4: txnmgr: free allocated but unneeded atom in atom_begin_and_assign_to_txnh().
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 1/7] reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 2/7] reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 4/7] reiser4: txnmgr: add reiser4_create_atom() which creates an empty atom without capturing any nodes Ivan Shapovalov
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
It is unclear why it hasn't been done before, as there was a
corresponding notice, and such change apparently does not carry any side
effects.
Do this to avoid duplicating code in the next commit.
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/txnmgr.c | 20 +++++---------------
1 file changed, 5 insertions(+), 15 deletions(-)
diff --git a/fs/reiser4/txnmgr.c b/fs/reiser4/txnmgr.c
index d73ecb9..68070a9 100644
--- a/fs/reiser4/txnmgr.c
+++ b/fs/reiser4/txnmgr.c
@@ -709,6 +709,9 @@ static int atom_begin_and_assign_to_txnh(txn_atom ** atom_alloc, txn_handle * tx
return RETERR(-ENOMEM);
}
+ atom = *atom_alloc;
+ *atom_alloc = NULL;
+
/* and, also, txnmgr spin lock should be taken before jnode and txnh
locks. */
mgr = &get_super_private(reiser4_get_current_sb())->tmgr;
@@ -717,18 +720,14 @@ static int atom_begin_and_assign_to_txnh(txn_atom ** atom_alloc, txn_handle * tx
/* Check whether new atom still needed */
if (txnh->atom != NULL) {
- /* NOTE-NIKITA probably it is rather better to free
- * atom_alloc here than thread it up to reiser4_try_capture() */
-
spin_unlock_txnh(txnh);
spin_unlock_txnmgr(mgr);
+ kmem_cache_free(_atom_slab, atom);
+
return -E_REPEAT;
}
- atom = *atom_alloc;
- *atom_alloc = NULL;
-
atom_init(atom);
assert("jmacd-17", atom_isclean(atom));
@@ -2031,15 +2030,6 @@ int reiser4_try_capture(jnode *node, znode_lock_mode lock_mode,
goto repeat;
}
- /* free extra atom object that was possibly allocated by
- try_capture_block().
-
- Do this before acquiring jnode spin lock to
- minimize time spent under lock. --nikita */
- if (atom_alloc != NULL) {
- kmem_cache_free(_atom_slab, atom_alloc);
- }
-
if (ret != 0) {
if (ret == -E_BLOCK) {
assert("nikita-3360",
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 4/7] reiser4: txnmgr: add reiser4_create_atom() which creates an empty atom without capturing any nodes.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
` (2 preceding siblings ...)
2014-08-17 16:26 ` [RFC] [PATCHv2 3/7] reiser4: txnmgr: free allocated but unneeded atom in atom_begin_and_assign_to_txnh() Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 5/7] reiser4: txnmgr: call reiser4_post_write_back_hook() also for empty atoms Ivan Shapovalov
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/txnmgr.c | 24 ++++++++++++++++++++++++
fs/reiser4/txnmgr.h | 2 ++
2 files changed, 26 insertions(+)
diff --git a/fs/reiser4/txnmgr.c b/fs/reiser4/txnmgr.c
index 68070a9..2862940 100644
--- a/fs/reiser4/txnmgr.c
+++ b/fs/reiser4/txnmgr.c
@@ -2050,6 +2050,30 @@ int reiser4_try_capture(jnode *node, znode_lock_mode lock_mode,
return ret;
}
+/* This function ensures that the current transcrash has an atom without
+ * capturing anything. If needed, an empty atom is created and assigned.
+ */
+int reiser4_create_atom(void)
+{
+ txn_atom *atom_alloc = NULL;
+ txn_handle *txnh = get_current_context()->trans;
+ int ret;
+
+ do {
+ spin_lock_txnh(txnh);
+ if (txnh->atom == NULL) {
+ spin_unlock_txnh(txnh);
+ /* assign empty atom to the txnh and repeat */
+ ret = atom_begin_and_assign_to_txnh(&atom_alloc, txnh);
+ } else {
+ spin_unlock_txnh(txnh);
+ ret = 0;
+ }
+ } while (ret == -E_REPEAT);
+
+ return ret;
+}
+
static void release_two_atoms(txn_atom *one, txn_atom *two)
{
spin_unlock_atom(one);
diff --git a/fs/reiser4/txnmgr.h b/fs/reiser4/txnmgr.h
index 72b84a2..50a1f54 100644
--- a/fs/reiser4/txnmgr.h
+++ b/fs/reiser4/txnmgr.h
@@ -437,6 +437,8 @@ extern void reiser4_uncapture_jnode(jnode *);
extern int reiser4_capture_inode(struct inode *);
extern int reiser4_uncapture_inode(struct inode *);
+extern int reiser4_create_atom(void);
+
extern txn_atom *get_current_atom_locked_nocheck(void);
#if REISER4_DEBUG
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 5/7] reiser4: txnmgr: call reiser4_post_write_back_hook() also for empty atoms.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
` (3 preceding siblings ...)
2014-08-17 16:26 ` [RFC] [PATCHv2 4/7] reiser4: txnmgr: add reiser4_create_atom() which creates an empty atom without capturing any nodes Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 6/7] reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories Ivan Shapovalov
` (2 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
The atoms generated by reiser4_trim_fs(), despite being empty (zero
capture_count), still have non-empty delete sets which have to be
processed.
Also the empty atom check has been moved after changing atom stage
to ASTAGE_PRE_COMMIT, because reiser4_post_write_back_hook() requires
atom to be unlocked.
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/txnmgr.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/fs/reiser4/txnmgr.c b/fs/reiser4/txnmgr.c
index 2862940..2efdf85 100644
--- a/fs/reiser4/txnmgr.c
+++ b/fs/reiser4/txnmgr.c
@@ -1064,9 +1064,6 @@ static int commit_current_atom(long *nr_submitted, txn_atom ** atom)
return RETERR(-E_REPEAT);
}
- if ((*atom)->capture_count == 0)
- goto done;
-
/* Up to this point we have been flushing and after flush is called we
return -E_REPEAT. Now we can commit. We cannot return -E_REPEAT
at this point, commit should be successful. */
@@ -1074,6 +1071,14 @@ static int commit_current_atom(long *nr_submitted, txn_atom ** atom)
ON_DEBUG(((*atom)->committer = current));
spin_unlock_atom(*atom);
+ if ((*atom)->capture_count == 0) {
+ /* Process the atom's delete set.
+ * Even if the atom has no captured nodes, the delete set may
+ * still be non-empty (see e. g. reiser4_trim_fs()). */
+ reiser4_post_write_back_hook();
+ goto done;
+ }
+
ret = current_atom_complete_writes();
if (ret)
return ret;
@@ -1100,8 +1105,8 @@ static int commit_current_atom(long *nr_submitted, txn_atom ** atom)
reiser4_invalidate_list(ATOM_WB_LIST(*atom));
assert("zam-927", list_empty(&(*atom)->inodes));
+done:
spin_lock_atom(*atom);
- done:
reiser4_atom_set_stage(*atom, ASTAGE_DONE);
ON_DEBUG((*atom)->committer = NULL);
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 6/7] reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
` (4 preceding siblings ...)
2014-08-17 16:26 ` [RFC] [PATCHv2 5/7] reiser4: txnmgr: call reiser4_post_write_back_hook() also for empty atoms Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 7/7] reiser4: batch discard support: actually implement the FITRIM ioctl handler Ivan Shapovalov
2014-08-17 20:25 ` [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Edward Shishkin
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/plugin/dir/dir.h | 2 ++
fs/reiser4/plugin/file_ops.c | 27 +++++++++++++++++++++++++++
fs/reiser4/plugin/object.c | 6 +++++-
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/fs/reiser4/plugin/dir/dir.h b/fs/reiser4/plugin/dir/dir.h
index 4a91ebe..5eb7bda 100644
--- a/fs/reiser4/plugin/dir/dir.h
+++ b/fs/reiser4/plugin/dir/dir.h
@@ -10,6 +10,8 @@
#include <linux/fs.h>*/
+long reiser4_ioctl_dir_common(struct file *file, unsigned int cmd, unsigned long arg);
+
/* declarations of functions implementing HASHED_DIR_PLUGIN_ID dir plugin */
/* "hashed" directory methods of dir plugin */
diff --git a/fs/reiser4/plugin/file_ops.c b/fs/reiser4/plugin/file_ops.c
index 466da64..65e2b02 100644
--- a/fs/reiser4/plugin/file_ops.c
+++ b/fs/reiser4/plugin/file_ops.c
@@ -107,6 +107,33 @@ int reiser4_sync_file_common(struct file *file, loff_t start, loff_t end, int da
return 0;
}
+/** reiser4_ioctl_dir_common - ioctl of struct file_operations for typical directory
+ */
+long reiser4_ioctl_dir_common(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct inode *inode = file_inode(file);
+ struct super_block *super = inode->i_sb;
+ reiser4_context *ctx;
+ int ret;
+
+ ctx = reiser4_init_context(super);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ switch (cmd) {
+ case FITRIM:
+ warning("intelfx-62", "FITRIM ioctl not implemented");
+ /* fall-through to -ENOSYS */
+
+ default:
+ ret = RETERR(-ENOSYS);
+ break;
+ }
+
+ reiser4_exit_context(ctx);
+ return ret;
+}
+
/*
* Local variables:
* c-indentation-style: "K&R"
diff --git a/fs/reiser4/plugin/object.c b/fs/reiser4/plugin/object.c
index 553f1e2..ce09a8a 100644
--- a/fs/reiser4/plugin/object.c
+++ b/fs/reiser4/plugin/object.c
@@ -251,7 +251,11 @@ static struct file_operations directory_f_ops = {
.read = generic_read_dir,
.iterate = reiser4_iterate_common,
.release = reiser4_release_dir_common,
- .fsync = reiser4_sync_common
+ .fsync = reiser4_sync_common,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = reiser4_ioctl_dir_common,
+#endif
+ .unlocked_ioctl = reiser4_ioctl_dir_common
};
static struct address_space_operations directory_a_ops = {
.writepage = writepage_bugop,
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC] [PATCHv2 7/7] reiser4: batch discard support: actually implement the FITRIM ioctl handler.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
` (5 preceding siblings ...)
2014-08-17 16:26 ` [RFC] [PATCHv2 6/7] reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories Ivan Shapovalov
@ 2014-08-17 16:26 ` Ivan Shapovalov
2014-08-17 20:25 ` [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Edward Shishkin
7 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 16:26 UTC (permalink / raw)
To: reiserfs-devel; +Cc: edward.shishkin, Ivan Shapovalov
It works in an iterative way, grabbing some fixed amount of space and allocating
blocks until grabbed space is exhausted or partition's end is reached.
Blocks are scheduled for discard by allocating them and immediately adding them
to the atom's delete set, which is read and processed at atom commit time.
After reaching the allocation stop condition, the atom is force-committed and,
if the allocation has been stopped due to grabbed space exhaustion (not due to
reaching end of partition), another iteration happens.
Signed-off-by: Ivan Shapovalov <intelfx100@gmail.com>
---
fs/reiser4/plugin/file_ops.c | 41 +++++++++++++-
fs/reiser4/super_ops.c | 131 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+), 3 deletions(-)
diff --git a/fs/reiser4/plugin/file_ops.c b/fs/reiser4/plugin/file_ops.c
index 65e2b02..7686406 100644
--- a/fs/reiser4/plugin/file_ops.c
+++ b/fs/reiser4/plugin/file_ops.c
@@ -8,6 +8,9 @@
#include "../inode.h"
#include "object.h"
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+
/* file operations */
/* implementation of vfs's llseek method of struct file_operations for
@@ -20,6 +23,9 @@ loff_t reiser4_llseek_dir_common(struct file *, loff_t, int origin);
*/
int reiser4_iterate_common(struct file *, struct dir_context *);
+/* this function is implemented in super_ops.c */
+int reiser4_trim_fs(struct super_block *super, struct fstrim_range* range);
+
/**
* reiser4_release_dir_common - release of struct file_operations
* @inode: inode of released file
@@ -121,9 +127,38 @@ long reiser4_ioctl_dir_common(struct file *file, unsigned int cmd, unsigned long
return PTR_ERR(ctx);
switch (cmd) {
- case FITRIM:
- warning("intelfx-62", "FITRIM ioctl not implemented");
- /* fall-through to -ENOSYS */
+ case FITRIM: {
+ struct request_queue *q = bdev_get_queue(super->s_bdev);
+ struct fstrim_range range;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ ret = RETERR(-EPERM);
+ break;
+ }
+
+ if (!blk_queue_discard(q)) {
+ ret = RETERR(-EOPNOTSUPP);
+ break;
+ }
+
+ if (copy_from_user(&range, (struct fstrim_range __user *)arg,
+ sizeof(range))) {
+ ret = RETERR(-EFAULT);
+ break;
+ }
+
+ range.minlen = max((unsigned int)range.minlen,
+ q->limits.discard_granularity);
+
+ ret = reiser4_trim_fs(super, &range);
+
+ if (copy_to_user((struct fstrim_range __user *)arg, &range,
+ sizeof(range))) {
+ ret = RETERR(-EFAULT);
+ }
+
+ break;
+ }
default:
ret = RETERR(-ENOSYS);
diff --git a/fs/reiser4/super_ops.c b/fs/reiser4/super_ops.c
index bcd7fd6..0048e83 100644
--- a/fs/reiser4/super_ops.c
+++ b/fs/reiser4/super_ops.c
@@ -14,6 +14,7 @@
#include <linux/debugfs.h>
#include <linux/backing-dev.h>
#include <linux/module.h>
+#include <linux/delay.h>
/* slab cache for inodes */
static struct kmem_cache *inode_cache;
@@ -471,6 +472,136 @@ static int reiser4_show_options(struct seq_file *m, struct dentry *dentry)
return 0;
}
+/**
+ * reiser4_trim_fs - discards all free space in a filesystem
+ * @super: the superblock of filesystem to discard
+ * @range: parameters for discarding
+ *
+ * Called from @reiser4_ioctl_dir_common().
+ */
+int reiser4_trim_fs(struct super_block *super, struct fstrim_range* range)
+{
+ reiser4_blocknr_hint hint;
+ reiser4_block_nr start, end, len, minlen, discarded_count = 0;
+ reiser4_context *ctx;
+ struct super_block *sb;
+ txn_atom *atom;
+ int ret, finished = 0;
+
+ reiser4_blocknr_hint_init(&hint);
+ ctx = get_current_context();
+ sb = ctx->super;
+
+ /*
+ * Configure the hint for block allocator.
+ * We will allocate in forward direction only.
+ */
+
+ hint.blk = range->start >> sb->s_blocksize_bits;
+ hint.max_dist = range->len >> sb->s_blocksize_bits;
+ hint.block_stage = BLOCK_GRABBED;
+ hint.forward = 1;
+
+ end = hint.blk + hint.max_dist;
+ minlen = range->minlen >> sb->s_blocksize_bits;
+
+ /*
+ * We will perform the process in iterations in order not to starve
+ * the rest of the system of disk space.
+ * Each iteration we will grab some space (using the BA_SOME_SPACE
+ * flag, which currently grabs 25% of free disk space), create an empty
+ * atom and sequentially allocate extents of disk space while we can
+ * afford it (i. e. while we haven't reached the end of partition AND
+ * while we haven't exhausted the grabbed space).
+ */
+ do {
+ /*
+ * Grab some sane amount of space.
+ * We will allocate blocks until end of the partition or until
+ * the grabbed space is exhausted.
+ */
+ ret = reiser4_grab_reserved(super, 0, BA_CAN_COMMIT | BA_SOME_SPACE);
+ if (ret != 0)
+ goto out;
+ if (ctx->grabbed_blocks == 0)
+ goto out;
+
+ /*
+ * We will not capture anything, so we need an empty atom.
+ */
+ ret = reiser4_create_atom();
+ if (ret != 0)
+ goto out;
+
+ while (ctx->grabbed_blocks != 0) {
+ /*
+ * Allocate no more than is grabbed.
+ * FIXME: use minlen.
+ */
+ len = ctx->grabbed_blocks;
+ ret = reiser4_alloc_blocks(&hint, &start, &len, 0 /* flags */);
+ if (ret == -ENOSPC)
+ break;
+ if (ret != 0)
+ goto out;
+
+ /*
+ * Update the hint in order for the next scan to start
+ * right after the newly allocated extent.
+ */
+ hint.blk = start + len;
+ hint.max_dist = end - hint.blk;
+
+ /*
+ * Mark the newly allocated extent for deallocation.
+ * Discard happens on deallocation.
+ */
+ ret = reiser4_dealloc_blocks(&start, &len, BLOCK_NOT_COUNTED, BA_DEFER);
+ if (ret != 0)
+ goto out;
+
+ /*
+ * FIXME: get the actual discarded block count,
+ * accounting for speculative discard of extent heads and tails.
+ *
+ * PRIORITY: LOW because we have already allocated all
+ * possible space, so allocations of heads/tails will
+ * fail unless there is a concurrent process reclaiming
+ * space.
+ */
+ discarded_count += len;
+ }
+
+ assert("intelfx-64", (ret == 0) || (ret == -ENOSPC));
+
+ if (ret == -ENOSPC) {
+ ret = 0;
+ finished = 1;
+ }
+
+ /*
+ * Extents marked for deallocation are discarded here, as part
+ * of committing current atom.
+ */
+ atom = get_current_atom_locked();
+ spin_lock_txnh(ctx->trans);
+ force_commit_atom(ctx->trans);
+ all_grabbed2free();
+ grab_space_enable();
+ } while (!finished);
+
+out:
+ reiser4_release_reserved(super);
+ reiser4_blocknr_hint_done(&hint);
+
+ /*
+ * Update the statistics.
+ */
+ range->len = discarded_count << sb->s_blocksize_bits;
+
+ return ret;
+}
+
struct super_operations reiser4_super_operations = {
.alloc_inode = reiser4_alloc_inode,
.destroy_inode = reiser4_destroy_inode,
--
2.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation.
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
` (6 preceding siblings ...)
2014-08-17 16:26 ` [RFC] [PATCHv2 7/7] reiser4: batch discard support: actually implement the FITRIM ioctl handler Ivan Shapovalov
@ 2014-08-17 20:25 ` Edward Shishkin
2014-08-17 20:29 ` Ivan Shapovalov
7 siblings, 1 reply; 10+ messages in thread
From: Edward Shishkin @ 2014-08-17 20:25 UTC (permalink / raw)
To: Ivan Shapovalov, reiserfs-devel
Great, thanks!
I'll take a look at leisure.
What is the status of this code? Did you test it?
Edward.
On 08/17/2014 06:26 PM, Ivan Shapovalov wrote:
> This patch series implements FITRIM ioctl support in reiser4.
>
> The FITRIM ioctl is supposed to be applied to any directory inside the target
> filesystem. At least, this can be deduced from `fstrim` utility behavior on
> mainstream filesystems (e. g. ext2/3/4).
>
> The idea of implementation is per Edward's advices: FITRIM handler iteratively
> grabs a portion of disk space, sequentially allocates extents within grabbed
> space and commits the resulting atom. This way we avoid starving concurrent
> processes of the disk space. This process is repeated until the partition has
> been fully scanned and processed.
>
> Points I'm really uncertain of:
> - grabbing fixed amount of space (new BA_SOME_SPACE flag, grabs 25% of disk space)
> - creation of empty atoms (reiser4_create_atom())
> - handling of empty atoms in commit_current_atom()
>
> v2: - fix PATCH 5/7 "reiser4: txnmgr: call reiser4_post_write_back_hook() for empty atoms."
> * fix a typo
> * release atom spinlock before calling reiser4_post_write_back_hook()
>
> Ivan Shapovalov (7):
> reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space.
> reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction.
> 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: call reiser4_post_write_back_hook() for empty atoms.
> reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories.
> reiser4: batch discard support: actually implement the FITRIM ioctl handler.
>
> fs/reiser4/block_alloc.c | 6 ++
> fs/reiser4/block_alloc.h | 10 ++-
> fs/reiser4/plugin/dir/dir.h | 2 +
> fs/reiser4/plugin/file_ops.c | 62 ++++++++++++++++++
> fs/reiser4/plugin/object.c | 6 +-
> fs/reiser4/plugin/space/bitmap.c | 3 +-
> fs/reiser4/super_ops.c | 131 +++++++++++++++++++++++++++++++++++++++
> fs/reiser4/txnmgr.c | 57 +++++++++++------
> fs/reiser4/txnmgr.h | 2 +
> 9 files changed, 255 insertions(+), 24 deletions(-)
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation.
2014-08-17 20:25 ` [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Edward Shishkin
@ 2014-08-17 20:29 ` Ivan Shapovalov
0 siblings, 0 replies; 10+ messages in thread
From: Ivan Shapovalov @ 2014-08-17 20:29 UTC (permalink / raw)
To: Edward Shishkin; +Cc: reiserfs-devel
[-- Attachment #1: Type: text/plain, Size: 3035 bytes --]
On Sunday 17 August 2014 at 22:25:07, Edward Shishkin wrote:
> Great, thanks!
> I'll take a look at leisure.
> What is the status of this code? Did you test it?
The v1 does not compile and is bogus.
The v2 works for me; tested 1) in idle and 2) simultaneously with
while :; do rm -rf *; git reset --hard; done
on the Linux source tree on the same partition, ten times in a row.
No corruptions so far, however, there has been only one testing session.
I think I'll schedule a hourly fstrim to all partitions involved.
--
Ivan Shapovalov / intelfx /
>
> Edward.
>
>
> On 08/17/2014 06:26 PM, Ivan Shapovalov wrote:
> > This patch series implements FITRIM ioctl support in reiser4.
> >
> > The FITRIM ioctl is supposed to be applied to any directory inside the target
> > filesystem. At least, this can be deduced from `fstrim` utility behavior on
> > mainstream filesystems (e. g. ext2/3/4).
> >
> > The idea of implementation is per Edward's advices: FITRIM handler iteratively
> > grabs a portion of disk space, sequentially allocates extents within grabbed
> > space and commits the resulting atom. This way we avoid starving concurrent
> > processes of the disk space. This process is repeated until the partition has
> > been fully scanned and processed.
> >
> > Points I'm really uncertain of:
> > - grabbing fixed amount of space (new BA_SOME_SPACE flag, grabs 25% of disk space)
> > - creation of empty atoms (reiser4_create_atom())
> > - handling of empty atoms in commit_current_atom()
> >
> > v2: - fix PATCH 5/7 "reiser4: txnmgr: call reiser4_post_write_back_hook() for empty atoms."
> > * fix a typo
> > * release atom spinlock before calling reiser4_post_write_back_hook()
> >
> > Ivan Shapovalov (7):
> > reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space.
> > reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction.
> > 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: call reiser4_post_write_back_hook() for empty atoms.
> > reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories.
> > reiser4: batch discard support: actually implement the FITRIM ioctl handler.
> >
> > fs/reiser4/block_alloc.c | 6 ++
> > fs/reiser4/block_alloc.h | 10 ++-
> > fs/reiser4/plugin/dir/dir.h | 2 +
> > fs/reiser4/plugin/file_ops.c | 62 ++++++++++++++++++
> > fs/reiser4/plugin/object.c | 6 +-
> > fs/reiser4/plugin/space/bitmap.c | 3 +-
> > fs/reiser4/super_ops.c | 131 +++++++++++++++++++++++++++++++++++++++
> > fs/reiser4/txnmgr.c | 57 +++++++++++------
> > fs/reiser4/txnmgr.h | 2 +
> > 9 files changed, 255 insertions(+), 24 deletions(-)
> >
>
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 213 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-08-17 20:29 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-17 16:26 [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 1/7] reiser4: block_alloc: add BA_SOME_SPACE flag for grabbing a fixed amount of space Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 2/7] reiser4: block_alloc: add a "forward" parameter to reiser4_blocknr_hint to allocate blocks only in forward direction Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 3/7] reiser4: txnmgr: free allocated but unneeded atom in atom_begin_and_assign_to_txnh() Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 4/7] reiser4: txnmgr: add reiser4_create_atom() which creates an empty atom without capturing any nodes Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 5/7] reiser4: txnmgr: call reiser4_post_write_back_hook() also for empty atoms Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 6/7] reiser4: batch discard support: add a dummy FITRIM ioctl handler for directories Ivan Shapovalov
2014-08-17 16:26 ` [RFC] [PATCHv2 7/7] reiser4: batch discard support: actually implement the FITRIM ioctl handler Ivan Shapovalov
2014-08-17 20:25 ` [RFC] [PATCHv2 0/7] reiser4: batch discard support (FITRIM ioctl): initial implementation Edward Shishkin
2014-08-17 20:29 ` Ivan Shapovalov
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).