On Wed, 5 Feb 2014 03:16:34 +0100, Andreas Rohner wrote:
> 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.
>
> Signed-off-by: Andreas Rohner <[email protected]>
> ---
> man/nilfs_cleanerd.conf.5 | 22 +++++
> sbin/cleanerd/cldconfig.c | 168
> ++++++++++++++++++++++++++++----------
> sbin/cleanerd/cldconfig.h | 8 ++
> sbin/cleanerd/cleanerd.c | 9 ++
> sbin/cleanerd/nilfs_cleanerd.conf | 13 +++
> 5 files changed, 178 insertions(+), 42 deletions(-)
>
> diff --git a/man/nilfs_cleanerd.conf.5 b/man/nilfs_cleanerd.conf.5
> index 8f3fcd2..4315ecd 100644
> --- a/man/nilfs_cleanerd.conf.5
> +++ b/man/nilfs_cleanerd.conf.5
> @@ -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,
> diff --git a/sbin/cleanerd/cldconfig.c b/sbin/cleanerd/cldconfig.c
> index 270d360..b69f060 100644
> --- a/sbin/cleanerd/cldconfig.c
> +++ b/sbin/cleanerd/cldconfig.c
> @@ -278,6 +278,54 @@ nilfs_cldconfig_handle_protection_period(struct
> nilfs_cldconfig *config,
> }
>
> static unsigned long long
> +nilfs_convert_units_to_bytes(struct nilfs_param *param) {
Adding "const" qualifier is preferred for this argument. And, please
put the opening brace at the beginning of the next line for functions:
static unsigned long long
nilfs_convert_units_to_bytes(const struct nilfs_param *param)
{
> + unsigned long long bytes = param->num;
> +
> + switch (param->unit) {
> + case NILFS_SIZE_UNIT_KB:
> + bytes *= 1000ULL;
> + break;
> + case NILFS_SIZE_UNIT_KIB:
> + bytes <<= 10;
> + break;
> + case NILFS_SIZE_UNIT_MB:
> + bytes *= 1000000ULL;
> + break;
> + case NILFS_SIZE_UNIT_MIB:
> + bytes <<= 20;
> + break;
> + case NILFS_SIZE_UNIT_GB:
> + bytes *= 1000000000ULL;
> + break;
> + case NILFS_SIZE_UNIT_GIB:
> + bytes <<= 30;
> + break;
> + case NILFS_SIZE_UNIT_TB:
> + bytes *= 1000000000000ULL;
> + break;
> + case NILFS_SIZE_UNIT_TIB:
> + bytes <<= 40;
> + break;
> + case NILFS_SIZE_UNIT_PB:
> + bytes *= 1000000000000000ULL;
> + break;
> + case NILFS_SIZE_UNIT_PIB:
> + bytes <<= 50;
> + break;
> + case NILFS_SIZE_UNIT_EB:
> + bytes *= 1000000000000000000ULL;
> + break;
> + case NILFS_SIZE_UNIT_EIB:
> + bytes <<= 60;
> + break;
> + default:
> + assert(0);
> + }
> +
> + return bytes;
> +}
> +
> +static unsigned long long
> nilfs_convert_size_to_nsegments(struct nilfs *nilfs, struct nilfs_param
> *param)
> {
> unsigned long long ret, segment_size, bytes;
> @@ -287,48 +335,7 @@ nilfs_convert_size_to_nsegments(struct nilfs *nilfs,
> struct nilfs_param *param)
> } else if (param->unit == NILFS_SIZE_UNIT_PERCENT) {
> ret = (nilfs_get_nsegments(nilfs) * param->num + 99) / 100;
> } else {
> - bytes = param->num;
> -
> - switch (param->unit) {
> - case NILFS_SIZE_UNIT_KB:
> - bytes *= 1000ULL;
> - break;
> - case NILFS_SIZE_UNIT_KIB:
> - bytes <<= 10;
> - break;
> - case NILFS_SIZE_UNIT_MB:
> - bytes *= 1000000ULL;
> - break;
> - case NILFS_SIZE_UNIT_MIB:
> - bytes <<= 20;
> - break;
> - case NILFS_SIZE_UNIT_GB:
> - bytes *= 1000000000ULL;
> - break;
> - case NILFS_SIZE_UNIT_GIB:
> - bytes <<= 30;
> - break;
> - case NILFS_SIZE_UNIT_TB:
> - bytes *= 1000000000000ULL;
> - break;
> - case NILFS_SIZE_UNIT_TIB:
> - bytes <<= 40;
> - break;
> - case NILFS_SIZE_UNIT_PB:
> - bytes *= 1000000000000000ULL;
> - break;
> - case NILFS_SIZE_UNIT_PIB:
> - bytes <<= 50;
> - break;
> - case NILFS_SIZE_UNIT_EB:
> - bytes *= 1000000000000000000ULL;
> - break;
> - case NILFS_SIZE_UNIT_EIB:
> - bytes <<= 60;
> - break;
> - default:
> - assert(0);
> - }
> + bytes = nilfs_convert_units_to_bytes(param);
> segment_size = nilfs_get_block_size(nilfs) *
> nilfs_get_blocks_per_segment(nilfs);
> ret = (bytes + segment_size - 1) / segment_size;
> @@ -455,6 +462,52 @@ nilfs_cldconfig_handle_mc_nsegments_per_clean(struct
> nilfs_cldconfig *config,
> return 0;
> }
>
> +static unsigned long long
> +nilfs_convert_size_to_blocks_per_segment(struct nilfs *nilfs,
> + struct nilfs_param *param)
> +{
> + unsigned long long ret, segment_size, block_size, bytes;
> +
> + if (param->unit == NILFS_SIZE_UNIT_NONE) {
> + ret = param->num;
> + } else if (param->unit == NILFS_SIZE_UNIT_PERCENT) {
> + ret = (nilfs_get_blocks_per_segment(nilfs) * param->num) / 100;
> + } else {
> + block_size = nilfs_get_block_size(nilfs);
> + segment_size = block_size *
> + nilfs_get_blocks_per_segment(nilfs);
> + bytes = nilfs_convert_units_to_bytes(param) % segment_size;
> + ret = (bytes + block_size - 1) / block_size;
> + }
> + return ret;
> +}
> +
> +static int
> +nilfs_cldconfig_handle_min_reclaimable_blocks(struct nilfs_cldconfig *config,
> + char **tokens, size_t ntoks,
> + struct nilfs *nilfs)
> +{
> + struct nilfs_param param;
> +
> + if (nilfs_cldconfig_get_size_argument(tokens, ntoks, ¶m) == 0)
> + config->cf_min_reclaimable_blocks =
> + nilfs_convert_size_to_blocks_per_segment(nilfs, ¶m);
> + return 0;
> +}
> +
> +static int
> +nilfs_cldconfig_handle_mc_min_reclaimable_blocks(struct nilfs_cldconfig
> *config,
> + char **tokens, size_t ntoks,
> + struct nilfs *nilfs)
> +{
> + struct nilfs_param param;
> +
> + if (nilfs_cldconfig_get_size_argument(tokens, ntoks, ¶m) == 0)
> + config->cf_mc_min_reclaimable_blocks =
> + nilfs_convert_size_to_blocks_per_segment(nilfs, ¶m);
> + return 0;
> +}
> +
> static int
> nilfs_cldconfig_handle_cleaning_interval(struct nilfs_cldconfig *config,
> char **tokens, size_t ntoks,
> @@ -490,6 +543,14 @@ static int nilfs_cldconfig_handle_use_mmap(struct
> nilfs_cldconfig *config,
> return 0;
> }
>
> +static int nilfs_cldconfig_handle_use_set_suinfo(struct nilfs_cldconfig
> *config,
> + char **tokens, size_t ntoks,
> + struct nilfs *nilfs)
> +{
> + config->cf_use_set_suinfo = 1;
> + return 0;
> +}
> +
> static const struct nilfs_cldconfig_log_priority
> nilfs_cldconfig_log_priority_table[] = {
> {"emerg", LOG_EMERG},
> @@ -576,6 +637,18 @@ nilfs_cldconfig_keyword_table[] = {
> "log_priority", 2, 2,
> nilfs_cldconfig_handle_log_priority
> },
> + {
> + "min_reclaimable_blocks", 2, 2,
> + nilfs_cldconfig_handle_min_reclaimable_blocks
> + },
> + {
> + "mc_min_reclaimable_blocks", 2, 2,
> + nilfs_cldconfig_handle_mc_min_reclaimable_blocks
> + },
> + {
> + "use_set_suinfo", 1, 1,
> + nilfs_cldconfig_handle_use_set_suinfo
> + },
> };
>
> #define NILFS_CLDCONFIG_NKEYWORDS \
> @@ -640,7 +713,18 @@ static void nilfs_cldconfig_set_default(struct
> nilfs_cldconfig *config,
> config->cf_retry_interval.tv_sec = NILFS_CLDCONFIG_RETRY_INTERVAL;
> config->cf_retry_interval.tv_usec = 0;
> config->cf_use_mmap = NILFS_CLDCONFIG_USE_MMAP;
> + config->cf_use_set_suinfo = NILFS_CLDCONFIG_USE_SET_SUINFO;
> config->cf_log_priority = NILFS_CLDCONFIG_LOG_PRIORITY;
> +
> + param.num = NILFS_CLDCONFIG_MIN_RECLAIMABLE_BLOCKS;
> + param.unit = NILFS_CLDCONFIG_MIN_RECLAIMABLE_BLOCKS_UNIT;
> + config->cf_min_reclaimable_blocks =
> + nilfs_convert_size_to_blocks_per_segment(nilfs, ¶m);
> +
> + param.num = NILFS_CLDCONFIG_MC_MIN_RECLAIMABLE_BLOCKS;
> + param.unit = NILFS_CLDCONFIG_MC_MIN_RECLAIMABLE_BLOCKS_UNIT;
> + config->cf_mc_min_reclaimable_blocks =
> + nilfs_convert_size_to_blocks_per_segment(nilfs, ¶m);
> }
>
> static inline int iseol(int c)
> diff --git a/sbin/cleanerd/cldconfig.h b/sbin/cleanerd/cldconfig.h
> index 188ce9b..e7ac72e 100644
> --- a/sbin/cleanerd/cldconfig.h
> +++ b/sbin/cleanerd/cldconfig.h
> @@ -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;
Corresponding comment is missing.
> 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
>
> diff --git a/sbin/cleanerd/cleanerd.c b/sbin/cleanerd/cleanerd.c
> index 1d09b5b..b441448 100644
> --- a/sbin/cleanerd/cleanerd.c
> +++ b/sbin/cleanerd/cleanerd.c
> @@ -172,6 +172,7 @@ struct nilfs_cleanerd {
> struct timeval cleaning_interval;
> struct timeval target;
> struct timeval timeout;
> + unsigned long min_reclaimable_blocks;
Ditto.
> __u64 prev_nongc_ctime;
> mqd_t recvq;
> char *recvq_name;
> @@ -273,6 +274,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 +1241,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 */
> @@ -1442,6 +1449,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))
> diff --git a/sbin/cleanerd/nilfs_cleanerd.conf
> b/sbin/cleanerd/nilfs_cleanerd.conf
> index 26872aa..f88a57a 100644
> --- a/sbin/cleanerd/nilfs_cleanerd.conf
> +++ b/sbin/cleanerd/nilfs_cleanerd.conf
> @@ -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%
Description on suffixes is needed:
# The argument of min_reclaimable_blocks and mc_min_reclaimable_blocks
# can be followed by a percent sign (%) or one of the following
# multiplicative suffixes similar to min_clean_segments.
#
# If the argument is followed by "%", it represents a ratio for the
# number of blocks per segment.
> +
> +# enable set_suinfo ioctl if supported
> +# (needed for min_reclaimable_blocks)
> +use_set_suinfo
This parameter should be commented out at present.
Thanks,
Ryusuke Konishi
> +
> # Use mmap when reading segments if supported.
> use_mmap
>
> --
> 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