Skip to contentSkip to conversation

nilfs-utils: shortcut for certain GC operations

PATCH Superseded Andreas Rohner 2 participants 21 messages Jan 27, 2014 – Jan 30, 2014 12 messages not in the archive

Subsystems (2)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v3 cover nilfs-utils: shortcut for certain GC operations

Hi,

This is the third version of this patch set. It basically fixes a lot of bugs.

v2->v3
* Alignment in nilfs_suinfo_update
* Add missing comments
* nilfs2: Extra validity checks in nilfs_sufile_set_suinfo
* nilfs2: Update sh_ncleansegs, sh_ndirtysegs if flags change
* nilfs2: Fix bugs in nilfs_sufile_set_suinfo
* nilfs2: Use vmalloc instead of ioctl_wrap_copy
* nilfs-utils: Separate nilfs_relaim_segments_with_threshold
* nilfs-utils: Allow different units for min_reclaimable_blocks
* nilfs-utils: Introduce flag to disable the optimization
* nilfs-utils: Disable optimization if kernel retruns ENOTTY
* nilfs-utils: Remove EGCTRYAGAIN error return code
* nilfs-utils: Rename option to min_reclaimable_blocks v1->v2
* Implementation of NILFS_IOCTL_SET_SUINFO
* Added mc_min_free_blocks_threshold config option (if clean segments < min_clean_segments)
* Added new command line param for nilfs-clean
* Update man- and config-file

This patch set adds an optimized version of nilfs_reclaim_segments, which has an additional parameter min_reclaimable. This parameter specifies the minimum number of reclaimable blocks in a segment, before it can be cleaned. If a segment is below this threshold, it is considered to be not worth cleaning, because all the live blocks would need to be moved to a new segment, which is expensive, and the number of reclaimable blocks is too low. But it is still necessary to update the segment usage information to turn the old segment into a new one.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

Additionally new options are introduced for the configuration file and nilfs-clean to allow the user to specify the threshold.

This is potentially useful for all gc policies, but it is especially beneficial for the timestamp policy. Lets assume for example a NILFS2 volume with 20% static files and lets assume these static files are in the oldest segments. The current timestamp policy will select the oldest segments and, since the data is static, move them mostly unchanged to new segments. After a while they will become the oldest segments again. Then timestamp will move them again. These moving operations are expensive and unnecessary.

The benchmarks are currently running. I will give you the results shortly.

Regards,
Andreas Rohner

---
Andreas Rohner (4):
nilfs-utils: cldconfig add an option to set min. reclaimable blocks
nilfs-utils: nilfs-clean add cmdline param min-reclaimable-blocks
nilfs-utils: add suport for NILFS_IOCTL_SET_SUINFO ioctl
nilfs-utils: add optimized version of nilfs_reclaim_segments

 include/nilfs.h                   |   9 +-
 include/nilfs2_fs.h               |  43 ++++++++++
 include/nilfs_cleaner.h           |  19 +++--
 include/nilfs_gc.h                |   4 +
 lib/gc.c                          | 112 ++++++++++++++++++++-----
 lib/nilfs.c                       |  60 ++++++++++++++
 man/nilfs-clean.8                 |   4 +
 man/nilfs_cleanerd.conf.5         |  22 +++++
 sbin/cleanerd/cldconfig.c         | 168 ++++++++++++++++++++++++++++----------
 sbin/cleanerd/cldconfig.h         |   8 ++
 sbin/cleanerd/cleanerd.c          |  39 ++++++++-
 sbin/cleanerd/nilfs_cleanerd.conf |  13 +++
 sbin/nilfs-clean/nilfs-clean.c    |  44 ++++++++--
 13 files changed, 466 insertions(+), 79 deletions(-)
Signature · 6 lines
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

A message that is not in the archive (sent off-list or not yet received): [email protected]

#2 lore raw

PATCH v3 1/4 nilfs-utils: cldconfig add an option to set min. reclaimable blocks

With this option the user can specify the minimum number of reclaimable blocks of a segment, before it can be cleaned. This is a threshold for the GC to prevent needless moving of data. If there are less reclaimable blocks in a segment than the specified number, the GC will abort and try again with a different segment.

If there are less clean segments than min_clean_segments, mc_min_reclaimable_blocks is used instead of min_reclaimable_blocks. This allows for more flexibility in configuring the GC.

The number of blocks can be specified in percent of a segment or in bytes.

If the use_set_suinfo switch is not set, the optimization is completely disabled.

---
 include/nilfs.h                   |   7 +-
 lib/nilfs.c                       |  28 +++++++
 man/nilfs_cleanerd.conf.5         |  22 +++++
 sbin/cleanerd/cldconfig.c         | 168 ++++++++++++++++++++++++++++----------
 sbin/cleanerd/cldconfig.h         |   8 ++
 sbin/cleanerd/cleanerd.c          |  15 ++++
 sbin/cleanerd/nilfs_cleanerd.conf |  13 +++
 7 files changed, 218 insertions(+), 43 deletions(-)
include/nilfs.h +6 -1
index 56286a9..b5f85d3 100644
@@ -128,7 +128,8 @@ struct nilfs {
 #define NILFS_OPEN_RDWR		0x0008	/* Open NILFS API in read/write mode */
 #define NILFS_OPEN_GCLK		0x1000	/* Open GC lock primitive */
 
-#define NILFS_OPT_MMAP	0x01
+#define NILFS_OPT_MMAP		0x01
+#define NILFS_OPT_SET_SUINFO	0x02
 
 
 struct nilfs *nilfs_open(const char *, const char *, int);
@@ -140,6 +141,10 @@ void nilfs_opt_clear_mmap(struct nilfs *);
 int nilfs_opt_set_mmap(struct nilfs *);
 int nilfs_opt_test_mmap(struct nilfs *);
 
+void nilfs_opt_clear_set_suinfo(struct nilfs *);
+int nilfs_opt_set_set_suinfo(struct nilfs *);
+int nilfs_opt_test_set_suinfo(struct nilfs *);
+
 nilfs_cno_t nilfs_get_oldest_cno(struct nilfs *);
 
 struct nilfs_super_block *nilfs_get_sb(struct nilfs *);
lib/nilfs.c +28 -0
index c1771e8..93822de 100644
@@ -288,6 +288,34 @@ int nilfs_opt_test_mmap(struct nilfs *nilfs)
 	return !!(nilfs->n_opts & NILFS_OPT_MMAP);
 }
 
