diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index bce67e26..20e5ba90 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -484,3 +484,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 1b7204a9..ade9d1dc 100644 --- a/kmod/src/block.c +++ b/kmod/src/block.c @@ -1300,9 +1300,9 @@ 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); - KC_INIT_SHRINKER_FUNCS(&binf->shrinker, block_count_objects, - block_scan_objects); - KC_REGISTER_SHRINKER(&binf->shrinker, "scoutfs-block:" SCSBF, SCSB_ARGS(sb)); + KC_ALLOC_SHRINKER(binf->shrinker, binf, 0, "scoutfs-block:" SCSBF, SCSB_ARGS(sb)); + KC_INIT_SHRINKER_FUNCS(binf->shrinker, block_count_objects, block_scan_objects); + KC_REGISTER_SHRINKER(binf->shrinker); INIT_WORK(&binf->free_work, block_free_work); init_llist_head(&binf->free_llist); @@ -1322,7 +1322,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_remove_all(sb); flush_work(&binf->free_work); rhashtable_destroy(&binf->ht); diff --git a/kmod/src/item.c b/kmod/src/item.c index 330f3f78..737e5ce8 100644 --- a/kmod/src/item.c +++ b/kmod/src/item.c @@ -2690,10 +2690,9 @@ 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_ALLOC_SHRINKER(cinf->shrinker, cinf, 0, "scoutfs-item:" SCSBF, SCSB_ARGS(sb)); + KC_INIT_SHRINKER_FUNCS(cinf->shrinker, item_cache_count_objects, item_cache_scan_objects); + KC_REGISTER_SHRINKER(cinf->shrinker); #ifdef KC_CPU_NOTIFIER cinf->notifier.notifier_call = item_cpu_callback; register_hotcpu_notifier(&cinf->notifier); @@ -2720,7 +2719,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 68155e38..74fe61ec 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -142,25 +142,53 @@ 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_DEFINE_SHRINKER(name) struct shrinker *(name) +#define KC_SHRINKER_CONTAINER_OF(ptr, type) ptr->private_data +#define KC_ALLOC_SHRINKER(ptr, priv, flags, fmt, args) \ +do { \ + ptr = shrinker_alloc(flags, fmt, args); \ + if (ptr) { \ + ptr->private_data = (priv); \ + ptr->seeks = 0; \ + } \ +} while (0) +#define KC_INIT_SHRINKER_FUNCS(ptr, countfn, scanfn) \ +do { \ + (ptr)->count_objects = countfn; \ + (ptr)->scan_objects = scanfn; \ +} while (0) +#define KC_REGISTER_SHRINKER(ptr) shrinker_register(ptr) +#define KC_UNREGISTER_SHRINKER(ptr) shrinker_free(ptr); +#define KC_SHRINKER_FN(ptr) (ptr) + +#else /* KC_SHRINKER_ALLOC */ +#ifndef KC_SHRINKER_SHRINK +// el9, el8 + +#define KC_DEFINE_SHRINKER(name) struct shrinker (name) #define KC_INIT_SHRINKER_FUNCS(name, countfn, scanfn) do { \ - __typeof__(name) _shrink = (name); \ + __typeof__(name) *_shrink = &(name); \ _shrink->count_objects = (countfn); \ _shrink->scan_objects = (scanfn); \ - _shrink->seeks = DEFAULT_SEEKS; \ + _shrink->seeks = DEFAULT_SEEKS; \ } while (0) #define KC_SHRINKER_CONTAINER_OF(ptr, type) container_of(ptr, type, shrinker) #ifdef KC_SHRINKER_NAME -#define KC_REGISTER_SHRINKER register_shrinker +#define KC_ALLOC_SHRINKER(ptr, priv, flags, fmt, args) register_shrinker(&ptr, fmt, args) +#define KC_REGISTER_SHRINKER(ptr) do {} while(0) #else -#define KC_REGISTER_SHRINKER(ptr, fmt, ...) (register_shrinker(ptr)) +#define KC_ALLOC_SHRINKER(ptr, priv, flags, fmt, args) do {} while(0) +#define KC_REGISTER_SHRINKER(ptr) (register_shrinker(&ptr)) #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 @@ -177,18 +205,20 @@ 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); \ + 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_ALLOC_SHRINKER(ptr, priv, flags, fmt, args) do {} while(0) +#define KC_REGISTER_SHRINKER(ptr) (register_shrinker(&(ptr).shrink)) +#define KC_UNREGISTER_SHRINKER(ptr) (unregister_shrinker(&(ptr).shrink)) +#define KC_SHRINKER_FN(ptr) (&(ptr).shrink) #endif /* KC_SHRINKER_SHRINK */ +#endif /* KC_SHRINKER_ALLOC */ #ifdef KC_KERNEL_GETSOCKNAME_ADDRLEN #include diff --git a/kmod/src/lock.c b/kmod/src/lock.c index ce77bb51..851a1873 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -1505,7 +1505,7 @@ void scoutfs_free_unused_locks(struct super_block *sb) .nr_to_scan = INT_MAX, }; - lock_scan_objects(KC_SHRINKER_FN(&linfo->shrinker), &sc); + lock_scan_objects(KC_SHRINKER_FN(linfo->shrinker), &sc); } static void lock_tseq_show(struct seq_file *m, struct scoutfs_tseq_entry *ent) @@ -1612,7 +1612,7 @@ void scoutfs_lock_shutdown(struct super_block *sb) trace_scoutfs_lock_shutdown(sb, linfo); /* stop the shrinker from queueing work */ - KC_UNREGISTER_SHRINKER(&linfo->shrinker); + KC_UNREGISTER_SHRINKER(linfo->shrinker); flush_work(&linfo->shrink_work); /* cause current and future lock calls to return errors */ @@ -1731,9 +1731,9 @@ int scoutfs_lock_setup(struct super_block *sb) spin_lock_init(&linfo->lock); linfo->lock_tree = RB_ROOT; linfo->lock_range_tree = RB_ROOT; - KC_INIT_SHRINKER_FUNCS(&linfo->shrinker, lock_count_objects, - lock_scan_objects); - KC_REGISTER_SHRINKER(&linfo->shrinker, "scoutfs-lock:" SCSBF, SCSB_ARGS(sb)); + KC_ALLOC_SHRINKER(linfo->shrinker, linfo, 0, "scoutfs-lock:" SCSBF, SCSB_ARGS(sb)); + KC_INIT_SHRINKER_FUNCS(linfo->shrinker, lock_count_objects, lock_scan_objects); + KC_REGISTER_SHRINKER(linfo->shrinker); INIT_LIST_HEAD(&linfo->lru_list); INIT_WORK(&linfo->inv_work, lock_invalidate_worker); INIT_LIST_HEAD(&linfo->inv_list); diff --git a/kmod/src/quota.c b/kmod/src/quota.c index 9f331325..bca138c4 100644 --- a/kmod/src/quota.c +++ b/kmod/src/quota.c @@ -269,7 +269,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) @@ -1225,8 +1225,9 @@ 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_ALLOC_SHRINKER(qtinf->shrinker, qtinf, 0, "scoutfs-quota:" SCSBF, SCSB_ARGS(sb)); + KC_INIT_SHRINKER_FUNCS(qtinf->shrinker, count_cached_checks, scan_cached_checks); + KC_REGISTER_SHRINKER(qtinf->shrinker); sbi->squota_info = qtinf; @@ -1250,7 +1251,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 0dc476f4..2a3a4878 100644 --- a/kmod/src/wkic.c +++ b/kmod/src/wkic.c @@ -1112,8 +1112,9 @@ 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_ALLOC_SHRINKER(winf->shrinker, winf, 0, "scoutfs-weak_item:" SCSBF, SCSB_ARGS(sb)); + KC_INIT_SHRINKER_FUNCS(winf->shrinker, wkic_shrink_count, wkic_shrink_scan); + KC_REGISTER_SHRINKER(winf->shrinker); sbi->wkic_info = winf; return 0; @@ -1141,7 +1142,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]) {