By using the v_flags field of the nilfs_argv struct, it is possible to
communicate additional information to the kernel. This patch defines
two new flags, which are to be used with the nilfs_clean_segments
function.
NILFS_CLEAN_SEGMENTS_DEFAULT: Normal GC operation
NILFS_CLEAN_SEGMENTS_UPDATE_SEGUSG: Do not move any blocks, just update
the segment usage metadata
Additionally this patch implements a simple check in
nilfs_reclaim_segment. If the number of free blocks that can be gained
by cleaning the segments is below the threshold of minblocks, it sets
the NILFS_CLEAN_SEGMENTS_UPDATE_SEGUSG flag. This causes the kernel to
leave the segment alone, not move any blocks, and only update the
SUFILE.
This is useful, because if the gain of cleaning a segment is very low,
it is better to leave it alone and try cleaning a different segment.
Signed-off-by: Andreas Rohner <[email protected]>
---
include/nilfs.h | 2 +-
include/nilfs2_fs.h | 6 ++++++
lib/gc.c | 16 ++++++++++++++--
lib/nilfs.c | 3 ++-
4 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/include/nilfs.h b/include/nilfs.h
index 56286a9..5ca8bec 100644
--- a/include/nilfs.h
+++ b/include/nilfs.h
@@ -304,7 +304,7 @@ ssize_t nilfs_get_vinfo(const struct nilfs *, struct
nilfs_vinfo *, size_t);
ssize_t nilfs_get_bdescs(const struct nilfs *, struct nilfs_bdesc *, size_t);
int nilfs_clean_segments(struct nilfs *, struct nilfs_vdesc *, size_t,
struct nilfs_period *, size_t, __u64 *, size_t,
- struct nilfs_bdesc *, size_t, __u64 *, size_t);
+ struct nilfs_bdesc *, size_t, __u64 *, size_t, int);
int nilfs_sync(const struct nilfs *, nilfs_cno_t *);
int nilfs_resize(struct nilfs *nilfs, off_t size);
int nilfs_set_alloc_range(struct nilfs *nilfs, off_t start, off_t end);
diff --git a/include/nilfs2_fs.h b/include/nilfs2_fs.h
index e674f44..1ac558f 100644
--- a/include/nilfs2_fs.h
+++ b/include/nilfs2_fs.h
@@ -731,6 +731,12 @@ struct nilfs_cpmode {
__u32 cm_pad;
};
+/* values for v_flags */
+enum {
+ NILFS_CLEAN_SEGMENTS_DEFAULT,
+ NILFS_CLEAN_SEGMENTS_UPDATE_SEGUSG,
+};
+
/**
* struct nilfs_argv - argument vector
* @v_base: pointer on data array from userspace
diff --git a/lib/gc.c b/lib/gc.c
index 0b0e2d6..cbae0f3 100644
--- a/lib/gc.c
+++ b/lib/gc.c
@@ -616,6 +616,8 @@ ssize_t nilfs_reclaim_segment(struct nilfs *nilfs,
struct nilfs_vector *vdescv, *bdescv, *periodv, *vblocknrv;
sigset_t sigset, oldset, waitset;
ssize_t n, ret = -1;
+ __u32 freeblocks;
+ int cleaning_flags = NILFS_CLEAN_SEGMENTS_DEFAULT;
if (nsegs == 0)
return 0;
@@ -678,6 +680,13 @@ ssize_t nilfs_reclaim_segment(struct nilfs *nilfs,
goto out_lock;
}
+ freeblocks = (nilfs_get_blocks_per_segment(nilfs) * n)
+ - (nilfs_vector_get_size(vdescv)
+ + nilfs_vector_get_size(bdescv));
+
+ if (freeblocks < minblocks * n)
+ cleaning_flags = NILFS_CLEAN_SEGMENTS_UPDATE_SEGUSG;
+
ret = nilfs_clean_segments(nilfs,
nilfs_vector_get_data(vdescv),
nilfs_vector_get_size(vdescv),
@@ -687,12 +696,15 @@ ssize_t nilfs_reclaim_segment(struct nilfs *nilfs,
nilfs_vector_get_size(vblocknrv),
nilfs_vector_get_data(bdescv),
nilfs_vector_get_size(bdescv),
- segnums, n);
+ segnums, n, cleaning_flags);
if (ret < 0) {
nilfs_gc_logger(LOG_ERR, "cannot clean segments: %s",
strerror(errno));
} else {
- ret = n;
+ if (cleaning_flags == NILFS_CLEAN_SEGMENTS_UPDATE_SEGUSG)
+ ret = -EGCTRYAGAIN;
+ else
+ ret = n;
}
out_lock:
diff --git a/lib/nilfs.c b/lib/nilfs.c
index ebe50b8..50eed5e 100644
--- a/lib/nilfs.c
+++ b/lib/nilfs.c
@@ -627,7 +627,7 @@ int nilfs_clean_segments(struct nilfs *nilfs,
struct nilfs_period *periods, size_t nperiods,
__u64 *vblocknrs, size_t nvblocknrs,
struct nilfs_bdesc *bdescs, size_t nbdescs,
- __u64 *segnums, size_t nsegs)
+ __u64 *segnums, size_t nsegs, int flags)
{
struct nilfs_argv argv[5];
@@ -639,6 +639,7 @@ int nilfs_clean_segments(struct nilfs *nilfs,
argv[0].v_base = (unsigned long)vdescs;
argv[0].v_nmembs = nvdescs;
argv[0].v_size = sizeof(struct nilfs_vdesc);
+ argv[0].v_flags = flags;
argv[1].v_base = (unsigned long)periods;
argv[1].v_nmembs = nperiods;
argv[1].v_size = sizeof(struct nilfs_period);
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html