+/**
+ * nilfs_opt_set_set_suinfo - set set_suinfo option
+ * @nilfs: nilfs object
+ */
+int nilfs_opt_set_set_suinfo(struct nilfs *nilfs)
+{
+	nilfs->n_opts |= NILFS_OPT_SET_SUINFO;
+	return 0;
+}
+
+/**
+ * nilfs_opt_clear_set_suinfo - clear set_suinfo option
+ * @nilfs: nilfs object
+ */
+void nilfs_opt_clear_set_suinfo(struct nilfs *nilfs)
+{
+	nilfs->n_opts &= ~NILFS_OPT_SET_SUINFO;
+}
+
+/**
+ * nilfs_opt_test_set_suinfo - test whether set_suinfo option is set or not
+ * @nilfs: nilfs object
+ */
+int nilfs_opt_test_set_suinfo(struct nilfs *nilfs)
+{
+	return !!(nilfs->n_opts & NILFS_OPT_SET_SUINFO);
+}
+
 static int nilfs_open_sem(struct nilfs *nilfs)
 {
 	char semnambuf[NAME_MAX - 4];
man/nilfs_cleanerd.conf.5 +22 -0
index 8f3fcd2..4315ecd 100644
@@ -79,6 +79,28 @@ Specify whether to use \fBmmap\fP(2) for reading segments.  At
 present, this option is enabled if supported regardless of this
 directive.
 .TP
+.B use_set_suinfo
+Specify whether to use the set_suinfo ioctl if it is supported. This is
+necessary for the \fBmin_reclaimable_blocks\fP feature. By disabling this
+switch \fBmin_reclaimable_blocks\fP is also disabled.
+.TP
+.B min_reclaimable_blocks
+Specify the minimum number of reclaimable blocks in a segment before
+it can be cleaned.
+.TP
+.B mc_min_reclaimable_blocks
+Specify the minimum number of reclaimable blocks in a segment before
+it can be cleaned. if clean segments < min_clean_segments.
+.PP
+\fBmin_reclaimable_blocks\fP and \fBmc_min_reclaimable_blocks\fP may
+be followed by a percent sign or the following multiplicative suffixes:
+kB 1000, K 1024, MB 1000*1000, M 1024*1024, GB 1000*1000*1000, G
+1024*1024*1024, and so on for T, P, E.  If the argument is followed by
+a percent sign, it represents the ratio of blocks in a segment.
+.PP
+The default values of \fBmin_reclaimable_blocks\fP and
+\fBmc_min_reclaimable_blocks\fP are 5 percent and 1 percent respectively.
+.TP
 .B log_priority
 Gives the verbosity level that is used when logging messages from
 \fBnilfs_cleanerd\fP(8).  The possible values are: \fBemerg\fP,
sbin/cleanerd/cldconfig.c +126 -42

205 lines not on this page · raw message

sbin/cleanerd/cldconfig.h +8 -0
index 188ce9b..e7ac72e 100644
@@ -101,7 +101,10 @@ struct nilfs_cldconfig {
 	struct timeval cf_mc_cleaning_interval;
 	struct timeval cf_retry_interval;
 	int cf_use_mmap;
+	int cf_use_set_suinfo;
 	int cf_log_priority;
+	unsigned long cf_min_reclaimable_blocks;
+	unsigned long cf_mc_min_reclaimable_blocks;
 };
 
 #define NILFS_CLDCONFIG_SELECTION_POLICY_IMPORTANCE	\
@@ -119,7 +122,12 @@ struct nilfs_cldconfig {
 #define NILFS_CLDCONFIG_MC_CLEANING_INTERVAL		1
 #define NILFS_CLDCONFIG_RETRY_INTERVAL			60
 #define NILFS_CLDCONFIG_USE_MMAP			1
+#define NILFS_CLDCONFIG_USE_SET_SUINFO			0
 #define NILFS_CLDCONFIG_LOG_PRIORITY			LOG_INFO
+#define NILFS_CLDCONFIG_MIN_RECLAIMABLE_BLOCKS		5
+#define NILFS_CLDCONFIG_MIN_RECLAIMABLE_BLOCKS_UNIT	NILFS_SIZE_UNIT_PERCENT
+#define NILFS_CLDCONFIG_MC_MIN_RECLAIMABLE_BLOCKS	1
+#define NILFS_CLDCONFIG_MC_MIN_RECLAIMABLE_BLOCKS_UNIT	NILFS_SIZE_UNIT_PERCENT
 
 #define NILFS_CLDCONFIG_NSEGMENTS_PER_CLEAN_MAX	32
 
sbin/cleanerd/cleanerd.c +15 -0
index 742ab98..bf8b8b0 100644
@@ -172,6 +172,7 @@ struct nilfs_cleanerd {
 	struct timeval cleaning_interval;
 	struct timeval target;
 	struct timeval timeout;
+	unsigned long min_reclaimable_blocks;
 	__u64 prev_nongc_ctime;
 	mqd_t recvq;
 	char *recvq_name;
@@ -246,6 +247,12 @@ static int nilfs_cleanerd_config(struct nilfs_cleanerd *cleanerd,
 	else
 		nilfs_opt_clear_mmap(cleanerd->nilfs);
 #endif	/* HAVE_MMAP */
+
+	if (cleanerd->config.cf_use_set_suinfo)
+		nilfs_opt_set_set_suinfo(cleanerd->nilfs);
+	else
+		nilfs_opt_clear_set_suinfo(cleanerd->nilfs);
+
 	nilfs_cleanerd_set_log_priority(cleanerd);
 
 	if (protection_period != ULONG_MAX) {
@@ -273,6 +280,8 @@ static int nilfs_cleanerd_reconfig(struct nilfs_cleanerd *cleanerd,
 	} else {
 		cleanerd->ncleansegs = config->cf_nsegments_per_clean;
 		cleanerd->cleaning_interval = config->cf_cleaning_interval;
+		cleanerd->min_reclaimable_blocks =
+				config->cf_min_reclaimable_blocks;
 		syslog(LOG_INFO, "configuration file reloaded");
 	}
 	return ret;
@@ -1238,10 +1247,14 @@ static int nilfs_cleanerd_handle_clean_check(struct nilfs_cleanerd *cleanerd,
 		/* disk space is close to limit -- accelerate cleaning */
 		cleanerd->ncleansegs = config->cf_mc_nsegments_per_clean;
 		cleanerd->cleaning_interval = config->cf_mc_cleaning_interval;
+		cleanerd->min_reclaimable_blocks =
+				config->cf_mc_min_reclaimable_blocks;
 	} else {
 		/* continue to run */
 		cleanerd->ncleansegs = config->cf_nsegments_per_clean;
 		cleanerd->cleaning_interval = config->cf_cleaning_interval;
+		cleanerd->min_reclaimable_blocks =
+				config->cf_min_reclaimable_blocks;
 	}
 
 	return 0; /* do gc */
@@ -1427,6 +1440,8 @@ static int nilfs_cleanerd_clean_loop(struct nilfs_cleanerd *cleanerd)
 
 	cleanerd->ncleansegs = cleanerd->config.cf_nsegments_per_clean;
 	cleanerd->cleaning_interval = cleanerd->config.cf_cleaning_interval;
+	cleanerd->min_reclaimable_blocks =
+			cleanerd->config.cf_min_reclaimable_blocks;
 
 
 	if (nilfs_cleanerd_automatic_suspend(cleanerd))
sbin/cleanerd/nilfs_cleanerd.conf +13 -0
index 26872aa..f88a57a 100644
@@ -51,6 +51,19 @@ mc_cleaning_interval	1
 # Retry interval in seconds.
 retry_interval		60
 
+# Specify the minimum number of reclaimable blocks in a segment
+# before it can be cleaned.
+min_reclaimable_blocks	5%
+
+# Specify the minimum number of reclaimable blocks in a segment
+# before it can be cleaned.
+# if clean segments < min_clean_segments
+mc_min_reclaimable_blocks	1%
+
+# enable set_suinfo ioctl if supported
+# (needed for min_reclaimable_blocks)
+use_set_suinfo
+
 # Use mmap when reading segments if supported.
 use_mmap
 
Signature · 6 lines
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
#3 lore raw

PATCH v3 2/4 nilfs-utils: nilfs-clean add cmdline param min-reclaimable-blocks

In reply to a message not in the archive

This patch adds a command line parameter for nilfs-clean to allow the manual override of the min_reclaimable_blocks option.

---
 include/nilfs_cleaner.h        | 19 +++++++++---------
 man/nilfs-clean.8              |  4 ++++
 sbin/cleanerd/cleanerd.c       | 19 ++++++++++++++++++
 sbin/nilfs-clean/nilfs-clean.c | 44 ++++++++++++++++++++++++++++++++++++------
 4 files changed, 71 insertions(+), 15 deletions(-)
include/nilfs_cleaner.h +10 -9
index 0bf02aa..874c17a 100644
@@ -46,17 +46,18 @@ struct nilfs_cleaner_args {
 	uint64_t start_segnum;	/* start segment number */
 	uint64_t nsegs;		/* number of segments */
 	uint32_t runtime; /* runtime in seconds */
-	uint32_t pad2;
+	uint32_t min_reclaimable_blocks;
 };
 /* valid flags */
-#define NILFS_CLEANER_ARG_PROTECTION_PERIOD	(1 << 0)
-#define NILFS_CLEANER_ARG_NSEGMENTS_PER_CLEAN	(1 << 1)
-#define NILFS_CLEANER_ARG_CLEANING_INTERVAL	(1 << 2)
-#define NILFS_CLEANER_ARG_USAGE_RATE_THRESHOLD	(1 << 3) /* reserved */
-#define NILFS_CLEANER_ARG_START_SEGNUM		(1 << 4) /* reserved */
-#define NILFS_CLEANER_ARG_NSEGS			(1 << 5) /* reserved */
-#define NILFS_CLEANER_ARG_NPASSES		(1 << 6) /* reserved */
-#define NILFS_CLEANER_ARG_RUNTIME		(1 << 7) /* reserved */
+#define NILFS_CLEANER_ARG_PROTECTION_PERIOD		(1 << 0)
+#define NILFS_CLEANER_ARG_NSEGMENTS_PER_CLEAN		(1 << 1)
+#define NILFS_CLEANER_ARG_CLEANING_INTERVAL		(1 << 2)
+#define NILFS_CLEANER_ARG_USAGE_RATE_THRESHOLD		(1 << 3) /* reserved */
+#define NILFS_CLEANER_ARG_START_SEGNUM			(1 << 4) /* reserved */
+#define NILFS_CLEANER_ARG_NSEGS				(1 << 5) /* reserved */
+#define NILFS_CLEANER_ARG_NPASSES			(1 << 6) /* reserved */
+#define NILFS_CLEANER_ARG_RUNTIME			(1 << 7) /* reserved */
+#define NILFS_CLEANER_ARG_MIN_RECLAIMABLE_BLOCKS	(1 << 8)
 
 enum {
 	NILFS_CLEANER_STATUS_IDLE,
man/nilfs-clean.8 +4 -0
index 04e11c6..94267e1 100644
@@ -43,6 +43,10 @@ Display cleaner status.
 \fB\-h\fR, \fB\-\-help\fR
 Display help message and exit.
 .TP
+\fB\-m\fR, \fB\-\-min\-reclaimable\-blocks=\fICOUNT\fR
+Specify the minimum number of reclaimable blocks in a segment before
+it can be cleaned.
+.TP
 \fB\-p\fR, \fB\-\-protection-period=\fIinterval\fR
 Set protection period for a cleaner run.  The \fIinterval\fR parameter
 is an integer value and specifies the minimum time that deleted or
sbin/cleanerd/cleanerd.c +19 -0
index bf8b8b0..13018b2 100644
@@ -185,6 +185,7 @@ struct nilfs_cleanerd {
 	long mm_ncleansegs;
 	struct timeval mm_protection_period;
 	struct timeval mm_cleaning_interval;
+	unsigned long mm_min_reclaimable_blocks;
 };
 
 /**
@@ -468,6 +469,14 @@ nilfs_cleanerd_protection_period(struct nilfs_cleanerd *cleanerd)
 		&cleanerd->config.cf_protection_period;
 }
 
+static unsigned long
+nilfs_cleanerd_min_reclaimable_blocks(struct nilfs_cleanerd *cleanerd)
+{
+	return cleanerd->running == 2 ?
+		cleanerd->mm_min_reclaimable_blocks :
+		cleanerd->min_reclaimable_blocks;
+}
+
 static void
 nilfs_cleanerd_reduce_ncleansegs_for_retry(struct nilfs_cleanerd *cleanerd)
 {
@@ -1010,6 +1019,16 @@ static int nilfs_cleanerd_cmd_run(struct nilfs_cleanerd *cleanerd,
 		cleanerd->mm_cleaning_interval =
 			cleanerd->cleaning_interval;
 	}
+	/* minimal reclaimable blocks */
+	if ((req2->args.valid & NILFS_CLEANER_ARG_MIN_RECLAIMABLE_BLOCKS)
+		&& req2->args.min_reclaimable_blocks <=
+			nilfs_get_blocks_per_segment(cleanerd->nilfs)) {
+		cleanerd->mm_min_reclaimable_blocks =
+			req2->args.min_reclaimable_blocks;
+	} else {
+		cleanerd->mm_min_reclaimable_blocks =
+			cleanerd->min_reclaimable_blocks;
+	}
 	/* number of passes */
 	if (req2->args.valid & NILFS_CLEANER_ARG_NPASSES) {
 		if (!req2->args.npasses)
sbin/nilfs-clean/nilfs-clean.c +38 -6

96 lines not on this page · raw message

Signature · 6 lines
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
#4 lore raw

PATCH v3 3/4 nilfs-utils: add suport for NILFS_IOCTL_SET_SUINFO ioctl

In reply to a message not in the archive

This patch adds library support for the NILFS_IOCTL_SET_SUINFO ioctl. A new function nilfs_set_suinfo and the structure nilfs_suinfo_update, which contains the update information, are added.

With this function the segment usage information can be updated from userspace, which can be used as a shortcut for certain GC operations.

---
 include/nilfs.h     |  2 ++
 include/nilfs2_fs.h | 43 +++++++++++++++++++++++++++++++++++++++++++
 lib/nilfs.c         | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)
include/nilfs.h +2 -0
index b5f85d3..af4735d 100644
@@ -304,6 +304,8 @@ int nilfs_delete_checkpoint(struct nilfs *, nilfs_cno_t);
 int nilfs_get_cpstat(const struct nilfs *, struct nilfs_cpstat *);
 ssize_t nilfs_get_suinfo(const struct nilfs *, __u64, struct nilfs_suinfo *,
 			 size_t);
+ssize_t nilfs_set_suinfo(const struct nilfs *, struct nilfs_suinfo_update *,
+			 size_t);
 int nilfs_get_sustat(const struct nilfs *, struct nilfs_sustat *);
 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);
include/nilfs2_fs.h +43 -0

54 lines not on this page · raw message

lib/nilfs.c +32 -0
index 93822de..25664e1 100644
@@ -596,6 +596,38 @@ ssize_t nilfs_get_suinfo(const struct nilfs *nilfs, __u64 segnum,
 }
 
 /**
+ * nilfs_set_suinfo - sets segment usage info
+ * @nilfs: nilfs object
+ * @sup: an array of nilfs_suinfo_update structs
+ * @nsup: number of elements in sup
+ *
+ * Description: Takes an array of nilfs_suinfo_update structs and updates
+ * segment usage info accordingly. Only the fields indicated by sup_flags
+ * are updated.
+ *
+ * Return Value: On success, 0 is returned. On error, -1 is returned.
+ */
+ssize_t nilfs_set_suinfo(const struct nilfs *nilfs,
+			 struct nilfs_suinfo_update *sup, size_t nsup)
+{
+	struct nilfs_argv argv;
+
+	if (nilfs->n_iocfd < 0) {
+		errno = EBADF;
+		return -1;
+	}
+
+	argv.v_base = (unsigned long)sup;
+	argv.v_nmembs = nsup;
+	argv.v_size = sizeof(struct nilfs_suinfo_update);
+	argv.v_index = 0;
+	argv.v_flags = 0;
+	if (ioctl(nilfs->n_iocfd, NILFS_IOCTL_SET_SUINFO, &argv) < 0)
+		return -1;
+	return 0;
+}
+
+/**
  * nilfs_get_sustat - get segment usage statistics
  * @nilfs: nilfs object
  * @sustat: buffer of a nilfs_sustat struct to store statistics in
Signature · 6 lines
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
#5 lore raw

PATCH v3 4/4 nilfs-utils: add optimized version of nilfs_reclaim_segments

In reply to a message not in the archive

This patch adds an optimized version of nilfs_reclaim_segments, which has an additional parameter min_reclaimable. This parameter specifies the minimum number of reclaimable blocks in a segment, before it can be cleaned. If a segment is below this threshold, it is considered to be not worth cleaning, because all the live blocks would need to be moved to a new segment, which is expensive, and the number of reclaimable blocks is too low. But it is still necessary to update the segment usage information to turn the old segment into a new one.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

This optimization can be enabled and disabled by the use_set_suinfo switch in the configuration file. If the kernel doesn't support the set_suinfo ioctl it returns the error number ENOTTY, which also permanently disables the optimization.

---
 include/nilfs_gc.h       |   4 ++
 lib/gc.c                 | 112 +++++++++++++++++++++++++++++++++++++++--------
 sbin/cleanerd/cleanerd.c |   5 ++-
 3 files changed, 100 insertions(+), 21 deletions(-)
include/nilfs_gc.h +4 -0
index 72e9947..0ee797e 100644
@@ -18,6 +18,10 @@ ssize_t nilfs_reclaim_segment(struct nilfs *nilfs,
 			      __u64 *segnums, size_t nsegs,
 			      __u64 protseq, nilfs_cno_t protcno);
 
+ssize_t nilfs_reclaim_segment_with_threshold(struct nilfs *nilfs,
+				__u64 *segnums, size_t nsegs, __u64 protseq,
+				nilfs_cno_t protcno,
+				unsigned long min_reclaimable);
 
 static inline int nilfs_suinfo_reclaimable(const struct nilfs_suinfo *si)
 {
lib/gc.c +93 -19

143 lines not on this page · raw message

sbin/cleanerd/cleanerd.c +3 -2
index 13018b2..b225283 100644
@@ -1384,8 +1384,9 @@ static ssize_t nilfs_cleanerd_clean_segments(struct nilfs_cleanerd *cleanerd,
 		goto out;
 	}
 
-	ret = nilfs_reclaim_segment(cleanerd->nilfs, segnums, nsegs,
-				    protseq, protcno);
+	ret = nilfs_reclaim_segment_with_threshold(cleanerd->nilfs, segnums,
+			nsegs, protseq, protcno,
+			nilfs_cleanerd_min_reclaimable_blocks(cleanerd));
 	if (ret > 0) {
 		for (i = 0; i < ret; i++)
 			syslog(LOG_DEBUG, "segment %llu cleaned",
Signature · 6 lines
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
#6 lore raw

PATCH v3 1/3 nilfs2: add struct nilfs_suinfo_update and flags

In reply to a message not in the archive

This patch adds the nilfs_suinfo_update structure, which contains the information needed to update one segment usage entry. The flags specify, which fields need to be updated.

---
 include/linux/nilfs2_fs.h | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
include/linux/nilfs2_fs.h +41 -0
index 9875576..7b94449 100644
@@ -709,6 +709,47 @@ static inline int nilfs_suinfo_clean(const struct nilfs_suinfo *si)
 	return !si->sui_flags;
 }
 
+/**
+ * nilfs_suinfo_update - segment usage information update
+ * @sup_segnum: segment number
+ * @sup_flags: flags for which fields are active in sup_sui
+ * @sup_reserved: reserved necessary for alignment
+ * @sup_sui: segment usage information
+ */
+struct nilfs_suinfo_update {
+	__u64 sup_segnum;
+	__u32 sup_flags;
+	__u32 sup_reserved;
+	struct nilfs_suinfo sup_sui;
+};
+
+enum {
+	NILFS_SUINFO_UPDATE_LASTMOD,
+	NILFS_SUINFO_UPDATE_NBLOCKS,
+	NILFS_SUINFO_UPDATE_FLAGS,
+};
+
+#define NILFS_SUINFO_UPDATE_FNS(flag, name)				\
+static inline void							\
+nilfs_suinfo_update_set_##name(struct nilfs_suinfo_update *sup)		\
+{									\
+	sup->sup_flags |= 1UL << NILFS_SUINFO_UPDATE_##flag;		\
+}									\
+static inline void							\
+nilfs_suinfo_update_clear_##name(struct nilfs_suinfo_update *sup)	\
+{									\
+	sup->sup_flags &= ~(1UL << NILFS_SUINFO_UPDATE_##flag);		\
+}									\
+static inline int							\
+nilfs_suinfo_update_##name(const struct nilfs_suinfo_update *sup)	\
+{									\
+	return !!(sup->sup_flags & (1UL << NILFS_SUINFO_UPDATE_##flag));\
+}
+
+NILFS_SUINFO_UPDATE_FNS(LASTMOD, lastmod)
+NILFS_SUINFO_UPDATE_FNS(NBLOCKS, nblocks)
+NILFS_SUINFO_UPDATE_FNS(FLAGS, flags)
+
 /* ioctl */
 enum {
 	NILFS_CHECKPOINT,
Signature · 6 lines
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

A message that is not in the archive (sent off-list or not yet received): bb721a6255f199eb4a3fdfe2b34e0bdaa5f870a7.1390816620.git.andreas.rohner-hi6Y0CQ0nG0@public.gmane.org

#8 lore raw

PATCH v3 2/3 nilfs2: add nilfs_sufile_set_suinfo to update segment usage

This patch introduces the nilfs_sufile_set_suinfo function, which expects an array of nilfs_suinfo_update structures and updates the segment usage information accordingly.

This is basically a helper function for the newly introduced NILFS_IOCTL_SET_SUINFO ioctl.

---
 fs/nilfs2/sufile.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/sufile.h |   1 +
 2 files changed, 130 insertions(+)
fs/nilfs2/sufile.c +129 -0
index 3127e9f..8922523 100644
@@ -870,6 +870,135 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 }
 
 /**
+ * nilfs_sufile_set_suinfo - sets segment usage info
+ * @sufile: inode of segment usage file
+ * @buf: array of suinfo_update
+ * @supsz: byte size of suinfo_update
+ * @nsup: size of suinfo_update array
+ *
+ * Description: Takes an array of nilfs_suinfo_update structs and updates
+ * segment usage accordingly. Only the fields indicated by the sup_flags
+ * are updated.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the
+ * following negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-EINVAL - Invalid values in input (segment number, flags or nblocks)
+ */
+ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf,
+				unsigned supsz, size_t nsup)
+{
+	struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
+	struct buffer_head *header_bh, *bh;
+	struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup;
+	struct nilfs_segment_usage *su;
+	void *kaddr;
+	unsigned long blkoff, prev_blkoff;
+	int ret = 0, ncleansegs, ndirtysegs, cleansi,
+			cleansu, dirtysi, dirtysu;
+
+	if (unlikely(nsup == 0))
+		return ret;
+
+	for (sup = buf; sup < supend; sup = (void *)sup + supsz) {
+		if (sup->sup_segnum >= nilfs->ns_nsegments
+			|| (sup->sup_flags &
+				(~0UL << (NILFS_SUINFO_UPDATE_FLAGS + 1)))
+			|| (nilfs_suinfo_update_nblocks(sup) &&
+				sup->sup_sui.sui_nblocks >
+				nilfs->ns_blocks_per_segment)
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))
+			return -EINVAL;
+	}
+
+	down_write(&NILFS_MDT(sufile)->mi_sem);
+
+	ret = nilfs_sufile_get_header_block(sufile, &header_bh);
+	if (ret < 0)
+		goto out_sem;
+
+	sup = buf;
+	blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+	ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+	if (ret < 0)
+		goto out_header;
+
+	for (;;) {
+		kaddr = kmap_atomic(bh->b_page);
+		su = nilfs_sufile_block_get_segment_usage(
+			sufile, sup->sup_segnum, bh, kaddr);
+
+		if (nilfs_suinfo_update_lastmod(sup))
+			su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod);
+
+		if (nilfs_suinfo_update_nblocks(sup))
+			su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks);
+
+		if (nilfs_suinfo_update_flags(sup)) {
+			sup->sup_sui.sui_flags &=
+					~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
+
+			ncleansegs = 0;
+			ndirtysegs = 0;
+			cleansi = nilfs_suinfo_clean(&sup->sup_sui);
+			cleansu = nilfs_segment_usage_clean(su);
+			dirtysi = nilfs_suinfo_dirty(&sup->sup_sui);
+			dirtysu = nilfs_segment_usage_dirty(su);
+
+			if (cleansi && !cleansu)
+				++ncleansegs;
+			else if (!cleansi && cleansu)
+				--ncleansegs;
+
+			if (dirtysi && !dirtysu)
+				++ndirtysegs;
+			else if (!dirtysi && dirtysu)
+				--ndirtysegs;
+
+			su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags);
+
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;
+		}
+
+		kunmap_atomic(kaddr);
+
+		sup = (void *)sup + supsz;
+		if (sup >= supend)
+			break;
+
+		prev_blkoff = blkoff;
+		blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+		if (blkoff == prev_blkoff)
+			continue;
+
+		/* get different block */
+		mark_buffer_dirty(bh);
+		brelse(bh);
+		ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+		if (unlikely(ret < 0))
+			goto out_mark;
+	}
+	mark_buffer_dirty(bh);
+	brelse(bh);
+
+ out_mark:
+	nilfs_mdt_mark_dirty(sufile);
+ out_header:
+	brelse(header_bh);
+ out_sem:
+	up_write(&NILFS_MDT(sufile)->mi_sem);
+	return ret;
+}
+
+/**
  * nilfs_sufile_read - read or get sufile inode
  * @sb: super block instance
  * @susize: size of a segment usage entry
fs/nilfs2/sufile.h +1 -0
index e84bc5b..366003c 100644
@@ -44,6 +44,7 @@ int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
 int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
 ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned,
 				size_t);
+ssize_t nilfs_sufile_set_suinfo(struct inode *, void *, unsigned , size_t);
 
 int nilfs_sufile_updatev(struct inode *, __u64 *, size_t, int, size_t *,
 			 void (*dofunc)(struct inode *, __u64,
Signature · 6 lines
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

A message that is not in the archive (sent off-list or not yet received): 93a209490951530b1b9eb03be4e3b309d36740f4.1390816620.git.andreas.rohner-hi6Y0CQ0nG0@public.gmane.org

#10 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Quoted 41 lines · Andreas Rohner

This patch introduces the nilfs_sufile_set_suinfo function, which expects an array of nilfs_suinfo_update structures and updates the segment usage information accordingly.

This is basically a helper function for the newly introduced NILFS_IOCTL_SET_SUINFO ioctl.

---
 fs/nilfs2/sufile.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/sufile.h |   1 +
 2 files changed, 130 insertions(+)
fs/nilfs2/sufile.c +20 -0
index 3127e9f..8922523 100644
@@ -870,6 +870,135 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 }
 
 /**
+ * nilfs_sufile_set_suinfo - sets segment usage info
+ * @sufile: inode of segment usage file
+ * @buf: array of suinfo_update
+ * @supsz: byte size of suinfo_update
+ * @nsup: size of suinfo_update array
+ *
+ * Description: Takes an array of nilfs_suinfo_update structs and updates
+ * segment usage accordingly. Only the fields indicated by the sup_flags
+ * are updated.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the
+ * following negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-EINVAL - Invalid values in input (segment number, flags or nblocks)
+ */
+ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf,

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 902

Quoted 10 lines
fs/nilfs2/sufile.c +10 -0
+				unsigned supsz, size_t nsup)
+{
+	struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
+	struct buffer_head *header_bh, *bh;
+	struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup;
+	struct nilfs_segment_usage *su;
+	void *kaddr;
+	unsigned long blkoff, prev_blkoff;
+	int ret = 0, ncleansegs, ndirtysegs, cleansi,
+			cleansu, dirtysi, dirtysu;

This indentation looks peculiar. Why not separate them into two or more lines? At least, ncleansegs and ndirtysegs differ from cleansi, cleansu, dirtysi, dirtysu and ret. ncleansegs and ndirtysegs sounds confusing since these local variables do not give a total number. ncleaned and ndirtied would be better.

	int cleansi, cleansu, dirtysi, dirtysu;
	int ncleaned, ndirtied;
	int ret = 0;

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 910

Quoted 8 lines
fs/nilfs2/sufile.c +8 -0
+
+	if (unlikely(nsup == 0))
+		return ret;
+
+	for (sup = buf; sup < supend; sup = (void *)sup + supsz) {
+		if (sup->sup_segnum >= nilfs->ns_nsegments
+			|| (sup->sup_flags &
+				(~0UL << (NILFS_SUINFO_UPDATE_FLAGS + 1)))

This looks confusing. It should be clarified as follows:

enum {
NILFS_SUINFO_UPDATE_LASTMOD,
NILFS_SUINFO_UPDATE_NBLOCKS,
NILFS_SUINFO_UPDATE_FLAGS,
__NR_NILFS_SUINFO_FIELDS
};

		if (sup->sup_segnum >= nilfs->ns_nsegments ||
		    (sup->sup_flags & (~0UL << __NR_NILFS_SUINFO_FIELDS)) ||

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 916

Quoted 6 lines
fs/nilfs2/sufile.c +6 -0
+			|| (nilfs_suinfo_update_nblocks(sup) &&
+				sup->sup_sui.sui_nblocks >
+				nilfs->ns_blocks_per_segment)
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Any comments on this?

Quoted 18 lines
fs/nilfs2/sufile.c +18 -0
+	}
+
+	down_write(&NILFS_MDT(sufile)->mi_sem);
+
+	ret = nilfs_sufile_get_header_block(sufile, &header_bh);
+	if (ret < 0)
+		goto out_sem;
+
+	sup = buf;
+	blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+	ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+	if (ret < 0)
+		goto out_header;
+
+	for (;;) {
+		kaddr = kmap_atomic(bh->b_page);
+		su = nilfs_sufile_block_get_segment_usage(
+			sufile, sup->sup_segnum, bh, kaddr);

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 945

Quoted 10 lines
fs/nilfs2/sufile.c +10 -0
+
+		if (nilfs_suinfo_update_lastmod(sup))
+			su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod);
+
+		if (nilfs_suinfo_update_nblocks(sup))
+			su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks);
+
+		if (nilfs_suinfo_update_flags(sup)) {
+			sup->sup_sui.sui_flags &=
+					~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);

Your would be better off adding a comment to explain what's this.

/*
* Active flag is a virtual flag projected by running
* nilfs kernel code - drop it not to write it to
* disk.
*/

Quoted 12 lines
fs/nilfs2/sufile.c +12 -0
+
+			ncleansegs = 0;
+			ndirtysegs = 0;
+			cleansi = nilfs_suinfo_clean(&sup->sup_sui);
+			cleansu = nilfs_segment_usage_clean(su);
+			dirtysi = nilfs_suinfo_dirty(&sup->sup_sui);
+			dirtysu = nilfs_segment_usage_dirty(su);
+
+			if (cleansi && !cleansu)
+				++ncleansegs;
+			else if (!cleansi && cleansu)
+				--ncleansegs;

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 967

Quoted 10 lines
fs/nilfs2/sufile.c +10 -0
+
+			if (dirtysi && !dirtysu)
+				++ndirtysegs;
+			else if (!dirtysi && dirtysu)
+				--ndirtysegs;
+
+			su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags);
+
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 968

Quoted 1 line
fs/nilfs2/sufile.c +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

Regards,
Ryusuke Konishi

Quoted 55 lines
fs/nilfs2/sufile.c +33 -0
+		}
+
+		kunmap_atomic(kaddr);
+
+		sup = (void *)sup + supsz;
+		if (sup >= supend)
+			break;
+
+		prev_blkoff = blkoff;
+		blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+		if (blkoff == prev_blkoff)
+			continue;
+
+		/* get different block */
+		mark_buffer_dirty(bh);
+		brelse(bh);
+		ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+		if (unlikely(ret < 0))
+			goto out_mark;
+	}
+	mark_buffer_dirty(bh);
+	brelse(bh);
+
+ out_mark:
+	nilfs_mdt_mark_dirty(sufile);
+ out_header:
+	brelse(header_bh);
+ out_sem:
+	up_write(&NILFS_MDT(sufile)->mi_sem);
+	return ret;
+}
+
+/**
  * nilfs_sufile_read - read or get sufile inode
  * @sb: super block instance
  * @susize: size of a segment usage entry
fs/nilfs2/sufile.h +1 -0
index e84bc5b..366003c 100644
@@ -44,6 +44,7 @@ int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
 int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
 ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned,
 				size_t);
+ssize_t nilfs_sufile_set_suinfo(struct inode *, void *, unsigned , size_t);
 
 int nilfs_sufile_updatev(struct inode *, __u64 *, size_t, int, size_t *,
 			 void (*dofunc)(struct inode *, __u64,
Signature · 6 lines
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

--
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

A message that is not in the archive (sent off-list or not yet received): 20140128.040735.413842146.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org

#12 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Quoted 104 lines · Ryusuke Konishi
Quoted 41 lines · Andreas Rohner

This patch introduces the nilfs_sufile_set_suinfo function, which expects an array of nilfs_suinfo_update structures and updates the segment usage information accordingly.

This is basically a helper function for the newly introduced NILFS_IOCTL_SET_SUINFO ioctl.

---
 fs/nilfs2/sufile.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/sufile.h |   1 +
 2 files changed, 130 insertions(+)
fs/nilfs2/sufile.c +20 -0
index 3127e9f..8922523 100644
@@ -870,6 +870,135 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 }
 
 /**
+ * nilfs_sufile_set_suinfo - sets segment usage info
+ * @sufile: inode of segment usage file
+ * @buf: array of suinfo_update
+ * @supsz: byte size of suinfo_update
+ * @nsup: size of suinfo_update array
+ *
+ * Description: Takes an array of nilfs_suinfo_update structs and updates
+ * segment usage accordingly. Only the fields indicated by the sup_flags
+ * are updated.
+ *
+ * Return Value: On success, 0 is returned. On error, one of the
+ * following negative error codes is returned.
+ *
+ * %-EIO - I/O error.
+ *
+ * %-ENOMEM - Insufficient amount of memory available.
+ *
+ * %-EINVAL - Invalid values in input (segment number, flags or nblocks)
+ */
+ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf,

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 902

