staging/lustre/ldlm: convert to shrinkers to count/scan API

convert ldlm shrinker to new count/scan API.

Signed-off-by: Peng Tao <tao.peng@emc.com>
Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Peng Tao 2013-08-28 10:18:19 +10:00 коммит произвёл Al Viro
Родитель 488964666f
Коммит cbc3769ecd
1 изменённых файлов: 79 добавлений и 69 удалений

Просмотреть файл

@ -521,7 +521,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
int nr, unsigned int gfp_mask) int nr, unsigned int gfp_mask)
{ {
struct ldlm_namespace *ns; struct ldlm_namespace *ns;
int canceled = 0, unused; int unused;
ns = ldlm_pl2ns(pl); ns = ldlm_pl2ns(pl);
@ -540,14 +540,10 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
unused = ns->ns_nr_unused; unused = ns->ns_nr_unused;
spin_unlock(&ns->ns_lock); spin_unlock(&ns->ns_lock);
if (nr) { if (nr == 0)
canceled = ldlm_cancel_lru(ns, nr, LCF_ASYNC, return (unused / 100) * sysctl_vfs_cache_pressure;
LDLM_CANCEL_SHRINK); else
} return ldlm_cancel_lru(ns, nr, LCF_ASYNC, LDLM_CANCEL_SHRINK);
/*
* Return the number of potentially reclaimable locks.
*/
return ((unused - canceled) / 100) * sysctl_vfs_cache_pressure;
} }
struct ldlm_pool_ops ldlm_srv_pool_ops = { struct ldlm_pool_ops ldlm_srv_pool_ops = {
@ -601,9 +597,10 @@ int ldlm_pool_recalc(struct ldlm_pool *pl)
return recalc_interval_sec; return recalc_interval_sec;
} }
/** /*
* Pool shrink wrapper. Will call either client or server pool recalc callback * Pool shrink wrapper. Will call either client or server pool recalc callback
* depending what pool \a pl is used. * depending what pool pl is used. When nr == 0, just return the number of
* freeable locks. Otherwise, return the number of canceled locks.
*/ */
int ldlm_pool_shrink(struct ldlm_pool *pl, int nr, int ldlm_pool_shrink(struct ldlm_pool *pl, int nr,
unsigned int gfp_mask) unsigned int gfp_mask)
@ -1017,29 +1014,24 @@ static int ldlm_pool_granted(struct ldlm_pool *pl)
} }
static struct ptlrpc_thread *ldlm_pools_thread; static struct ptlrpc_thread *ldlm_pools_thread;
static struct shrinker *ldlm_pools_srv_shrinker;
static struct shrinker *ldlm_pools_cli_shrinker;
static struct completion ldlm_pools_comp; static struct completion ldlm_pools_comp;
/* /*
* Cancel \a nr locks from all namespaces (if possible). Returns number of * count locks from all namespaces (if possible). Returns number of
* cached locks after shrink is finished. All namespaces are asked to * cached locks.
* cancel approximately equal amount of locks to keep balancing.
*/ */
static int ldlm_pools_shrink(ldlm_side_t client, int nr, static unsigned long ldlm_pools_count(ldlm_side_t client, unsigned int gfp_mask)
unsigned int gfp_mask)
{ {
int total = 0, cached = 0, nr_ns; int total = 0, nr_ns;
struct ldlm_namespace *ns; struct ldlm_namespace *ns;
struct ldlm_namespace *ns_old = NULL; /* loop detection */ struct ldlm_namespace *ns_old = NULL; /* loop detection */
void *cookie; void *cookie;
if (client == LDLM_NAMESPACE_CLIENT && nr != 0 && if (client == LDLM_NAMESPACE_CLIENT && !(gfp_mask & __GFP_FS))
!(gfp_mask & __GFP_FS)) return 0;
return -1;
CDEBUG(D_DLMTRACE, "Request to shrink %d %s locks from all pools\n", CDEBUG(D_DLMTRACE, "Request to count %s locks from all pools\n",
nr, client == LDLM_NAMESPACE_CLIENT ? "client" : "server"); client == LDLM_NAMESPACE_CLIENT ? "client" : "server");
cookie = cl_env_reenter(); cookie = cl_env_reenter();
@ -1047,8 +1039,7 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr,
* Find out how many resources we may release. * Find out how many resources we may release.
*/ */
for (nr_ns = ldlm_namespace_nr_read(client); for (nr_ns = ldlm_namespace_nr_read(client);
nr_ns > 0; nr_ns--) nr_ns > 0; nr_ns--) {
{
mutex_lock(ldlm_namespace_lock(client)); mutex_lock(ldlm_namespace_lock(client));
if (list_empty(ldlm_namespace_list(client))) { if (list_empty(ldlm_namespace_list(client))) {
mutex_unlock(ldlm_namespace_lock(client)); mutex_unlock(ldlm_namespace_lock(client));
@ -1078,17 +1069,27 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr,
ldlm_namespace_put(ns); ldlm_namespace_put(ns);
} }
if (nr == 0 || total == 0) {
cl_env_reexit(cookie); cl_env_reexit(cookie);
return total; return total;
} }
/* static unsigned long ldlm_pools_scan(ldlm_side_t client, int nr, unsigned int gfp_mask)
* Shrink at least ldlm_namespace_nr(client) namespaces.
*/
for (nr_ns = ldlm_namespace_nr_read(client) - nr_ns;
nr_ns > 0; nr_ns--)
{ {
unsigned long freed = 0;
int tmp, nr_ns;
struct ldlm_namespace *ns;
void *cookie;
if (client == LDLM_NAMESPACE_CLIENT && !(gfp_mask & __GFP_FS))
return -1;
cookie = cl_env_reenter();
/*
* Shrink at least ldlm_namespace_nr_read(client) namespaces.
*/
for (tmp = nr_ns = ldlm_namespace_nr_read(client);
tmp > 0; tmp--) {
int cancel, nr_locks; int cancel, nr_locks;
/* /*
@ -1097,12 +1098,6 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr,
mutex_lock(ldlm_namespace_lock(client)); mutex_lock(ldlm_namespace_lock(client));
if (list_empty(ldlm_namespace_list(client))) { if (list_empty(ldlm_namespace_list(client))) {
mutex_unlock(ldlm_namespace_lock(client)); mutex_unlock(ldlm_namespace_lock(client));
/*
* If list is empty, we can't return any @cached > 0,
* that probably would cause needless shrinker
* call.
*/
cached = 0;
break; break;
} }
ns = ldlm_namespace_first_locked(client); ns = ldlm_namespace_first_locked(client);
@ -1111,29 +1106,42 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr,
mutex_unlock(ldlm_namespace_lock(client)); mutex_unlock(ldlm_namespace_lock(client));
nr_locks = ldlm_pool_granted(&ns->ns_pool); nr_locks = ldlm_pool_granted(&ns->ns_pool);
cancel = 1 + nr_locks * nr / total; /*
ldlm_pool_shrink(&ns->ns_pool, cancel, gfp_mask); * We use to shrink propotionally but with new shrinker API,
cached += ldlm_pool_granted(&ns->ns_pool); * we lost the total number of freeable locks.
*/
cancel = 1 + min_t(int, nr_locks, nr / nr_ns);
freed += ldlm_pool_shrink(&ns->ns_pool, cancel, gfp_mask);
ldlm_namespace_put(ns); ldlm_namespace_put(ns);
} }
cl_env_reexit(cookie); cl_env_reexit(cookie);
/* we only decrease the SLV in server pools shrinker, return -1 to /*
* kernel to avoid needless loop. LU-1128 */ * we only decrease the SLV in server pools shrinker, return
return (client == LDLM_NAMESPACE_SERVER) ? -1 : cached; * SHRINK_STOP to kernel to avoid needless loop. LU-1128
*/
return (client == LDLM_NAMESPACE_SERVER) ? SHRINK_STOP : freed;
} }
static int ldlm_pools_srv_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask)) static unsigned long ldlm_pools_srv_count(struct shrinker *s, struct shrink_control *sc)
{ {
return ldlm_pools_shrink(LDLM_NAMESPACE_SERVER, return ldlm_pools_count(LDLM_NAMESPACE_SERVER, sc->gfp_mask);
shrink_param(sc, nr_to_scan),
shrink_param(sc, gfp_mask));
} }
static int ldlm_pools_cli_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask)) static unsigned long ldlm_pools_srv_scan(struct shrinker *s, struct shrink_control *sc)
{ {
return ldlm_pools_shrink(LDLM_NAMESPACE_CLIENT, return ldlm_pools_scan(LDLM_NAMESPACE_SERVER, sc->nr_to_scan,
shrink_param(sc, nr_to_scan), sc->gfp_mask);
shrink_param(sc, gfp_mask)); }
static unsigned long ldlm_pools_cli_count(struct shrinker *s, struct shrink_control *sc)
{
return ldlm_pools_count(LDLM_NAMESPACE_CLIENT, sc->gfp_mask);
}
static unsigned long ldlm_pools_cli_scan(struct shrinker *s, struct shrink_control *sc)
{
return ldlm_pools_scan(LDLM_NAMESPACE_CLIENT, sc->nr_to_scan,
sc->gfp_mask);
} }
int ldlm_pools_recalc(ldlm_side_t client) int ldlm_pools_recalc(ldlm_side_t client)
@ -1216,7 +1224,7 @@ int ldlm_pools_recalc(ldlm_side_t client)
} }
/* /*
* Recalc at least ldlm_namespace_nr(client) namespaces. * Recalc at least ldlm_namespace_nr_read(client) namespaces.
*/ */
for (nr = ldlm_namespace_nr_read(client); nr > 0; nr--) { for (nr = ldlm_namespace_nr_read(client); nr > 0; nr--) {
int skip; int skip;
@ -1383,18 +1391,26 @@ static void ldlm_pools_thread_stop(void)
ldlm_pools_thread = NULL; ldlm_pools_thread = NULL;
} }
static struct shrinker ldlm_pools_srv_shrinker = {
.count_objects = ldlm_pools_srv_count,
.scan_objects = ldlm_pools_srv_scan,
.seeks = DEFAULT_SEEKS,
};
static struct shrinker ldlm_pools_cli_shrinker = {
.count_objects = ldlm_pools_cli_count,
.scan_objects = ldlm_pools_cli_scan,
.seeks = DEFAULT_SEEKS,
};
int ldlm_pools_init(void) int ldlm_pools_init(void)
{ {
int rc; int rc;
rc = ldlm_pools_thread_start(); rc = ldlm_pools_thread_start();
if (rc == 0) { if (rc == 0) {
ldlm_pools_srv_shrinker = register_shrinker(&ldlm_pools_srv_shrinker);
set_shrinker(DEFAULT_SEEKS, register_shrinker(&ldlm_pools_cli_shrinker);
ldlm_pools_srv_shrink);
ldlm_pools_cli_shrinker =
set_shrinker(DEFAULT_SEEKS,
ldlm_pools_cli_shrink);
} }
return rc; return rc;
} }
@ -1402,14 +1418,8 @@ EXPORT_SYMBOL(ldlm_pools_init);
void ldlm_pools_fini(void) void ldlm_pools_fini(void)
{ {
if (ldlm_pools_srv_shrinker != NULL) { unregister_shrinker(&ldlm_pools_srv_shrinker);
remove_shrinker(ldlm_pools_srv_shrinker); unregister_shrinker(&ldlm_pools_cli_shrinker);
ldlm_pools_srv_shrinker = NULL;
}
if (ldlm_pools_cli_shrinker != NULL) {
remove_shrinker(ldlm_pools_cli_shrinker);
ldlm_pools_cli_shrinker = NULL;
}
ldlm_pools_thread_stop(); ldlm_pools_thread_stop();
} }
EXPORT_SYMBOL(ldlm_pools_fini); EXPORT_SYMBOL(ldlm_pools_fini);