|
@@ -521,7 +521,7 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
|
|
|
int nr, unsigned int gfp_mask)
|
|
|
{
|
|
|
struct ldlm_namespace *ns;
|
|
|
- int canceled = 0, unused;
|
|
|
+ int unused;
|
|
|
|
|
|
ns = ldlm_pl2ns(pl);
|
|
|
|
|
@@ -540,14 +540,10 @@ static int ldlm_cli_pool_shrink(struct ldlm_pool *pl,
|
|
|
unused = ns->ns_nr_unused;
|
|
|
spin_unlock(&ns->ns_lock);
|
|
|
|
|
|
- if (nr) {
|
|
|
- canceled = 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;
|
|
|
+ if (nr == 0)
|
|
|
+ return (unused / 100) * sysctl_vfs_cache_pressure;
|
|
|
+ else
|
|
|
+ return ldlm_cancel_lru(ns, nr, LCF_ASYNC, LDLM_CANCEL_SHRINK);
|
|
|
}
|
|
|
|
|
|
struct ldlm_pool_ops ldlm_srv_pool_ops = {
|
|
@@ -601,9 +597,10 @@ int ldlm_pool_recalc(struct ldlm_pool *pl)
|
|
|
return recalc_interval_sec;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
+/*
|
|
|
* 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,
|
|
|
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 shrinker *ldlm_pools_srv_shrinker;
|
|
|
-static struct shrinker *ldlm_pools_cli_shrinker;
|
|
|
static struct completion ldlm_pools_comp;
|
|
|
|
|
|
/*
|
|
|
- * Cancel \a nr locks from all namespaces (if possible). Returns number of
|
|
|
- * cached locks after shrink is finished. All namespaces are asked to
|
|
|
- * cancel approximately equal amount of locks to keep balancing.
|
|
|
+ * count locks from all namespaces (if possible). Returns number of
|
|
|
+ * cached locks.
|
|
|
*/
|
|
|
-static int ldlm_pools_shrink(ldlm_side_t client, int nr,
|
|
|
- unsigned int gfp_mask)
|
|
|
+static unsigned long ldlm_pools_count(ldlm_side_t client, unsigned int gfp_mask)
|
|
|
{
|
|
|
- int total = 0, cached = 0, nr_ns;
|
|
|
+ int total = 0, nr_ns;
|
|
|
struct ldlm_namespace *ns;
|
|
|
struct ldlm_namespace *ns_old = NULL; /* loop detection */
|
|
|
void *cookie;
|
|
|
|
|
|
- if (client == LDLM_NAMESPACE_CLIENT && nr != 0 &&
|
|
|
- !(gfp_mask & __GFP_FS))
|
|
|
- return -1;
|
|
|
+ if (client == LDLM_NAMESPACE_CLIENT && !(gfp_mask & __GFP_FS))
|
|
|
+ return 0;
|
|
|
|
|
|
- CDEBUG(D_DLMTRACE, "Request to shrink %d %s locks from all pools\n",
|
|
|
- nr, client == LDLM_NAMESPACE_CLIENT ? "client" : "server");
|
|
|
+ CDEBUG(D_DLMTRACE, "Request to count %s locks from all pools\n",
|
|
|
+ client == LDLM_NAMESPACE_CLIENT ? "client" : "server");
|
|
|
|
|
|
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.
|
|
|
*/
|
|
|
for (nr_ns = ldlm_namespace_nr_read(client);
|
|
|
- nr_ns > 0; nr_ns--)
|
|
|
- {
|
|
|
+ nr_ns > 0; nr_ns--) {
|
|
|
mutex_lock(ldlm_namespace_lock(client));
|
|
|
if (list_empty(ldlm_namespace_list(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);
|
|
|
}
|
|
|
|
|
|
- if (nr == 0 || total == 0) {
|
|
|
- cl_env_reexit(cookie);
|
|
|
- return total;
|
|
|
- }
|
|
|
+ cl_env_reexit(cookie);
|
|
|
+ return total;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned long ldlm_pools_scan(ldlm_side_t client, int nr, unsigned int gfp_mask)
|
|
|
+{
|
|
|
+ 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(client) namespaces.
|
|
|
+ * Shrink at least ldlm_namespace_nr_read(client) namespaces.
|
|
|
*/
|
|
|
- for (nr_ns = ldlm_namespace_nr_read(client) - nr_ns;
|
|
|
- nr_ns > 0; nr_ns--)
|
|
|
- {
|
|
|
+ for (tmp = nr_ns = ldlm_namespace_nr_read(client);
|
|
|
+ tmp > 0; tmp--) {
|
|
|
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));
|
|
|
if (list_empty(ldlm_namespace_list(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;
|
|
|
}
|
|
|
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));
|
|
|
|
|
|
nr_locks = ldlm_pool_granted(&ns->ns_pool);
|
|
|
- cancel = 1 + nr_locks * nr / total;
|
|
|
- ldlm_pool_shrink(&ns->ns_pool, cancel, gfp_mask);
|
|
|
- cached += ldlm_pool_granted(&ns->ns_pool);
|
|
|
+ /*
|
|
|
+ * We use to shrink propotionally but with new shrinker API,
|
|
|
+ * 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);
|
|
|
}
|
|
|
cl_env_reexit(cookie);
|
|
|
- /* we only decrease the SLV in server pools shrinker, return -1 to
|
|
|
- * kernel to avoid needless loop. LU-1128 */
|
|
|
- return (client == LDLM_NAMESPACE_SERVER) ? -1 : cached;
|
|
|
+ /*
|
|
|
+ * we only decrease the SLV in server pools shrinker, return
|
|
|
+ * SHRINK_STOP to kernel to avoid needless loop. LU-1128
|
|
|
+ */
|
|
|
+ return (client == LDLM_NAMESPACE_SERVER) ? SHRINK_STOP : freed;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned long ldlm_pools_srv_count(struct shrinker *s, struct shrink_control *sc)
|
|
|
+{
|
|
|
+ return ldlm_pools_count(LDLM_NAMESPACE_SERVER, sc->gfp_mask);
|
|
|
}
|
|
|
|
|
|
-static int ldlm_pools_srv_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_SERVER,
|
|
|
- shrink_param(sc, nr_to_scan),
|
|
|
- shrink_param(sc, gfp_mask));
|
|
|
+ return ldlm_pools_scan(LDLM_NAMESPACE_SERVER, sc->nr_to_scan,
|
|
|
+ sc->gfp_mask);
|
|
|
}
|
|
|
|
|
|
-static int ldlm_pools_cli_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
|
|
|
+static unsigned long ldlm_pools_cli_count(struct shrinker *s, struct shrink_control *sc)
|
|
|
{
|
|
|
- return ldlm_pools_shrink(LDLM_NAMESPACE_CLIENT,
|
|
|
- shrink_param(sc, nr_to_scan),
|
|
|
- shrink_param(sc, gfp_mask));
|
|
|
+ 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)
|
|
@@ -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--) {
|
|
|
int skip;
|
|
@@ -1383,18 +1391,26 @@ static void ldlm_pools_thread_stop(void)
|
|
|
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 rc;
|
|
|
|
|
|
rc = ldlm_pools_thread_start();
|
|
|
if (rc == 0) {
|
|
|
- ldlm_pools_srv_shrinker =
|
|
|
- set_shrinker(DEFAULT_SEEKS,
|
|
|
- ldlm_pools_srv_shrink);
|
|
|
- ldlm_pools_cli_shrinker =
|
|
|
- set_shrinker(DEFAULT_SEEKS,
|
|
|
- ldlm_pools_cli_shrink);
|
|
|
+ register_shrinker(&ldlm_pools_srv_shrinker);
|
|
|
+ register_shrinker(&ldlm_pools_cli_shrinker);
|
|
|
}
|
|
|
return rc;
|
|
|
}
|
|
@@ -1402,14 +1418,8 @@ EXPORT_SYMBOL(ldlm_pools_init);
|
|
|
|
|
|
void ldlm_pools_fini(void)
|
|
|
{
|
|
|
- if (ldlm_pools_srv_shrinker != NULL) {
|
|
|
- remove_shrinker(ldlm_pools_srv_shrinker);
|
|
|
- ldlm_pools_srv_shrinker = NULL;
|
|
|
- }
|
|
|
- if (ldlm_pools_cli_shrinker != NULL) {
|
|
|
- remove_shrinker(ldlm_pools_cli_shrinker);
|
|
|
- ldlm_pools_cli_shrinker = NULL;
|
|
|
- }
|
|
|
+ unregister_shrinker(&ldlm_pools_srv_shrinker);
|
|
|
+ unregister_shrinker(&ldlm_pools_cli_shrinker);
|
|
|
ldlm_pools_thread_stop();
|
|
|
}
|
|
|
EXPORT_SYMBOL(ldlm_pools_fini);
|