Quoted 10 lines
fs/nilfs2/sufile.c +10 -0
+				unsigned supsz, size_t nsup)
+{
+	struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
+	struct buffer_head *header_bh, *bh;
+	struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup;
+	struct nilfs_segment_usage *su;
+	void *kaddr;
+	unsigned long blkoff, prev_blkoff;
+	int ret = 0, ncleansegs, ndirtysegs, cleansi,
+			cleansu, dirtysi, dirtysu;

This indentation looks peculiar. Why not separate them into two or more lines? At least, ncleansegs and ndirtysegs differ from cleansi, cleansu, dirtysi, dirtysu and ret. ncleansegs and ndirtysegs sounds confusing since these local variables do not give a total number. ncleaned and ndirtied would be better.

	int cleansi, cleansu, dirtysi, dirtysu;
	int ncleaned, ndirtied;
	int ret = 0;

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 910

Quoted 8 lines
fs/nilfs2/sufile.c +8 -0
+
+	if (unlikely(nsup == 0))
+		return ret;
+
+	for (sup = buf; sup < supend; sup = (void *)sup + supsz) {
+		if (sup->sup_segnum >= nilfs->ns_nsegments
+			|| (sup->sup_flags &
+				(~0UL << (NILFS_SUINFO_UPDATE_FLAGS + 1)))

This looks confusing. It should be clarified as follows:

enum {
NILFS_SUINFO_UPDATE_LASTMOD,
NILFS_SUINFO_UPDATE_NBLOCKS,
NILFS_SUINFO_UPDATE_FLAGS,
__NR_NILFS_SUINFO_FIELDS
};

		if (sup->sup_segnum >= nilfs->ns_nsegments ||
		    (sup->sup_flags & (~0UL << __NR_NILFS_SUINFO_FIELDS)) ||

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 916

Quoted 6 lines
fs/nilfs2/sufile.c +6 -0
+			|| (nilfs_suinfo_update_nblocks(sup) &&
+				sup->sup_sui.sui_nblocks >
+				nilfs->ns_blocks_per_segment)
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))
Quoted 6 lines

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Any comments on this?

Hmm, I think it can't hurt to let the userland cleaner use the su_flags. As far as I can tell, it shouldn't affect the kernel side. nilfs_segment_usage_set_clean() would still work and nilfs_sufile_do_scrap() overwrites the whole su_flags as well.

Quoted 62 lines
Quoted 18 lines
fs/nilfs2/sufile.c +18 -0
+	}
+
+	down_write(&NILFS_MDT(sufile)->mi_sem);
+
+	ret = nilfs_sufile_get_header_block(sufile, &header_bh);
+	if (ret < 0)
+		goto out_sem;
+
+	sup = buf;
+	blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+	ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+	if (ret < 0)
+		goto out_header;
+
+	for (;;) {
+		kaddr = kmap_atomic(bh->b_page);
+		su = nilfs_sufile_block_get_segment_usage(
+			sufile, sup->sup_segnum, bh, kaddr);

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 945

Quoted 10 lines
fs/nilfs2/sufile.c +10 -0
+
+		if (nilfs_suinfo_update_lastmod(sup))
+			su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod);
+
+		if (nilfs_suinfo_update_nblocks(sup))
+			su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks);
+
+		if (nilfs_suinfo_update_flags(sup)) {
+			sup->sup_sui.sui_flags &=
+					~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);

