diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index 30d3630b..74079e66 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -546,3 +546,12 @@ ifneq (,$(shell grep -s 'define __assign_str.dst, src' \ include/trace/stages/stage6_event_callback.h)) ccflags-y += -DKC_HAVE_ASSIGN_STR_PARMS endif + +# +# v6.6-rc4-53-gc42d50aefd17 +# +# el10 yet again modifies the shrinker API significantly, breaking our current +# implementation. +ifneq (,$(shell grep 'struct shrinker .shrinker_alloc' include/linux/shrinker.h)) +ccflags-y += -DKC_SHRINKER_ALLOC +endif diff --git a/kmod/src/block.c b/kmod/src/block.c index 34165aeb..ca92f6b1 100644 --- a/kmod/src/block.c +++ b/kmod/src/block.c @@ -1290,9 +1290,12 @@ int scoutfs_block_setup(struct super_block *sb) binf->sb = sb; init_waitqueue_head(&binf->waitq); - KC_INIT_SHRINKER_FUNCS(&binf->shrinker, block_count_objects, - block_scan_objects); - KC_REGISTER_SHRINKER(&binf->shrinker, "scoutfs-block:" SCSBF, SCSB_ARGS(sb)); + KC_SETUP_SHRINKER(binf->shrinker, binf, 0, block_count_objects, + block_scan_objects, "scoutfs-block:" SCSBF, SCSB_ARGS(sb)); + if (KC_SHRINKER_IS_NULL(binf->shrinker)) { + ret = -ENOMEM; + goto out; + } INIT_WORK(&binf->free_work, block_free_work); init_llist_head(&binf->free_llist); @@ -1314,7 +1317,7 @@ void scoutfs_block_destroy(struct super_block *sb) struct block_info *binf = SCOUTFS_SB(sb)->block_info; if (binf) { - KC_UNREGISTER_SHRINKER(&binf->shrinker); + KC_UNREGISTER_SHRINKER(binf->shrinker); block_shrink_all(sb); flush_work(&binf->free_work); rhashtable_destroy(&binf->ht); diff --git a/kmod/src/item.c b/kmod/src/item.c index bbd6878d..d6fca8b0 100644 --- a/kmod/src/item.c +++ b/kmod/src/item.c @@ -2626,10 +2626,10 @@ int scoutfs_item_setup(struct super_block *sb) for_each_possible_cpu(cpu) init_pcpu_pages(cinf, cpu); - - KC_INIT_SHRINKER_FUNCS(&cinf->shrinker, item_cache_count_objects, - item_cache_scan_objects); - KC_REGISTER_SHRINKER(&cinf->shrinker, "scoutfs-item:" SCSBF, SCSB_ARGS(sb)); + KC_SETUP_SHRINKER(cinf->shrinker, cinf, 0, item_cache_count_objects, + item_cache_scan_objects, "scoutfs-item:" SCSBF, SCSB_ARGS(sb)); + if (KC_SHRINKER_IS_NULL(cinf->shrinker)) + return -ENOMEM; #ifdef KC_CPU_NOTIFIER cinf->notifier.notifier_call = item_cpu_callback; register_hotcpu_notifier(&cinf->notifier); @@ -2654,7 +2654,7 @@ void scoutfs_item_destroy(struct super_block *sb) #ifdef KC_CPU_NOTIFIER unregister_hotcpu_notifier(&cinf->notifier); #endif - KC_UNREGISTER_SHRINKER(&cinf->shrinker); + KC_UNREGISTER_SHRINKER(cinf->shrinker); for_each_possible_cpu(cpu) drop_pcpu_pages(sb, cinf, cpu); diff --git a/kmod/src/kernelcompat.h b/kmod/src/kernelcompat.h index 56d3f202..f0eb179f 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -142,25 +142,54 @@ struct timespec64 kc_current_time(struct inode *inode); #define kc_timespec timespec64 #endif -#ifndef KC_SHRINKER_SHRINK +#ifdef KC_SHRINKER_ALLOC +// el10+ -#define KC_DEFINE_SHRINKER(name) struct shrinker name -#define KC_INIT_SHRINKER_FUNCS(name, countfn, scanfn) do { \ - __typeof__(name) _shrink = (name); \ - _shrink->count_objects = (countfn); \ - _shrink->scan_objects = (scanfn); \ - _shrink->seeks = DEFAULT_SEEKS; \ +#define KC_DEFINE_SHRINKER(name) struct shrinker *(name) +#define KC_SHRINKER_CONTAINER_OF(ptr, type) ptr->private_data +#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \ +do { \ + ptr = shrinker_alloc(flags, fmt, args); \ + if (ptr) { \ + ptr->private_data = (priv); \ + ptr->seeks = DEFAULT_SEEKS; \ + ptr->count_objects = countfn; \ + ptr->scan_objects = scanfn; \ + shrinker_register(ptr); \ + } \ } while (0) +#define KC_UNREGISTER_SHRINKER(ptr) shrinker_free(ptr) +#define KC_SHRINKER_FN(ptr) (ptr) +#define KC_SHRINKER_IS_NULL(ptr) (!(ptr)) +#else /* KC_SHRINKER_ALLOC */ +#ifndef KC_SHRINKER_SHRINK +// el9, el8 + +#define KC_DEFINE_SHRINKER(name) struct shrinker (name) #define KC_SHRINKER_CONTAINER_OF(ptr, type) container_of(ptr, type, shrinker) #ifdef KC_SHRINKER_NAME -#define KC_REGISTER_SHRINKER register_shrinker +#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \ +do { \ + (ptr).count_objects = (countfn); \ + (ptr).scan_objects = (scanfn); \ + (ptr).seeks = DEFAULT_SEEKS; \ + register_shrinker(&(ptr), fmt, args); \ +} while (0) #else -#define KC_REGISTER_SHRINKER(ptr, fmt, ...) (register_shrinker(ptr)) +#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \ +do { \ + (ptr).count_objects = (countfn); \ + (ptr).scan_objects = (scanfn); \ + (ptr).seeks = DEFAULT_SEEKS; \ + register_shrinker(&(ptr)); \ +} while (0) #endif /* KC_SHRINKER_NAME */ -#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(ptr)) -#define KC_SHRINKER_FN(ptr) (ptr) -#else +#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(&(ptr))) +#define KC_SHRINKER_FN(ptr) (&ptr) + +#else /* KC_SHRINKER_SHRINK */ +// el7 #include #ifndef SHRINK_STOP @@ -176,19 +205,21 @@ struct kc_shrinker_wrapper { }; #define KC_DEFINE_SHRINKER(name) struct kc_shrinker_wrapper name; -#define KC_INIT_SHRINKER_FUNCS(name, countfn, scanfn) do { \ - struct kc_shrinker_wrapper *_wrap = (name); \ - _wrap->count_objects = (countfn); \ - _wrap->scan_objects = (scanfn); \ - _wrap->shrink.shrink = kc_shrink_wrapper_fn; \ - _wrap->shrink.seeks = DEFAULT_SEEKS; \ -} while (0) #define KC_SHRINKER_CONTAINER_OF(ptr, type) container_of(container_of(ptr, struct kc_shrinker_wrapper, shrink), type, shrinker) -#define KC_REGISTER_SHRINKER(ptr, fmt, ...) (register_shrinker(ptr.shrink)) -#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(ptr.shrink)) -#define KC_SHRINKER_FN(ptr) (ptr.shrink) +#define KC_SETUP_SHRINKER(ptr, priv, flags, countfn, scanfn, fmt, args) \ +do { \ + (ptr).count_objects = (countfn); \ + (ptr).scan_objects = (scanfn); \ + (ptr).shrink.shrink = kc_shrink_wrapper_fn; \ + (ptr).shrink.seeks = DEFAULT_SEEKS; \ + register_shrinker(&(ptr).shrink); \ +} while (0) +#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(&(ptr).shrink)) +#define KC_SHRINKER_FN(ptr) (&(ptr).shrink) #endif /* KC_SHRINKER_SHRINK */ +#define KC_SHRINKER_IS_NULL(ptr) (0) +#endif /* KC_SHRINKER_ALLOC */ #ifdef KC_KERNEL_GETSOCKNAME_ADDRLEN #include diff --git a/kmod/src/quota.c b/kmod/src/quota.c index b9461a15..afa6cfd3 100644 --- a/kmod/src/quota.c +++ b/kmod/src/quota.c @@ -270,7 +270,7 @@ static void shrink_all_cached_checks(struct squota_info *qtinf) { struct shrink_control sc = { .nr_to_scan = LONG_MAX, }; - scan_cached_checks(KC_SHRINKER_FN(&qtinf->shrinker), &sc); + scan_cached_checks(KC_SHRINKER_FN(qtinf->shrinker), &sc); } static u8 ns_is_attr(u8 ns) @@ -1232,8 +1232,12 @@ int scoutfs_quota_setup(struct super_block *sb) spin_lock_init(&qtinf->lock); init_waitqueue_head(&qtinf->waitq); - KC_INIT_SHRINKER_FUNCS(&qtinf->shrinker, count_cached_checks, scan_cached_checks); - KC_REGISTER_SHRINKER(&qtinf->shrinker, "scoutfs-quota:" SCSBF, SCSB_ARGS(sb)); + KC_SETUP_SHRINKER(qtinf->shrinker, qtinf, 0, count_cached_checks, + scan_cached_checks, "scoutfs-quota:" SCSBF, SCSB_ARGS(sb)); + if (KC_SHRINKER_IS_NULL(qtinf->shrinker)) { + ret = -ENOMEM; + goto out; + } sbi->squota_info = qtinf; @@ -1257,7 +1261,7 @@ void scoutfs_quota_destroy(struct super_block *sb) if (qtinf) { debugfs_remove(qtinf->drop_dentry); - KC_UNREGISTER_SHRINKER(&qtinf->shrinker); + KC_UNREGISTER_SHRINKER(qtinf->shrinker); spin_lock(&qtinf->lock); rs = rcu_dereference_protected(qtinf->ruleset, lockdep_is_held(&qtinf->lock)); diff --git a/kmod/src/wkic.c b/kmod/src/wkic.c index 3109dc61..9129f16e 100644 --- a/kmod/src/wkic.c +++ b/kmod/src/wkic.c @@ -1169,8 +1169,13 @@ int scoutfs_wkic_setup(struct super_block *sb) } winf->sb = sb; - KC_INIT_SHRINKER_FUNCS(&winf->shrinker, wkic_shrink_count, wkic_shrink_scan); - KC_REGISTER_SHRINKER(&winf->shrinker, "scoutfs-weak_item:" SCSBF, SCSB_ARGS(sb)); + KC_SETUP_SHRINKER(winf->shrinker, winf, 0, wkic_shrink_count, + wkic_shrink_scan, "scoutfs-weak_item:" SCSBF, SCSB_ARGS(sb)); + if (KC_SHRINKER_IS_NULL(winf->shrinker)) { + debugfs_remove(winf->drop_dentry); + kfree(winf); + return -ENOMEM; + } sbi->wkic_info = winf; return 0; @@ -1198,7 +1203,7 @@ void scoutfs_wkic_destroy(struct super_block *sb) if (winf) { debugfs_remove(winf->drop_dentry); - KC_UNREGISTER_SHRINKER(&winf->shrinker); + KC_UNREGISTER_SHRINKER(winf->shrinker); /* trees are in sync so tearing down one frees all pages */ rbtree_postorder_for_each_entry_safe(wpage, tmp, &winf->wpage_roots[0], nodes[0]) {