From: Andreas Rohner <andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
To: linux-nilfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH v2 5/5] nilfs-utils: add support for greedy/cost-benefit policies
Date: Sun, 3 May 2015 12:07:07 +0200 [thread overview]
Message-ID: <1430647627-18902-5-git-send-email-andreas.rohner@gmx.net> (raw)
In-Reply-To: <1430647522-14304-1-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
This patch implements the cost-benefit and greedy GC policies. These are
well known policies for log-structured file systems [1].
* Greedy:
Select the segments with the most reclaimable space.
* Cost-Benefit [1]:
Perform a cost-benefit analysis, whereby the reclaimable space
gained is weighed against the cost of collecting the segment.
Since especially cost-benefit needs more information than is available
in nilfs_suinfo, a few extra parameters are added to the policy callback
function prototype. The flag p_comparison is added to indicate how the
importance values should be interpreted. For example for the timestamp
policy smaller values mean older timestamps, which is better. For greedy
and cost-benefit on the other hand, higher values are better.
nilfs_cleanerd_select_segments() was updated accordingly.
The threshold in nilfs_cleanerd_select_segments() can no longer be set
to sustat->ss_nongc_ctime on default, because the greedy/cost-benefit
policies do not return a timestamp, so their importance values cannot be
compared to each other. Instead segments that are younger than
sustat->ss_nongc_ctime are always excluded.
[1] Mendel Rosenblum and John K. Ousterhout. The design and implementa-
tion of a log-structured file system. ACM Trans. Comput. Syst.,
10(1):26–52, February 1992.
Signed-off-by: Andreas Rohner <andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
---
sbin/cleanerd/cldconfig.c | 79 +++++++++++++++++++++++++++++++++++++++++++++--
sbin/cleanerd/cldconfig.h | 22 +++++++++----
sbin/cleanerd/cleanerd.c | 43 ++++++++++++++++++++------
3 files changed, 126 insertions(+), 18 deletions(-)
diff --git a/sbin/cleanerd/cldconfig.c b/sbin/cleanerd/cldconfig.c
index c8b197b..68090e9 100644
--- a/sbin/cleanerd/cldconfig.c
+++ b/sbin/cleanerd/cldconfig.c
@@ -380,7 +380,9 @@ nilfs_cldconfig_handle_clean_check_interval(struct nilfs_cldconfig *config,
}
static unsigned long long
-nilfs_cldconfig_selection_policy_timestamp(const struct nilfs_suinfo *si)
+nilfs_cldconfig_selection_policy_timestamp(const struct nilfs_suinfo *si,
+ const struct nilfs_sustat *sustat,
+ __u64 prottime)
{
return si->sui_lastmod;
}
@@ -392,13 +394,84 @@ nilfs_cldconfig_handle_selection_policy_timestamp(struct nilfs_cldconfig *config
config->cf_selection_policy.p_importance =
NILFS_CLDCONFIG_SELECTION_POLICY_IMPORTANCE;
config->cf_selection_policy.p_threshold =
- NILFS_CLDCONFIG_SELECTION_POLICY_THRESHOLD;
+ NILFS_CLDCONFIG_SELECTION_POLICY_NO_THRESHOLD;
+ config->cf_selection_policy.p_comparison =
+ NILFS_CLDCONFIG_SELECTION_POLICY_SMALLER_IS_BETTER;
+ return 0;
+}
+
+static unsigned long long
+nilfs_cldconfig_selection_policy_greedy(const struct nilfs_suinfo *si,
+ const struct nilfs_sustat *sustat,
+ __u64 prottime)
+{
+ if (si->sui_nblocks < si->sui_nlive_blks ||
+ si->sui_nlive_lastmod >= prottime)
+ return 0;
+
+ return si->sui_nblocks - si->sui_nlive_blks;
+}
+
+static int
+nilfs_cldconfig_handle_selection_policy_greedy(struct nilfs_cldconfig *config,
+ char **tokens, size_t ntoks)
+{
+ config->cf_selection_policy.p_importance =
+ nilfs_cldconfig_selection_policy_greedy;
+ config->cf_selection_policy.p_threshold =
+ NILFS_CLDCONFIG_SELECTION_POLICY_NO_THRESHOLD;
+ config->cf_selection_policy.p_comparison =
+ NILFS_CLDCONFIG_SELECTION_POLICY_BIGGER_IS_BETTER;
+ return 0;
+}
+
+static unsigned long long
+nilfs_cldconfig_selection_policy_cost_benefit(const struct nilfs_suinfo *si,
+ const struct nilfs_sustat *sustat,
+ __u64 prottime)
+{
+ __u32 free_blocks, cleaning_cost;
+ unsigned long long age;
+
+ if (si->sui_nblocks < si->sui_nlive_blks ||
+ sustat->ss_nongc_ctime < si->sui_lastmod ||
+ si->sui_nlive_lastmod >= prottime)
+ return 0;
+
+ free_blocks = si->sui_nblocks - si->sui_nlive_blks;
+ /* read the whole segment + write the live blocks */
+ cleaning_cost = 2 * si->sui_nlive_blks;
+ /*
+ * multiply by 1000 to convert age to milliseconds
+ * (higher precision for division)
+ */
+ age = (sustat->ss_nongc_ctime - si->sui_lastmod) * 1000;
+
+ if (cleaning_cost == 0)
+ cleaning_cost = 1;
+
+ return (age * free_blocks) / cleaning_cost;
+}
+
+static int
+nilfs_cldconfig_handle_selection_policy_cost_benefit(
+ struct nilfs_cldconfig *config,
+ char **tokens, size_t ntoks)
+{
+ config->cf_selection_policy.p_importance =
+ nilfs_cldconfig_selection_policy_cost_benefit;
+ config->cf_selection_policy.p_threshold =
+ NILFS_CLDCONFIG_SELECTION_POLICY_NO_THRESHOLD;
+ config->cf_selection_policy.p_comparison =
+ NILFS_CLDCONFIG_SELECTION_POLICY_BIGGER_IS_BETTER;
return 0;
}
static const struct nilfs_cldconfig_polhandle
nilfs_cldconfig_polhandle_table[] = {
{"timestamp", nilfs_cldconfig_handle_selection_policy_timestamp},
+ {"greedy", nilfs_cldconfig_handle_selection_policy_greedy},
+ {"cost-benefit", nilfs_cldconfig_handle_selection_policy_cost_benefit},
};
#define NILFS_CLDCONFIG_NPOLHANDLES \
@@ -690,6 +763,8 @@ static void nilfs_cldconfig_set_default(struct nilfs_cldconfig *config,
NILFS_CLDCONFIG_SELECTION_POLICY_IMPORTANCE;
config->cf_selection_policy.p_threshold =
NILFS_CLDCONFIG_SELECTION_POLICY_THRESHOLD;
+ config->cf_selection_policy.p_comparison =
+ NILFS_CLDCONFIG_SELECTION_POLICY_COMPARISON;
config->cf_protection_period.tv_sec = NILFS_CLDCONFIG_PROTECTION_PERIOD;
config->cf_protection_period.tv_usec = 0;
diff --git a/sbin/cleanerd/cldconfig.h b/sbin/cleanerd/cldconfig.h
index 2a0af5f..3c9f5e6 100644
--- a/sbin/cleanerd/cldconfig.h
+++ b/sbin/cleanerd/cldconfig.h
@@ -30,16 +30,22 @@
#include <sys/time.h>
#include <syslog.h>
+struct nilfs;
+struct nilfs_sustat;
struct nilfs_suinfo;
/**
* struct nilfs_selection_policy -
- * @p_importance:
- * @p_threshold:
+ * @p_importance: function to calculate the importance for the policy
+ * @p_threshold: segments with lower/higher importance are ignored
+ * @p_comparison: flag that indicates how to sort the importance
*/
struct nilfs_selection_policy {
- unsigned long long (*p_importance)(const struct nilfs_suinfo *);
+ unsigned long long (*p_importance)(const struct nilfs_suinfo *,
+ const struct nilfs_sustat *,
+ __u64);
unsigned long long p_threshold;
+ int p_comparison;
};
/**
@@ -111,9 +117,15 @@ struct nilfs_cldconfig {
unsigned long cf_mc_min_reclaimable_blocks;
};
+#define NILFS_CLDCONFIG_SELECTION_POLICY_SMALLER_IS_BETTER 0
+#define NILFS_CLDCONFIG_SELECTION_POLICY_BIGGER_IS_BETTER 1
+#define NILFS_CLDCONFIG_SELECTION_POLICY_NO_THRESHOLD 0
#define NILFS_CLDCONFIG_SELECTION_POLICY_IMPORTANCE \
nilfs_cldconfig_selection_policy_timestamp
-#define NILFS_CLDCONFIG_SELECTION_POLICY_THRESHOLD 0
+#define NILFS_CLDCONFIG_SELECTION_POLICY_THRESHOLD \
+ NILFS_CLDCONFIG_SELECTION_POLICY_NO_THRESHOLD
+#define NILFS_CLDCONFIG_SELECTION_POLICY_COMPARISON \
+ NILFS_CLDCONFIG_SELECTION_POLICY_SMALLER_IS_BETTER
#define NILFS_CLDCONFIG_PROTECTION_PERIOD 3600
#define NILFS_CLDCONFIG_MIN_CLEAN_SEGMENTS 10
#define NILFS_CLDCONFIG_MIN_CLEAN_SEGMENTS_UNIT NILFS_SIZE_UNIT_PERCENT
@@ -135,8 +147,6 @@ struct nilfs_cldconfig {
#define NILFS_CLDCONFIG_NSEGMENTS_PER_CLEAN_MAX 32
-struct nilfs;
-
int nilfs_cldconfig_read(struct nilfs_cldconfig *config, const char *path,
struct nilfs *nilfs);
diff --git a/sbin/cleanerd/cleanerd.c b/sbin/cleanerd/cleanerd.c
index d37bd5c..e0741f1 100644
--- a/sbin/cleanerd/cleanerd.c
+++ b/sbin/cleanerd/cleanerd.c
@@ -417,7 +417,7 @@ static void nilfs_cleanerd_destroy(struct nilfs_cleanerd *cleanerd)
free(cleanerd);
}
-static int nilfs_comp_segimp(const void *elem1, const void *elem2)
+static int nilfs_comp_segimp_asc(const void *elem1, const void *elem2)
{
const struct nilfs_segimp *segimp1 = elem1, *segimp2 = elem2;
@@ -429,6 +429,18 @@ static int nilfs_comp_segimp(const void *elem1, const void *elem2)
return (segimp1->si_segnum < segimp2->si_segnum) ? -1 : 1;
}
+static int nilfs_comp_segimp_desc(const void *elem1, const void *elem2)
+{
+ const struct nilfs_segimp *segimp1 = elem1, *segimp2 = elem2;
+
+ if (segimp1->si_importance > segimp2->si_importance)
+ return -1;
+ else if (segimp1->si_importance < segimp2->si_importance)
+ return 1;
+
+ return (segimp1->si_segnum < segimp2->si_segnum) ? -1 : 1;
+}
+
static int nilfs_cleanerd_automatic_suspend(struct nilfs_cleanerd *cleanerd)
{
return cleanerd->config.cf_min_clean_segments > 0;
@@ -580,7 +592,7 @@ nilfs_cleanerd_select_segments(struct nilfs_cleanerd *cleanerd,
size_t count, nsegs;
ssize_t nssegs, n;
unsigned long long imp, thr;
- int i;
+ int i, sib;
nsegs = nilfs_cleanerd_ncleansegs(cleanerd);
nilfs = cleanerd->nilfs;
@@ -600,11 +612,17 @@ nilfs_cleanerd_select_segments(struct nilfs_cleanerd *cleanerd,
prottime = tv2.tv_sec;
oldest = tv.tv_sec;
- /* The segments that have larger importance than thr are not
+ /*
+ * sufile extension fields may not be initialized by
+ * nilfs_get_suinfo()
+ */
+ memset(si, 0, sizeof(si));
+
+ /* The segments that have larger/smaller importance than thr are not
* selected. */
- thr = (config->cf_selection_policy.p_threshold != 0) ?
- config->cf_selection_policy.p_threshold :
- sustat->ss_nongc_ctime;
+ thr = config->cf_selection_policy.p_threshold;
+ sib = config->cf_selection_policy.p_comparison ==
+ NILFS_CLDCONFIG_SELECTION_POLICY_SMALLER_IS_BETTER;
for (segnum = 0; segnum < sustat->ss_nsegs; segnum += n) {
count = min_t(__u64, sustat->ss_nsegs - segnum,
@@ -615,11 +633,13 @@ nilfs_cleanerd_select_segments(struct nilfs_cleanerd *cleanerd,
goto out;
}
for (i = 0; i < n; i++) {
- if (!nilfs_suinfo_reclaimable(&si[i]))
+ if (!nilfs_suinfo_reclaimable(&si[i]) ||
+ si[i].sui_lastmod >= sustat->ss_nongc_ctime)
continue;
- imp = config->cf_selection_policy.p_importance(&si[i]);
- if (imp < thr) {
+ imp = config->cf_selection_policy.p_importance(&si[i],
+ sustat, prottime);
+ if (!thr || (sib && imp < thr) || (!sib && imp > thr)) {
if (si[i].sui_lastmod < oldest)
oldest = si[i].sui_lastmod;
if (si[i].sui_lastmod < prottime) {
@@ -642,7 +662,10 @@ nilfs_cleanerd_select_segments(struct nilfs_cleanerd *cleanerd,
break;
}
}
- nilfs_vector_sort(smv, nilfs_comp_segimp);
+ if (sib)
+ nilfs_vector_sort(smv, nilfs_comp_segimp_asc);
+ else
+ nilfs_vector_sort(smv, nilfs_comp_segimp_desc);
nssegs = (nilfs_vector_get_size(smv) < nsegs) ?
nilfs_vector_get_size(smv) : nsegs;
--
2.3.7
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2015-05-03 10:07 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-03 10:05 [PATCH v2 0/9] nilfs2: implementation of cost-benefit GC policy Andreas Rohner
[not found] ` <1430647522-14304-1-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-03 10:05 ` [PATCH v2 1/9] nilfs2: copy file system feature flags to the nilfs object Andreas Rohner
[not found] ` <1430647522-14304-2-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 1:54 ` Ryusuke Konishi
[not found] ` <20150509.105445.1816655707671265145.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 18:41 ` Andreas Rohner
2015-05-03 10:05 ` [PATCH v2 2/9] nilfs2: extend SUFILE on-disk format to enable tracking of live blocks Andreas Rohner
[not found] ` <1430647522-14304-3-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 2:24 ` Ryusuke Konishi
[not found] ` <20150509.112403.380867861504859109.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 18:47 ` Andreas Rohner
2015-05-03 10:05 ` [PATCH v2 3/9] nilfs2: introduce new feature flag for tracking " Andreas Rohner
[not found] ` <1430647522-14304-4-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 2:28 ` Ryusuke Konishi
[not found] ` <20150509.112814.2026089040966346261.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 18:53 ` Andreas Rohner
2015-05-03 10:05 ` [PATCH v2 4/9] nilfs2: add kmem_cache for SUFILE cache nodes Andreas Rohner
[not found] ` <1430647522-14304-5-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 2:41 ` Ryusuke Konishi
[not found] ` <20150509.114149.1643183669812667339.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 19:10 ` Andreas Rohner
[not found] ` <554E5B9D.7070807-hi6Y0CQ0nG0@public.gmane.org>
2015-05-10 0:05 ` Ryusuke Konishi
2015-05-03 10:05 ` [PATCH v2 5/9] nilfs2: add SUFILE cache for changes to su_nlive_blks field Andreas Rohner
[not found] ` <1430647522-14304-6-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 4:09 ` Ryusuke Konishi
[not found] ` <20150509.130900.223492430584220355.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 19:39 ` Andreas Rohner
[not found] ` <554E626A.2030503-hi6Y0CQ0nG0@public.gmane.org>
2015-05-10 2:09 ` Ryusuke Konishi
2015-05-03 10:05 ` [PATCH v2 6/9] nilfs2: add tracking of block deletions and updates Andreas Rohner
[not found] ` <1430647522-14304-7-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 7:05 ` Ryusuke Konishi
[not found] ` <20150509.160512.1087140271092828536.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 15:58 ` Ryusuke Konishi
2015-05-09 20:02 ` Andreas Rohner
[not found] ` <554E67C0.1050309-hi6Y0CQ0nG0@public.gmane.org>
2015-05-10 3:17 ` Ryusuke Konishi
2015-05-03 10:05 ` [PATCH v2 7/9] nilfs2: ensure that all dirty blocks are written out Andreas Rohner
[not found] ` <1430647522-14304-8-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-09 12:17 ` Ryusuke Konishi
[not found] ` <20150509.211741.1463241033923032068.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-09 20:18 ` Andreas Rohner
[not found] ` <554E6B7E.8070000-hi6Y0CQ0nG0@public.gmane.org>
2015-05-10 3:31 ` Ryusuke Konishi
2015-05-10 11:04 ` Andreas Rohner
[not found] ` <554F3B32.5050004-hi6Y0CQ0nG0@public.gmane.org>
2015-06-01 4:13 ` Ryusuke Konishi
[not found] ` <20150601.131320.1075202804382267027.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-06-01 14:33 ` Andreas Rohner
2015-05-03 10:05 ` [PATCH v2 8/9] nilfs2: correct live block tracking for GC protection period Andreas Rohner
[not found] ` <1430647522-14304-9-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-10 18:15 ` Ryusuke Konishi
[not found] ` <20150511.031512.1036934606749624197.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-10 18:23 ` Ryusuke Konishi
[not found] ` <20150511.032323.1250231827423193240.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-11 2:07 ` Ryusuke Konishi
[not found] ` <20150511.110726.725667075147435663.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-11 12:32 ` Andreas Rohner
2015-05-11 13:00 ` Andreas Rohner
[not found] ` <5550A7FC.4050709-hi6Y0CQ0nG0@public.gmane.org>
2015-05-12 14:31 ` Ryusuke Konishi
[not found] ` <20150512.233126.2206330706583570566.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-12 15:37 ` Andreas Rohner
2015-05-03 10:05 ` [PATCH v2 9/9] nilfs2: prevent starvation of segments protected by snapshots Andreas Rohner
[not found] ` <1430647522-14304-10-git-send-email-andreas.rohner-hi6Y0CQ0nG0@public.gmane.org>
2015-05-20 14:43 ` Ryusuke Konishi
[not found] ` <20150520.234335.542615158366069430.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-20 15:49 ` Ryusuke Konishi
2015-05-22 18:10 ` Andreas Rohner
[not found] ` <555F70FD.6090500-hi6Y0CQ0nG0@public.gmane.org>
2015-05-31 16:45 ` Ryusuke Konishi
[not found] ` <20150601.014550.269184778137708369.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-05-31 18:13 ` Andreas Rohner
[not found] ` <556B4F58.9080801-hi6Y0CQ0nG0@public.gmane.org>
2015-06-01 0:44 ` Ryusuke Konishi
[not found] ` <20150601.094441.24658496988941562.konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2015-06-01 14:45 ` Andreas Rohner
2015-05-03 10:07 ` [PATCH v2 1/5] nilfs-utils: extend SUFILE on-disk format to enable track live blocks Andreas Rohner
2015-05-03 10:07 ` [PATCH v2 2/5] nilfs-utils: add additional flags for nilfs_vdesc Andreas Rohner
2015-05-03 10:07 ` [PATCH v2 3/5] nilfs-utils: add support for tracking live blocks Andreas Rohner
2015-05-03 10:07 ` [PATCH v2 4/5] nilfs-utils: implement the tracking of live blocks for set_suinfo Andreas Rohner
2015-05-03 10:07 ` Andreas Rohner [this message]
2015-05-05 3:09 ` [PATCH v2 0/9] nilfs2: implementation of cost-benefit GC policy Ryusuke Konishi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1430647627-18902-5-git-send-email-andreas.rohner@gmx.net \
--to=andreas.rohner-hi6y0cq0ng0@public.gmane.org \
--cc=linux-nilfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).