Your would be better off adding a comment to explain what's this.

/*
* Active flag is a virtual flag projected by running
* nilfs kernel code - drop it not to write it to
* disk.
*/

Quoted 12 lines
fs/nilfs2/sufile.c +12 -0
+
+			ncleansegs = 0;
+			ndirtysegs = 0;
+			cleansi = nilfs_suinfo_clean(&sup->sup_sui);
+			cleansu = nilfs_segment_usage_clean(su);
+			dirtysi = nilfs_suinfo_dirty(&sup->sup_sui);
+			dirtysu = nilfs_segment_usage_dirty(su);
+
+			if (cleansi && !cleansu)
+				++ncleansegs;
+			else if (!cleansi && cleansu)
+				--ncleansegs;

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 967

Quoted 10 lines
fs/nilfs2/sufile.c +10 -0
+
+			if (dirtysi && !dirtysu)
+				++ndirtysegs;
+			else if (!dirtysi && dirtysu)
+				--ndirtysegs;
+
+			su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags);
+
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

Quoted 3 lines

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 968

Quoted 1 line
fs/nilfs2/sufile.c +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

I have tested it and it works. At least on my 64 bit architecture. It is probably still a good idea to do an explicit cast.

How about I use s64 for ncleaned and ndirtied and move nilfs_sufile_mod_counter outside the loop?

	s64 ncleaned = 0, ndirtied = 0;

	...

	for (;;) {
		...
	}
	mark_buffer_dirty(bh);
	brelse(bh);

