!!! Important kernel design point !!!
Very generic notifiers and hooks tend to have a large maintenance impact because they have the potential to alter the code flow in unexpected ways, lead to lock order problems, bugs, and unexpected behavior, and generally making code harder to maintain and debug later.
Linux kernel is a lock-based complex parallel system, the main method to prevent ABBA style dead-lock is enforcing lock order. But notifiers or hooks makes it hard to audit the order of locks.
Notifiers or hooks in lower layer to call functions on higher layer should be avoided. One method to call higher layer function in lower layer is via work queue like asynchronous mechanism.
Notifiers or hooks in higher layer to call functions on lower layer is OK. Such as struct file_operations is collections of function pointers (a kind of hooks?), it is only used as some kind of abstraction for lower layer, make adding new lower layer component more convenient.
For a project which is very complex like Linux kernel, (seems that most projects become more and more complex as time goes by), maintenance is something in the core of Linux kernel development.
To make code maintainable, firstly, code should be made readable. The code is clean-upped and redesigned again and again to make it cleaner, thus more readable.
It is much easier to add a component under the current design. Such as add a new device driver. If you need something to be changed in subsystem core, you should consider the design, maybe you need clean-up or redesign some part of the subsystem core to make code maintainable.
A patch submitter should maintain his code at least for a short while after merging.
Interface designs for user space programs is very important too. It should be stable for imaginable future.
Changing a published interface later is much harder and often special backwards compatiblility code is required.