Use count/scan objects shrinking interface

Move to the more recent interfaces for counting and scanning cached
objects to shrink.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2022-08-02 15:29:48 -07:00
parent fd1c4777c2
commit a49584739a
6 changed files with 93 additions and 14 deletions
+4
View File
@@ -46,6 +46,10 @@ scoutfs-y += \
volopt.o \
xattr.o
ifdef KC_BUILD_KERNELCOMPAT
scoutfs-y += kernelcompat.o
endif
#
# The raw types aren't available in userspace headers. Make sure all
# the types we use in the headers are the exported __ versions.
+10
View File
@@ -73,3 +73,13 @@ endif
ifneq (,$(shell grep 'bi_status' include/linux/blk_types.h))
ccflags-y += -DKC_BIO_BI_STATUS
endif
#
# v3.11-8765-ga0b02131c5fc
#
# Remove the old ->shrink() API, ->{scan,count}_objects is preferred.
#
ifneq (,$(shell grep '(*shrink)' include/linux/shrinker.h))
ccflags-y += -DKC_SHRINKER_SHRINK
KC_BUILD_KERNELCOMPAT=1
endif
+22 -14
View File
@@ -58,7 +58,7 @@ struct block_info {
atomic64_t access_counter;
struct rhashtable ht;
wait_queue_head_t waitq;
struct shrinker shrinker;
KC_DEFINE_SHRINKER(shrinker);
struct work_struct free_work;
struct llist_head free_llist;
};
@@ -1040,6 +1040,17 @@ u64 scoutfs_block_writer_dirty_bytes(struct super_block *sb,
return wri->nr_dirty_blocks * SCOUTFS_BLOCK_LG_SIZE;
}
static unsigned long block_count_objects(struct shrinker *shrink, struct shrink_control *sc)
{
struct block_info *binf = container_of(shrink, struct block_info, shrinker);
struct super_block *sb = binf->sb;
scoutfs_inc_counter(sb, block_cache_scan_objects);
return min_t(u64, (u64)atomic_read(&binf->total_inserted) * SCOUTFS_BLOCK_LG_PAGES_PER,
ULONG_MAX / 2); /* magic numbers as we approach ~0UL :/ */
}
/*
* Remove a number of cached blocks that haven't been used recently.
*
@@ -1060,23 +1071,19 @@ u64 scoutfs_block_writer_dirty_bytes(struct super_block *sb,
* atomically remove blocks when the only references are ours and the
* hash table.
*/
static int block_shrink(struct shrinker *shrink, struct shrink_control *sc)
static unsigned long block_scan_objects(struct shrinker *shrink, struct shrink_control *sc)
{
struct block_info *binf = container_of(shrink, struct block_info,
shrinker);
struct block_info *binf = container_of(shrink, struct block_info, shrinker);
struct super_block *sb = binf->sb;
struct rhashtable_iter iter;
struct block_private *bp;
unsigned long freed = 0;
unsigned long nr;
u64 recently;
nr = sc->nr_to_scan;
if (nr == 0)
goto out;
scoutfs_inc_counter(sb, block_cache_scan_objects);
scoutfs_inc_counter(sb, block_cache_shrink);
nr = DIV_ROUND_UP(nr, SCOUTFS_BLOCK_LG_PAGES_PER);
nr = DIV_ROUND_UP(sc->nr_to_scan, SCOUTFS_BLOCK_LG_PAGES_PER);
restart:
recently = accessed_recently(binf);
@@ -1119,6 +1126,7 @@ restart:
if (block_remove_solo(sb, bp)) {
scoutfs_inc_counter(sb, block_cache_shrink_remove);
TRACE_BLOCK(shrink, bp);
freed++;
nr--;
}
block_put(sb, bp);
@@ -1127,9 +1135,8 @@ restart:
rhashtable_walk_stop(&iter);
rhashtable_walk_exit(&iter);
out:
return min_t(u64, (u64)atomic_read(&binf->total_inserted) * SCOUTFS_BLOCK_LG_PAGES_PER,
INT_MAX);
return freed;
}
struct sm_block_completion {
@@ -1255,7 +1262,8 @@ int scoutfs_block_setup(struct super_block *sb)
atomic_set(&binf->total_inserted, 0);
atomic64_set(&binf->access_counter, 0);
init_waitqueue_head(&binf->waitq);
binf->shrinker.shrink = block_shrink;
KC_INIT_SHRINKER_FUNCS(struct block_info, shrinker,
&binf->shrinker, block_count_objects, block_scan_objects);
binf->shrinker.seeks = DEFAULT_SEEKS;
register_shrinker(&binf->shrinker);
INIT_WORK(&binf->free_work, block_free_work);
+2
View File
@@ -30,6 +30,8 @@
EXPAND_COUNTER(block_cache_free) \
EXPAND_COUNTER(block_cache_free_work) \
EXPAND_COUNTER(block_cache_remove_stale) \
EXPAND_COUNTER(block_cache_count_objects) \
EXPAND_COUNTER(block_cache_scan_objects) \
EXPAND_COUNTER(block_cache_shrink) \
EXPAND_COUNTER(block_cache_shrink_next) \
EXPAND_COUNTER(block_cache_shrink_recent) \
+23
View File
@@ -0,0 +1,23 @@
#include "kernelcompat.h"
#ifdef KC_SHRINKER_SHRINK
#include <linux/shrinker.h>
/*
* If a target doesn't have that .{count,scan}_objects() interface then
* we have a .shrink() helper that performs the shrink work in terms of
* count/scan.
*/
int kc_shrink_wrapper(struct shrinker *shrink, struct shrink_control *sc)
{
struct kc_shrinker_funcs *funcs = KC_SHRINKER_FUNCS(shrink);
unsigned long nr;
if (sc->nr_to_scan != 0)
funcs->scan_objects(shrink, sc);
nr = funcs->count_objects(shrink, sc);
return min_t(unsigned long, nr, INT_MAX);
}
#endif
+32
View File
@@ -91,4 +91,36 @@ do { \
#define kc_bio_get_errno(bio) ({ (int)((void)(bio), _error_arg); })
#endif
#ifndef KC_SHRINKER_SHRINK
#define KC_DEFINE_SHRINKER(name) struct shrinker name
#define KC_INIT_SHRINKER_FUNCS(type, name, shrink, count, scan) do { \
__typeof__(shrink) _shrink = (shrink); \
_shrink->count_objects = count; \
_shrink->scan_objects = scan; \
} while (0)
#else
#include <linux/shrinker.h>
struct kc_shrinker_funcs {
unsigned long (*count_objects)(struct shrinker *, struct shrink_control *sc);
unsigned long (*scan_objects)(struct shrinker *, struct shrink_control *sc);
};
/* using adjacent member of an unnamed struct */
#define KC_DEFINE_SHRINKER(name) \
{ \
struct kc_shrinker_funcs shrinker_funcs; \
struct shinker name; \
}
#define KC_SHRINKER_FUNCS(shrinker) \
((void *)((long)(shrink) - sizeof(struct kc_shrinker_funcs)))
#define KC_INIT_SHRINKER_FUNCS(type, name, shrink, count, scan) do { \
BUILD_BUG_ON(offsetof(cont, shrink_funcs) + sizeof(struct kc_shrinker_funcs)) != \
offsetof(cont, name) + sizeof(struct kc_shrinker_funcs); \
struct kc_shrinker_funcs *_funcs = KC_SHRINKER_FUNCS(shrink) \
__typeof__(shrink) _shrink = (shrink); \
_funcs->count_objects = count; \
_funcs->scan_objects = scan; \
_shrink->shrink = kc_shrink_wrapper; \
} while (0)
#endif
#endif