out_mark:

	if (ncleaned || ndirtied) {
		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
				(u64)ndirtied);
		NILFS_SUI(sufile)->ncleansegs += ncleaned;
	}
	nilfs_mdt_mark_dirty(sufile);
 out_header:
	brelse(header_bh);
 out_sem:
	up_write(&NILFS_MDT(sufile)->mi_sem);
	return ret;

Best regards,
Andreas Rohner

Quoted 55 lines

Regards,
Ryusuke Konishi

Quoted 51 lines
fs/nilfs2/sufile.c +33 -0
+		}
+
+		kunmap_atomic(kaddr);
+
+		sup = (void *)sup + supsz;
+		if (sup >= supend)
+			break;
+
+		prev_blkoff = blkoff;
+		blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum);
+		if (blkoff == prev_blkoff)
+			continue;
+
+		/* get different block */
+		mark_buffer_dirty(bh);
+		brelse(bh);
+		ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh);
+		if (unlikely(ret < 0))
+			goto out_mark;
+	}
+	mark_buffer_dirty(bh);
+	brelse(bh);
+
+ out_mark:
+	nilfs_mdt_mark_dirty(sufile);
+ out_header:
+	brelse(header_bh);
+ out_sem:
+	up_write(&NILFS_MDT(sufile)->mi_sem);
+	return ret;
+}
+
+/**
  * nilfs_sufile_read - read or get sufile inode
  * @sb: super block instance
  * @susize: size of a segment usage entry
fs/nilfs2/sufile.h +1 -0
index e84bc5b..366003c 100644
@@ -44,6 +44,7 @@ int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
 int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
 ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned,
 				size_t);
+ssize_t nilfs_sufile_set_suinfo(struct inode *, void *, unsigned , size_t);
 
 int nilfs_sufile_updatev(struct inode *, __u64 *, size_t, int, size_t *,
 			 void (*dofunc)(struct inode *, __u64,
Signature · 1 line
1.8.5.3
Quoted 5 lines
Quoted 4 lines

--
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

--
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

A message that is not in the archive (sent off-list or not yet received): [email protected]

#14 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Quoted 24 lines · Andreas Rohner
Quoted 23 lines · Ryusuke Konishi

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 916

Quoted 3 lines · Andreas Rohner
fs/nilfs2/sufile.c +3 -0
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Quoted 6 lines
Quoted 1 line

Any comments on this?

Hmm, I think it can't hurt to let the userland cleaner use the su_flags. As far as I can tell, it shouldn't affect the kernel side. nilfs_segment_usage_set_clean() would still work and nilfs_sufile_do_scrap() overwrites the whole su_flags as well.

Well, actually the current definition of nilfs_segment_usage_set_clean() and also nilfs_segment_usage_clean() are written without compatibility consideration.

It looks to be a separate change if we allow to use the upper bits. In that case, a bunch of changes and a new feature_compat_ro flag to deal it as a disk format change, would be needed.

Ok, let's take the above one which protects the upper bits for now.

Quoted 10 lines
Quoted 9 lines

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 967

Quoted 2 lines
fs/nilfs2/sufile.c +2 -0
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

fs/nilfs2/sufile.c ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, · line 968

Quoted 1 line
fs/nilfs2/sufile.c +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

Quoted 5 lines

I have tested it and it works. At least on my 64 bit architecture. It is probably still a good idea to do an explicit cast.

How about I use s64 for ncleaned and ndirtied and move nilfs_sufile_mod_counter outside the loop?

Yes, this one looks better. In that case, the u64 cast seems unnecessary.

Quoted 10 lines
	s64 ncleaned = 0, ndirtied = 0;

	...

	for (;;) {
		...
	}
	mark_buffer_dirty(bh);
	brelse(bh);
Quoted 6 lines

out_mark:

	if (ncleaned || ndirtied) {
		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
				(u64)ndirtied);

		NILFS_SUI(sufile)->ncleansegs += ncleaned;

This one looks unclear.

How about defining ncleaned and ndirtied with unsigned long type and cast them to (u64) for the arguments of nilfs_sufile_mod_counter() ?

Regards,
Ryusuke Konishi

Quoted 8 lines
	}
	nilfs_mdt_mark_dirty(sufile);
 out_header:
	brelse(header_bh);
 out_sem:
	up_write(&NILFS_MDT(sufile)->mi_sem);
	return ret;

--
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

A message that is not in the archive (sent off-list or not yet received): 20140128.100304.163656186.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org

#16 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Quoted 27 lines · Ryusuke Konishi
Quoted 26 lines · Andreas Rohner
Quoted 24 lines · Ryusuke Konishi

Review

Quoted 3 lines · Andreas Rohner
(quoted diff) +3 -0
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Any comments on this?

Quoted 8 lines
Quoted 4 lines

Hmm, I think it can't hurt to let the userland cleaner use the su_flags. As far as I can tell, it shouldn't affect the kernel side. nilfs_segment_usage_set_clean() would still work and nilfs_sufile_do_scrap() overwrites the whole su_flags as well.

Well, actually the current definition of nilfs_segment_usage_set_clean() and also nilfs_segment_usage_clean() are written without compatibility consideration.

I actually thought it would be a good idea to wipe the custom flags if a segment is cleaned, which the current implementation does. So the custom flags are only valid for dirty segments and a segment is only considered to be clean with nilfs_segment_usage_clean if there are no custom flags. I don't think that would be unreasonable, because the GC has no use for flags on clean segments anyway.

Quoted 3 lines

It looks to be a separate change if we allow to use the upper bits. In that case, a bunch of changes and a new feature_compat_ro flag to deal it as a disk format change, would be needed.

I think we would only have to define, which flags are reserved for future use and which are available for the userspace GC. Everything else would just work.

Quoted 1 line

Ok, let's take the above one which protects the upper bits for now.

Ok. It is certainly cleaner that way.

Quoted 34 lines
Quoted 10 lines
Quoted 9 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

Review

Quoted 1 line
(quoted diff) +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

Quoted 5 lines

I have tested it and it works. At least on my 64 bit architecture. It is probably still a good idea to do an explicit cast.

How about I use s64 for ncleaned and ndirtied and move nilfs_sufile_mod_counter outside the loop?

Yes, this one looks better. In that case, the u64 cast seems unnecessary.

Quoted 14 lines
	s64 ncleaned = 0, ndirtied = 0;

	...

	for (;;) {
		...
	}
	mark_buffer_dirty(bh);
	brelse(bh);

out_mark:

	if (ncleaned || ndirtied) {
		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
				(u64)ndirtied);
Quoted 6 lines
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

This one looks unclear.

How about defining ncleaned and ndirtied with unsigned long type and cast them to (u64) for the arguments of nilfs_sufile_mod_counter() ?

Ok I agree ncleansegs could be 32 bit on 32 bit systems. But why "unsigned long" and not just "long"? It seems a bit strange to use an unsigned type for possible negative values and I don't see the problem of adding a negative number to an unsigned type of the same size.

Additionally if we use "unsigned long" wouldn't a typecast to (u64) result in a number like 4294967295 rather than 18446744073709551615, which is equivalent to -1, on a 32 bit system?

Best regards,
Andreas Rohner
--
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

A message that is not in the archive (sent off-list or not yet received): [email protected]

#18 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Quoted 37 lines · Andreas Rohner
Quoted 27 lines · Ryusuke Konishi
Quoted 26 lines · Andreas Rohner
Quoted 24 lines · Ryusuke Konishi

Review

Quoted 3 lines · Andreas Rohner
(quoted diff) +3 -0
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Any comments on this?

Quoted 8 lines
Quoted 4 lines

Hmm, I think it can't hurt to let the userland cleaner use the su_flags. As far as I can tell, it shouldn't affect the kernel side. nilfs_segment_usage_set_clean() would still work and nilfs_sufile_do_scrap() overwrites the whole su_flags as well.

Well, actually the current definition of nilfs_segment_usage_set_clean() and also nilfs_segment_usage_clean() are written without compatibility consideration.

Quoted 6 lines

I actually thought it would be a good idea to wipe the custom flags if a segment is cleaned, which the current implementation does. So the custom flags are only valid for dirty segments and a segment is only considered to be clean with nilfs_segment_usage_clean if there are no custom flags. I don't think that would be unreasonable, because the GC has no use for flags on clean segments anyway.

I looked over functions manipulating su_flags again, and came to the same conclusion. We can keep consistency even if userland gc programs utilize the remaining flags for their own purpose. There are no compatibility issues at least if we manipulate su_flags of dirty segments. In this regard, the current implementation, which wipes the custom flags when it cleans segment, is not bad, yes.

Quoted 7 lines
Quoted 3 lines

It looks to be a separate change if we allow to use the upper bits. In that case, a bunch of changes and a new feature_compat_ro flag to deal it as a disk format change, would be needed.

I think we would only have to define, which flags are reserved for future use and which are available for the userspace GC. Everything else would just work.

Right. My above comment is completely wrong. We don't have to add a new feature-compat flag to use custom flags unless we want to use them for free segments (in this case, we need to change definition of nilfs_segment_usage_clean() and nilfs_segment_usage_set_clean())

Quoted 3 lines
Quoted 1 line

Ok, let's take the above one which protects the upper bits for now.

Ok. It is certainly cleaner that way.

Let me recant my comment. Let's change the patch to allow custom flags.

Quoted 42 lines
Quoted 35 lines
Quoted 11 lines
Quoted 10 lines

Review

Quoted 3 lines
(quoted diff) +2 -0
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

Review

Quoted 1 line
(quoted diff) +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

Quoted 5 lines

I have tested it and it works. At least on my 64 bit architecture. It is probably still a good idea to do an explicit cast.

How about I use s64 for ncleaned and ndirtied and move nilfs_sufile_mod_counter outside the loop?

Yes, this one looks better. In that case, the u64 cast seems unnecessary.

Quoted 14 lines
	s64 ncleaned = 0, ndirtied = 0;

	...

	for (;;) {
		...
	}
	mark_buffer_dirty(bh);
	brelse(bh);

out_mark:

	if (ncleaned || ndirtied) {
		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
				(u64)ndirtied);
Quoted 6 lines
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

This one looks unclear.

How about defining ncleaned and ndirtied with unsigned long type and cast them to (u64) for the arguments of nilfs_sufile_mod_counter() ?

Quoted 8 lines

Ok I agree ncleansegs could be 32 bit on 32 bit systems. But why "unsigned long" and not just "long"? It seems a bit strange to use an unsigned type for possible negative values and I don't see the problem of adding a negative number to an unsigned type of the same size.

Additionally if we use "unsigned long" wouldn't a typecast to (u64) result in a number like 4294967295 rather than 18446744073709551615, which is equivalent to -1, on a 32 bit system?

Yes, sorry, I said wrong thing here too. If we define ncleaned with unsigned long type, it must be arithmetically extended when we convert it to 64 bit size. So, casting with "signed long" is needed like "(long)ncleaned" before converting it to u64.

Quoted 1 line
Quoted 1 line
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

would be calculated as "unsigned long" even if the type of ncleaned is "long" according to the usual arithmetic conversion rule of C99 (6.3.1.8). And, in this case, we can omit the above typecast "(long)".

Regards,
Ryusuke Konishi
--
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

A message that is not in the archive (sent off-list or not yet received): 20140128.163924.157483560.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org

#20 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Hi Andreas,

Quoted 65 lines · Ryusuke Konishi
Quoted 37 lines · Andreas Rohner
Quoted 27 lines · Ryusuke Konishi
Quoted 26 lines · Andreas Rohner
Quoted 24 lines · Ryusuke Konishi

Review

Quoted 3 lines · Andreas Rohner
(quoted diff) +3 -0
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Any comments on this?

Quoted 8 lines
Quoted 4 lines

Hmm, I think it can't hurt to let the userland cleaner use the su_flags. As far as I can tell, it shouldn't affect the kernel side. nilfs_segment_usage_set_clean() would still work and nilfs_sufile_do_scrap() overwrites the whole su_flags as well.

Well, actually the current definition of nilfs_segment_usage_set_clean() and also nilfs_segment_usage_clean() are written without compatibility consideration.

Quoted 6 lines

I actually thought it would be a good idea to wipe the custom flags if a segment is cleaned, which the current implementation does. So the custom flags are only valid for dirty segments and a segment is only considered to be clean with nilfs_segment_usage_clean if there are no custom flags. I don't think that would be unreasonable, because the GC has no use for flags on clean segments anyway.

I looked over functions manipulating su_flags again, and came to the same conclusion. We can keep consistency even if userland gc programs utilize the remaining flags for their own purpose. There are no compatibility issues at least if we manipulate su_flags of dirty segments. In this regard, the current implementation, which wipes the custom flags when it cleans segment, is not bad, yes.

Quoted 7 lines
Quoted 3 lines

It looks to be a separate change if we allow to use the upper bits. In that case, a bunch of changes and a new feature_compat_ro flag to deal it as a disk format change, would be needed.

I think we would only have to define, which flags are reserved for future use and which are available for the userspace GC. Everything else would just work.

Right. My above comment is completely wrong. We don't have to add a new feature-compat flag to use custom flags unless we want to use them for free segments (in this case, we need to change definition of nilfs_segment_usage_clean() and nilfs_segment_usage_set_clean())

Quoted 6 lines
Quoted 3 lines
Quoted 1 line

Ok, let's take the above one which protects the upper bits for now.

Ok. It is certainly cleaner that way.

Let me recant my comment. Let's change the patch to allow custom flags.

By the way, can you post the revised version of this series (kernel patches) before it gets late ?

I'd like to send these 3 patches to upstream so that they will be merged into the mainline in the next merge window.

Userland changes can be merged and released early once we finished review-and-fix process, but it take longer time until kernel patches are merged and released.

Thanks,
Ryusuke Konishi

Quoted 62 lines
Quoted 41 lines
Quoted 34 lines
Quoted 10 lines
Quoted 9 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

Review

Quoted 1 line
(quoted diff) +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

Quoted 5 lines

I have tested it and it works. At least on my 64 bit architecture. It is probably still a good idea to do an explicit cast.

How about I use s64 for ncleaned and ndirtied and move nilfs_sufile_mod_counter outside the loop?

Yes, this one looks better. In that case, the u64 cast seems unnecessary.

Quoted 14 lines
	s64 ncleaned = 0, ndirtied = 0;

	...

	for (;;) {
		...
	}
	mark_buffer_dirty(bh);
	brelse(bh);

out_mark:

	if (ncleaned || ndirtied) {
		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
				(u64)ndirtied);
Quoted 6 lines
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

This one looks unclear.

How about defining ncleaned and ndirtied with unsigned long type and cast them to (u64) for the arguments of nilfs_sufile_mod_counter() ?

Quoted 8 lines

Ok I agree ncleansegs could be 32 bit on 32 bit systems. But why "unsigned long" and not just "long"? It seems a bit strange to use an unsigned type for possible negative values and I don't see the problem of adding a negative number to an unsigned type of the same size.

Additionally if we use "unsigned long" wouldn't a typecast to (u64) result in a number like 4294967295 rather than 18446744073709551615, which is equivalent to -1, on a 32 bit system?

Yes, sorry, I said wrong thing here too. If we define ncleaned with unsigned long type, it must be arithmetically extended when we convert it to 64 bit size. So, casting with "signed long" is needed like "(long)ncleaned" before converting it to u64.

Quoted 1 line
Quoted 1 line
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

would be calculated as "unsigned long" even if the type of ncleaned is "long" according to the usual arithmetic conversion rule of C99 (6.3.1.8). And, in this case, we can omit the above typecast "(long)".

Quoted 6 lines

Regards,
Ryusuke Konishi
--
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

--
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

A message that is not in the archive (sent off-list or not yet received): 20140130.165734.221580541.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org

#22 lore raw

Re: [PATCH v3 2/3] nilfs2: add nilfs_sufile_set_suinfo to update segment usage

Quoted 80 lines · Ryusuke Konishi

Hi Andreas,

Quoted 65 lines · Ryusuke Konishi
Quoted 37 lines · Andreas Rohner
Quoted 27 lines · Ryusuke Konishi
Quoted 26 lines · Andreas Rohner
Quoted 24 lines · Ryusuke Konishi

Review

Quoted 3 lines · Andreas Rohner
(quoted diff) +3 -0
+			|| (nilfs_suinfo_update_flags(sup) &&
+				(sup->sup_sui.sui_flags &
+				(~0UL << (NILFS_SEGMENT_USAGE_ERROR + 1)))))

Ditto. We need to add a definition to nilfs2_fs.h.

enum {
NILFS_SEGMENT_USAGE_ACTIVE,
NILFS_SEGMENT_USAGE_DIRTY,
NILFS_SEGMENT_USAGE_ERROR,
__NR_NILFS_SEGMENT_USAGE_FLAGS
};

		    (nilfs_suinfo_update_flags(sup) &&
		     (sup->sup_sui.sui_flags &
		      (~0UL << __NR_NILFS_SEGMENT_USAGE_FLAGS))))

By the way, this will dismiss the capability that userland cleaner programs uses the rest of su_flags for their own purpose such as GC optimization. I think this (rejecting or utilizing it) should be carefully determined.

Any comments on this?

Quoted 8 lines
Quoted 4 lines

Hmm, I think it can't hurt to let the userland cleaner use the su_flags. As far as I can tell, it shouldn't affect the kernel side. nilfs_segment_usage_set_clean() would still work and nilfs_sufile_do_scrap() overwrites the whole su_flags as well.

Well, actually the current definition of nilfs_segment_usage_set_clean() and also nilfs_segment_usage_clean() are written without compatibility consideration.

Quoted 6 lines

I actually thought it would be a good idea to wipe the custom flags if a segment is cleaned, which the current implementation does. So the custom flags are only valid for dirty segments and a segment is only considered to be clean with nilfs_segment_usage_clean if there are no custom flags. I don't think that would be unreasonable, because the GC has no use for flags on clean segments anyway.

I looked over functions manipulating su_flags again, and came to the same conclusion. We can keep consistency even if userland gc programs utilize the remaining flags for their own purpose. There are no compatibility issues at least if we manipulate su_flags of dirty segments. In this regard, the current implementation, which wipes the custom flags when it cleans segment, is not bad, yes.

Quoted 7 lines
Quoted 3 lines

It looks to be a separate change if we allow to use the upper bits. In that case, a bunch of changes and a new feature_compat_ro flag to deal it as a disk format change, would be needed.

I think we would only have to define, which flags are reserved for future use and which are available for the userspace GC. Everything else would just work.

Right. My above comment is completely wrong. We don't have to add a new feature-compat flag to use custom flags unless we want to use them for free segments (in this case, we need to change definition of nilfs_segment_usage_clean() and nilfs_segment_usage_set_clean())

Quoted 6 lines
Quoted 3 lines
Quoted 1 line

Ok, let's take the above one which protects the upper bits for now.

Ok. It is certainly cleaner that way.

Let me recant my comment. Let's change the patch to allow custom flags.

By the way, can you post the revised version of this series (kernel patches) before it gets late ?

I'd like to send these 3 patches to upstream so that they will be merged into the mainline in the next merge window.

Quoted 6 lines

Userland changes can be merged and released early once we finished review-and-fix process, but it take longer time until kernel patches are merged and released.

Thanks,
Ryusuke Konishi

Sure. I'll send them as soon as possible.

Thanks,
Andreas Rohner

Quoted 62 lines
Quoted 62 lines
Quoted 41 lines
Quoted 34 lines
Quoted 10 lines
Quoted 9 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			nilfs_sufile_mod_counter(header_bh, ncleansegs,
+					ndirtysegs);

Does it work for a negative value without cast of (u64) ? Please confirm that these counters are updated as you expected.

Review

Quoted 1 line
(quoted diff) +1 -0
+			NILFS_SUI(sufile)->ncleansegs += ncleansegs;

Ditto.

Quoted 5 lines

I have tested it and it works. At least on my 64 bit architecture. It is probably still a good idea to do an explicit cast.

How about I use s64 for ncleaned and ndirtied and move nilfs_sufile_mod_counter outside the loop?

Yes, this one looks better. In that case, the u64 cast seems unnecessary.

Quoted 14 lines
	s64 ncleaned = 0, ndirtied = 0;

	...

	for (;;) {
		...
	}
	mark_buffer_dirty(bh);
	brelse(bh);

out_mark:

	if (ncleaned || ndirtied) {
		nilfs_sufile_mod_counter(header_bh, (u64)ncleaned,
				(u64)ndirtied);
Quoted 6 lines
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

This one looks unclear.

How about defining ncleaned and ndirtied with unsigned long type and cast them to (u64) for the arguments of nilfs_sufile_mod_counter() ?

Quoted 8 lines

Ok I agree ncleansegs could be 32 bit on 32 bit systems. But why "unsigned long" and not just "long"? It seems a bit strange to use an unsigned type for possible negative values and I don't see the problem of adding a negative number to an unsigned type of the same size.

Additionally if we use "unsigned long" wouldn't a typecast to (u64) result in a number like 4294967295 rather than 18446744073709551615, which is equivalent to -1, on a 32 bit system?

Yes, sorry, I said wrong thing here too. If we define ncleaned with unsigned long type, it must be arithmetically extended when we convert it to 64 bit size. So, casting with "signed long" is needed like "(long)ncleaned" before converting it to u64.

Quoted 1 line
Quoted 1 line
Quoted 1 line
		NILFS_SUI(sufile)->ncleansegs += ncleaned;

would be calculated as "unsigned long" even if the type of ncleaned is "long" according to the usual arithmetic conversion rule of C99 (6.3.1.8). And, in this case, we can omit the above typecast "(long)".

Quoted 7 lines
Quoted 6 lines

Regards,
Ryusuke Konishi
--
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

--
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

#23 lore raw

PATCH v3 3/3 nilfs2: implementation of NILFS_IOCTL_SET_SUINFO ioctl

In reply to a message not in the archive

With this ioctl the segment usage entries in the SUFILE can be updated from userspace.

This is useful, because it allows the userspace GC to modify and update segment usage entries for specific segments, which enables it to avoid unnecessary write operations.

If a segment needs to be cleaned, but there is no or very little reclaimable space in it, the cleaning operation basically degrades to a useless moving operation. In the end the only thing that changes is the location of the data and a timestamp in the segment usage information. With this ioctl the GC can skip the cleaning and update the segment usage entries directly instead.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

---
 fs/nilfs2/ioctl.c         | 61 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/nilfs2_fs.h |  2 ++
 2 files changed, 63 insertions(+)
fs/nilfs2/ioctl.c +61 -0
index b44bdb2..e97df9c 100644
@@ -767,6 +767,64 @@ out:
 	return ret;
 }
 
+static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
+				unsigned int cmd, void __user *argp)
+{
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+	struct nilfs_transaction_info ti;
+	struct nilfs_argv argv;
+	size_t len;
+	void __user *base;
+	void *kbuf;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ret = mnt_want_write_file(filp);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	if (copy_from_user(&argv, argp, sizeof(argv)))
+		goto out;
+
+	ret = -EINVAL;
+	if (argv.v_size < sizeof(struct nilfs_suinfo_update))
+		goto out;
+
+	if (argv.v_nmembs > nilfs->ns_nsegments)
+		goto out;
+
+	len = argv.v_size * argv.v_nmembs;
+	base = (void __user *)(unsigned long)argv.v_base;
+	kbuf = vmalloc(len);
+	if (!kbuf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(kbuf, base, len)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	nilfs_transaction_begin(inode->i_sb, &ti, 0);
+	ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
+			argv.v_nmembs);
+	if (unlikely(ret < 0))
+		nilfs_transaction_abort(inode->i_sb);
+	else
+		nilfs_transaction_commit(inode->i_sb); /* never fails */
+
+out_free:
+	vfree(kbuf);
+out:
+	mnt_drop_write_file(filp);
+	return ret;
+}
+
+
 static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
 				unsigned int cmd, void __user *argp,
 				size_t membsz,
@@ -820,6 +878,8 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
 					    sizeof(struct nilfs_suinfo),
 					    nilfs_ioctl_do_get_suinfo);
+	case NILFS_IOCTL_SET_SUINFO:
+		return nilfs_ioctl_set_suinfo(inode, filp, cmd, argp);
 	case NILFS_IOCTL_GET_SUSTAT:
 		return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
 	case NILFS_IOCTL_GET_VINFO:
@@ -859,6 +919,7 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case NILFS_IOCTL_GET_CPINFO:
 	case NILFS_IOCTL_GET_CPSTAT:
 	case NILFS_IOCTL_GET_SUINFO:
+	case NILFS_IOCTL_SET_SUINFO:
 	case NILFS_IOCTL_GET_SUSTAT:
 	case NILFS_IOCTL_GET_VINFO:
 	case NILFS_IOCTL_GET_BDESCS:
include/linux/nilfs2_fs.h +2 -0
index 7b94449..4140f7f 100644
@@ -904,5 +904,7 @@ struct nilfs_bdesc {
 	_IOW(NILFS_IOCTL_IDENT, 0x8B, __u64)
 #define NILFS_IOCTL_SET_ALLOC_RANGE  \
 	_IOW(NILFS_IOCTL_IDENT, 0x8C, __u64[2])
+#define NILFS_IOCTL_SET_SUINFO  \
+	_IOW(NILFS_IOCTL_IDENT, 0x8D, struct nilfs_argv)
 
 #endif	/* _LINUX_NILFS_FS_H */
Signature · 6 lines
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

A message that is not in the archive (sent off-list or not yet received): ce24b310783bf1a501408eeb0dfa268155c07444.1390816620.git.andreas.rohner-hi6Y0CQ0nG0@public.gmane.org

#25 lore raw

Re: [PATCH v3 3/3] nilfs2: implementation of NILFS_IOCTL_SET_SUINFO ioctl

Quoted 52 lines · Andreas Rohner

With this ioctl the segment usage entries in the SUFILE can be updated from userspace.

This is useful, because it allows the userspace GC to modify and update segment usage entries for specific segments, which enables it to avoid unnecessary write operations.

If a segment needs to be cleaned, but there is no or very little reclaimable space in it, the cleaning operation basically degrades to a useless moving operation. In the end the only thing that changes is the location of the data and a timestamp in the segment usage information. With this ioctl the GC can skip the cleaning and update the segment usage entries directly instead.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

---
 fs/nilfs2/ioctl.c         | 61 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/nilfs2_fs.h |  2 ++
 2 files changed, 63 insertions(+)
fs/nilfs2/ioctl.c +20 -0
index b44bdb2..e97df9c 100644
@@ -767,6 +767,64 @@ out:
 	return ret;
 }
 
+static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
+				unsigned int cmd, void __user *argp)
+{
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+	struct nilfs_transaction_info ti;
+	struct nilfs_argv argv;
+	size_t len;
+	void __user *base;
+	void *kbuf;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ret = mnt_want_write_file(filp);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	if (copy_from_user(&argv, argp, sizeof(argv)))

fs/nilfs2/ioctl.c out: · line 799

Quoted 10 lines
fs/nilfs2/ioctl.c +10 -0
+		goto out;
+
+	ret = -EINVAL;
+	if (argv.v_size < sizeof(struct nilfs_suinfo_update))
+		goto out;
+
+	if (argv.v_nmembs > nilfs->ns_nsegments)
+		goto out;
+
+	len = argv.v_size * argv.v_nmembs;

The following check should be inserted to avoid overflow of variable "len".

	if (argv.v_nmembs >= UINT_MAX / argv.v_size)
		goto out;

The size argument of vmalloc() is unsigned long, but sizeof(unsinged long) differs depending on architecture, thus undesirable.

The following check also should be inserted because vmalloc(0) arises a warning returning NULL.

	if (!len) {
		ret = 0;
		goto out;
	}

Regards,
Ryusuke Konishi

Quoted 68 lines
fs/nilfs2/ioctl.c +28 -0
+	base = (void __user *)(unsigned long)argv.v_base;
 
+	kbuf = vmalloc(len);
+	if (!kbuf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(kbuf, base, len)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	nilfs_transaction_begin(inode->i_sb, &ti, 0);
+	ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
+			argv.v_nmembs);
+	if (unlikely(ret < 0))
+		nilfs_transaction_abort(inode->i_sb);
+	else
+		nilfs_transaction_commit(inode->i_sb); /* never fails */
+
+out_free:
+	vfree(kbuf);
+out:
+	mnt_drop_write_file(filp);
+	return ret;
+}
+
+
 static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
 				unsigned int cmd, void __user *argp,
fs/nilfs2/ioctl.c +3 -0
 				size_t membsz,
@@ -820,6 +878,8 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
 					    sizeof(struct nilfs_suinfo),
 					    nilfs_ioctl_do_get_suinfo);
+	case NILFS_IOCTL_SET_SUINFO:
+		return nilfs_ioctl_set_suinfo(inode, filp, cmd, argp);
 	case NILFS_IOCTL_GET_SUSTAT:
 		return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
 	case NILFS_IOCTL_GET_VINFO:
@@ -859,6 +919,7 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case NILFS_IOCTL_GET_CPINFO:
 	case NILFS_IOCTL_GET_CPSTAT:
 	case NILFS_IOCTL_GET_SUINFO:
+	case NILFS_IOCTL_SET_SUINFO:
 	case NILFS_IOCTL_GET_SUSTAT:
 	case NILFS_IOCTL_GET_VINFO:
 	case NILFS_IOCTL_GET_BDESCS:
include/linux/nilfs2_fs.h +2 -0
index 7b94449..4140f7f 100644
@@ -904,5 +904,7 @@ struct nilfs_bdesc {
 	_IOW(NILFS_IOCTL_IDENT, 0x8B, __u64)
 #define NILFS_IOCTL_SET_ALLOC_RANGE  \
 	_IOW(NILFS_IOCTL_IDENT, 0x8C, __u64[2])
+#define NILFS_IOCTL_SET_SUINFO  \
+	_IOW(NILFS_IOCTL_IDENT, 0x8D, struct nilfs_argv)
 
 #endif	/* _LINUX_NILFS_FS_H */
Signature · 6 lines
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

--
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

#26 lore raw

Re: [PATCH v3 1/3] nilfs2: add struct nilfs_suinfo_update and flags

In reply to a message not in the archive
Quoted 63 lines · Andreas Rohner

This patch adds the nilfs_suinfo_update structure, which contains the information needed to update one segment usage entry. The flags specify, which fields need to be updated.

---
 include/linux/nilfs2_fs.h | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
include/linux/nilfs2_fs.h +41 -0
index 9875576..7b94449 100644
@@ -709,6 +709,47 @@ static inline int nilfs_suinfo_clean(const struct nilfs_suinfo *si)
 	return !si->sui_flags;
 }
 
+/**
+ * nilfs_suinfo_update - segment usage information update
+ * @sup_segnum: segment number
+ * @sup_flags: flags for which fields are active in sup_sui
+ * @sup_reserved: reserved necessary for alignment
+ * @sup_sui: segment usage information
+ */
+struct nilfs_suinfo_update {
+	__u64 sup_segnum;
+	__u32 sup_flags;
+	__u32 sup_reserved;
+	struct nilfs_suinfo sup_sui;
+};
+
+enum {
+	NILFS_SUINFO_UPDATE_LASTMOD,
+	NILFS_SUINFO_UPDATE_NBLOCKS,
+	NILFS_SUINFO_UPDATE_FLAGS,
+};
+
+#define NILFS_SUINFO_UPDATE_FNS(flag, name)				\
+static inline void							\
+nilfs_suinfo_update_set_##name(struct nilfs_suinfo_update *sup)		\
+{									\
+	sup->sup_flags |= 1UL << NILFS_SUINFO_UPDATE_##flag;		\
+}									\
+static inline void							\
+nilfs_suinfo_update_clear_##name(struct nilfs_suinfo_update *sup)	\
+{									\
+	sup->sup_flags &= ~(1UL << NILFS_SUINFO_UPDATE_##flag);		\
+}									\
+static inline int							\
+nilfs_suinfo_update_##name(const struct nilfs_suinfo_update *sup)	\
+{									\
+	return !!(sup->sup_flags & (1UL << NILFS_SUINFO_UPDATE_##flag));\
+}
+
+NILFS_SUINFO_UPDATE_FNS(LASTMOD, lastmod)
+NILFS_SUINFO_UPDATE_FNS(NBLOCKS, nblocks)
+NILFS_SUINFO_UPDATE_FNS(FLAGS, flags)
+
 /* ioctl */
 enum {
 	NILFS_CHECKPOINT,
Signature · 1 line
1.8.5.3

This patch looks good to me.

Strictly speaking, these declarations should be inserted in the ioctl section of nilfs2_fs.h which starts from the comment line /* ioctl */ instead of the disk format section. But, the current constuction of nilfs2_fs.h is already broken :(

The insert position you selected seems appropriate for now.

Regards,
Ryusuke Konishi
--
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

#27 lore raw
In reply to a message not in the archive

Hi Andreas,

Quoted 51 lines · Andreas Rohner

Hi,

This is the third version of this patch set. It basically fixes a lot of bugs.

v2->v3
* Alignment in nilfs_suinfo_update
* Add missing comments
* nilfs2: Extra validity checks in nilfs_sufile_set_suinfo
* nilfs2: Update sh_ncleansegs, sh_ndirtysegs if flags change
* nilfs2: Fix bugs in nilfs_sufile_set_suinfo
* nilfs2: Use vmalloc instead of ioctl_wrap_copy
* nilfs-utils: Separate nilfs_relaim_segments_with_threshold
* nilfs-utils: Allow different units for min_reclaimable_blocks
* nilfs-utils: Introduce flag to disable the optimization
* nilfs-utils: Disable optimization if kernel retruns ENOTTY
* nilfs-utils: Remove EGCTRYAGAIN error return code
* nilfs-utils: Rename option to min_reclaimable_blocks v1->v2
* Implementation of NILFS_IOCTL_SET_SUINFO
* Added mc_min_free_blocks_threshold config option (if clean segments < min_clean_segments)
* Added new command line param for nilfs-clean
* Update man- and config-file

This patch set adds an optimized version of nilfs_reclaim_segments, which has an additional parameter min_reclaimable. This parameter specifies the minimum number of reclaimable blocks in a segment, before it can be cleaned. If a segment is below this threshold, it is considered to be not worth cleaning, because all the live blocks would need to be moved to a new segment, which is expensive, and the number of reclaimable blocks is too low. But it is still necessary to update the segment usage information to turn the old segment into a new one.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

Additionally new options are introduced for the configuration file and nilfs-clean to allow the user to specify the threshold.

This is potentially useful for all gc policies, but it is especially beneficial for the timestamp policy. Lets assume for example a NILFS2 volume with 20% static files and lets assume these static files are in the oldest segments. The current timestamp policy will select the oldest segments and, since the data is static, move them mostly unchanged to new segments. After a while they will become the oldest segments again. Then timestamp will move them again. These moving operations are expensive and unnecessary.

Quoted 2 lines

The benchmarks are currently running. I will give you the results shortly.

The kernel patchset didn't apply to the mainline as is because Vyacheslav's ioctl commentary patch just has been merged. Please rebase your patchset on the current master branch next time. Also, nilfs_ioctl_set_suinfo() function needs summary comment as for the current master branch.

Anyway, I will review the kernel patches first, and then look into the userland patches.

Regards,
Ryusuke Konishi

Quoted 10 lines

Regards,
Andreas Rohner

---
Andreas Rohner (4):
nilfs-utils: cldconfig add an option to set min. reclaimable blocks
nilfs-utils: nilfs-clean add cmdline param min-reclaimable-blocks
nilfs-utils: add suport for NILFS_IOCTL_SET_SUINFO ioctl
nilfs-utils: add optimized version of nilfs_reclaim_segments

Quoted 22 lines
 include/nilfs.h                   |   9 +-
 include/nilfs2_fs.h               |  43 ++++++++++
 include/nilfs_cleaner.h           |  19 +++--
 include/nilfs_gc.h                |   4 +
 lib/gc.c                          | 112 ++++++++++++++++++++-----
 lib/nilfs.c                       |  60 ++++++++++++++
 man/nilfs-clean.8                 |   4 +
 man/nilfs_cleanerd.conf.5         |  22 +++++
 sbin/cleanerd/cldconfig.c         | 168 ++++++++++++++++++++++++++++----------
 sbin/cleanerd/cldconfig.h         |   8 ++
 sbin/cleanerd/cleanerd.c          |  39 ++++++++-
 sbin/cleanerd/nilfs_cleanerd.conf |  13 +++
 sbin/nilfs-clean/nilfs-clean.c    |  44 ++++++++--
 13 files changed, 466 insertions(+), 79 deletions(-)
Signature · 6 lines
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

--
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

A message that is not in the archive (sent off-list or not yet received): 20140128.000336.27790167.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org

#29 lore raw
Quoted 53 lines · Ryusuke Konishi

Hi Andreas,

Quoted 51 lines · Andreas Rohner

Hi,

This is the third version of this patch set. It basically fixes a lot of bugs.

v2->v3
* Alignment in nilfs_suinfo_update
* Add missing comments
* nilfs2: Extra validity checks in nilfs_sufile_set_suinfo
* nilfs2: Update sh_ncleansegs, sh_ndirtysegs if flags change
* nilfs2: Fix bugs in nilfs_sufile_set_suinfo
* nilfs2: Use vmalloc instead of ioctl_wrap_copy
* nilfs-utils: Separate nilfs_relaim_segments_with_threshold
* nilfs-utils: Allow different units for min_reclaimable_blocks
* nilfs-utils: Introduce flag to disable the optimization
* nilfs-utils: Disable optimization if kernel retruns ENOTTY
* nilfs-utils: Remove EGCTRYAGAIN error return code
* nilfs-utils: Rename option to min_reclaimable_blocks v1->v2
* Implementation of NILFS_IOCTL_SET_SUINFO
* Added mc_min_free_blocks_threshold config option (if clean segments < min_clean_segments)
* Added new command line param for nilfs-clean
* Update man- and config-file

This patch set adds an optimized version of nilfs_reclaim_segments, which has an additional parameter min_reclaimable. This parameter specifies the minimum number of reclaimable blocks in a segment, before it can be cleaned. If a segment is below this threshold, it is considered to be not worth cleaning, because all the live blocks would need to be moved to a new segment, which is expensive, and the number of reclaimable blocks is too low. But it is still necessary to update the segment usage information to turn the old segment into a new one.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

Additionally new options are introduced for the configuration file and nilfs-clean to allow the user to specify the threshold.

This is potentially useful for all gc policies, but it is especially beneficial for the timestamp policy. Lets assume for example a NILFS2 volume with 20% static files and lets assume these static files are in the oldest segments. The current timestamp policy will select the oldest segments and, since the data is static, move them mostly unchanged to new segments. After a while they will become the oldest segments again. Then timestamp will move them again. These moving operations are expensive and unnecessary.

Quoted 8 lines
Quoted 2 lines

The benchmarks are currently running. I will give you the results shortly.

The kernel patchset didn't apply to the mainline as is because Vyacheslav's ioctl commentary patch just has been merged. Please rebase your patchset on the current master branch next time. Also, nilfs_ioctl_set_suinfo() function needs summary comment as for the current master branch.

Sorry for that, I based it on 3.13. I will rebase it immediateley and add the summary comment.

Quoted 2 lines

Anyway, I will review the kernel patches first, and then look into the userland patches.

Thanks. By the way, is it ok to use one cover letter for both the userland and kernel patches?

br,
Andreas Rohner
--
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

A message that is not in the archive (sent off-list or not yet received): [email protected]

#31 lore raw
Quoted 57 lines · Andreas Rohner
Quoted 56 lines · Ryusuke Konishi

Hi Andreas,

Quoted 53 lines · Andreas Rohner

Hi,

This is the third version of this patch set. It basically fixes a lot of bugs.

v2->v3
* Alignment in nilfs_suinfo_update
* Add missing comments
* nilfs2: Extra validity checks in nilfs_sufile_set_suinfo
* nilfs2: Update sh_ncleansegs, sh_ndirtysegs if flags change
* nilfs2: Fix bugs in nilfs_sufile_set_suinfo
* nilfs2: Use vmalloc instead of ioctl_wrap_copy
* nilfs-utils: Separate nilfs_relaim_segments_with_threshold
* nilfs-utils: Allow different units for min_reclaimable_blocks
* nilfs-utils: Introduce flag to disable the optimization
* nilfs-utils: Disable optimization if kernel retruns ENOTTY
* nilfs-utils: Remove EGCTRYAGAIN error return code
* nilfs-utils: Rename option to min_reclaimable_blocks v1->v2
* Implementation of NILFS_IOCTL_SET_SUINFO
* Added mc_min_free_blocks_threshold config option (if clean segments < min_clean_segments)
* Added new command line param for nilfs-clean
* Update man- and config-file

This patch set adds an optimized version of nilfs_reclaim_segments, which has an additional parameter min_reclaimable. This parameter specifies the minimum number of reclaimable blocks in a segment, before it can be cleaned. If a segment is below this threshold, it is considered to be not worth cleaning, because all the live blocks would need to be moved to a new segment, which is expensive, and the number of reclaimable blocks is too low. But it is still necessary to update the segment usage information to turn the old segment into a new one.

This is basically a shortcut to cleaning the segment. It is still necessary to read the segment summary information, but the writing of the live blocks can be skipped if it's not worth it.

Additionally new options are introduced for the configuration file and nilfs-clean to allow the user to specify the threshold.

This is potentially useful for all gc policies, but it is especially beneficial for the timestamp policy. Lets assume for example a NILFS2 volume with 20% static files and lets assume these static files are in the oldest segments. The current timestamp policy will select the oldest segments and, since the data is static, move them mostly unchanged to new segments. After a while they will become the oldest segments again. Then timestamp will move them again. These moving operations are expensive and unnecessary.

The benchmarks are currently running. I will give you the results shortly.

Quoted 8 lines
Quoted 5 lines

The kernel patchset didn't apply to the mainline as is because Vyacheslav's ioctl commentary patch just has been merged. Please rebase your patchset on the current master branch next time. Also, nilfs_ioctl_set_suinfo() function needs summary comment as for the current master branch.

Sorry for that, I based it on 3.13. I will rebase it immediateley and add the summary comment.

I already rebased it manually. Please wait until I complete the review for all patches.

Quoted 5 lines
Quoted 2 lines

Anyway, I will review the kernel patches first, and then look into the userland patches.

Thanks. By the way, is it ok to use one cover letter for both the userland and kernel patches?

No problem. In either case, I will add a cover letter when I send them to upstream.

Regards,
Ryusuke Konishi
--
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

#32 lore raw
In reply to a message not in the archive
Quoted 2 lines · Andreas Rohner

The benchmarks are currently running. I will give you the results shortly.

Here are the promised results:

I used a 100GB nilfs2 volume on both a HDD and a SDD and the well known fs_mark benchmark tool. The benchmark consisted of the following steps:

1. Write a 20GB file (static data)
2. fs_mark -d dir -L 135 -D 16 -t 16 -n 150 -s 131072 -S 1 -w 4096
3. Wait for the cleaner to reach max_clean_segments

The following key configuration options were used:

min_clean_segments        20%
max_clean_segments        22%
nsegments_per_clean       4
mc_nsegments_per_clean    4
cleaning_interval         0.5
mc_cleaning_interval      0.5
min_reclaimable_blocks    5%

mc_min_reclaimable_blocks 1%
use_set_suinfo

HDD:

    Timestamp GB Written: 140.2588
    Timestamp GB Read:    48.06372
    Timestamp Runtime:    4145.151s
    Timestamp Disk Util.: 94%

    Patched GB Written:   120.1527
    Patched GB Read:      28.28576
    Patched Runtime:      3692.105s
    Patched Disk Util.:   93%

SSD:

    Timestamp GB Written: 210.2145
    Timestamp GB Read:    48.79246
    Timestamp Runtime:    3883.966s
    Timestamp Disk Util.: 87%

    Patched GB Written:   168.6009
    Patched GB Read:      28.66516
    Patched Runtime:      3566.425s
    Patched Disk Util.:   90%

The disk utilization is measured after step 2, because after step 3 it is always 78%.

The results for the HDD show, that the 20 GB of static data were moved in the case of the normal timestamp policy and they were ignored in case of the patched timestamp policy.

The results for the SSD were similar, but the difference in GBs written is 40 GB instead of 20 GB, which is a bit strange.

The value of 1% for mc_min_reclaimable_blocks seems to be ideal, because it is just enough, so that completely full segments fall below the threshold and can be skipped.

br,
Andreas Rohner

--
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