On Thu, Dec 20, 2018 at 05:06:19PM -0600, miny...@acm.org wrote: > From: Corey Minyard <cminy...@mvista.com> > > The IPMI driver was recently modified to use SRCU, but it turns out > this uses a chunk of percpu memory, even if IPMI is never used. > > So modify thing to on initialize on the first use. There was already > code to sort of handle this for handling init races, so piggy back > on top of that, and simplify it in the process. > > Signed-off-by: Corey Minyard <cminy...@mvista.com> > Reported-by: Tejun Heo <t...@kernel.org> > Cc: Paul E. McKenney <paul...@linux.vnet.ibm.com>
The initialization portion looks good, but don't you need a cleanup_srcu_struct() somewhere in cleanup_ipmi()? Or is it not possible to repeatedly load and unload this as a module? Thanx, Paul > --- > drivers/char/ipmi/ipmi_msghandler.c | 133 +++++++++++++++------------- > 1 file changed, 70 insertions(+), 63 deletions(-) > > Tejun, here's a patch to fix the issue. Does this look ok? > > Maybe it would be best to not use SRCU, but IMHO it's easier to use > than locking. That's why I used it. > > diff --git a/drivers/char/ipmi/ipmi_msghandler.c > b/drivers/char/ipmi/ipmi_msghandler.c > index 9650fe109f67..7490b9ae8508 100644 > --- a/drivers/char/ipmi/ipmi_msghandler.c > +++ b/drivers/char/ipmi/ipmi_msghandler.c > @@ -62,7 +62,8 @@ static void ipmi_debug_msg(const char *title, unsigned char > *data, > { } > #endif > > -static int initialized; > +static bool initialized; > +static bool drvregistered; > > enum ipmi_panic_event_op { > IPMI_SEND_PANIC_EVENT_NONE, > @@ -630,7 +631,7 @@ static DEFINE_MUTEX(ipmidriver_mutex); > > static LIST_HEAD(ipmi_interfaces); > static DEFINE_MUTEX(ipmi_interfaces_mutex); > -DEFINE_STATIC_SRCU(ipmi_interfaces_srcu); > +struct srcu_struct ipmi_interfaces_srcu; > > /* > * List of watchers that want to know when smi's are added and deleted. > @@ -1154,7 +1155,7 @@ int ipmi_create_user(unsigned int if_num, > { > unsigned long flags; > struct ipmi_user *new_user; > - int rv = 0, index; > + int rv, index; > struct ipmi_smi *intf; > > /* > @@ -1172,18 +1173,9 @@ int ipmi_create_user(unsigned int if_num, > * Make sure the driver is actually initialized, this handles > * problems with initialization order. > */ > - if (!initialized) { > - rv = ipmi_init_msghandler(); > - if (rv) > - return rv; > - > - /* > - * The init code doesn't return an error if it was turned > - * off, but it won't initialize. Check that. > - */ > - if (!initialized) > - return -ENODEV; > - } > + rv = ipmi_init_msghandler(); > + if (rv) > + return rv; > > new_user = kmalloc(sizeof(*new_user), GFP_KERNEL); > if (!new_user) > @@ -3364,17 +3356,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers > *handlers, > * Make sure the driver is actually initialized, this handles > * problems with initialization order. > */ > - if (!initialized) { > - rv = ipmi_init_msghandler(); > - if (rv) > - return rv; > - /* > - * The init code doesn't return an error if it was turned > - * off, but it won't initialize. Check that. > - */ > - if (!initialized) > - return -ENODEV; > - } > + rv = ipmi_init_msghandler(); > + if (rv) > + return rv; > > intf = kzalloc(sizeof(*intf), GFP_KERNEL); > if (!intf) > @@ -5084,6 +5068,22 @@ static int panic_event(struct notifier_block *this, > return NOTIFY_DONE; > } > > +/* Must be called with ipmi_interfaces_mutex held. */ > +static int ipmi_register_driver(void) > +{ > + int rv; > + > + if (drvregistered) > + return 0; > + > + rv = driver_register(&ipmidriver.driver); > + if (rv) > + pr_err("Could not register IPMI driver\n"); > + else > + drvregistered = true; > + return rv; > +} > + > static struct notifier_block panic_block = { > .notifier_call = panic_event, > .next = NULL, > @@ -5094,66 +5094,73 @@ static int ipmi_init_msghandler(void) > { > int rv; > > + mutex_lock(&ipmi_interfaces_mutex); > + rv = ipmi_register_driver(); > + if (rv) > + goto out; > if (initialized) > - return 0; > - > - rv = driver_register(&ipmidriver.driver); > - if (rv) { > - pr_err("Could not register IPMI driver\n"); > - return rv; > - } > + goto out; > > - pr_info("version " IPMI_DRIVER_VERSION "\n"); > + init_srcu_struct(&ipmi_interfaces_srcu); > > timer_setup(&ipmi_timer, ipmi_timeout, 0); > mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); > > atomic_notifier_chain_register(&panic_notifier_list, &panic_block); > > - initialized = 1; > + initialized = true; > > - return 0; > +out: > + mutex_unlock(&ipmi_interfaces_mutex); > + return rv; > } > > static int __init ipmi_init_msghandler_mod(void) > { > - ipmi_init_msghandler(); > - return 0; > + int rv; > + > + pr_info("version " IPMI_DRIVER_VERSION "\n"); > + > + mutex_lock(&ipmi_interfaces_mutex); > + rv = ipmi_register_driver(); > + mutex_unlock(&ipmi_interfaces_mutex); > + > + return rv; > } > > static void __exit cleanup_ipmi(void) > { > int count; > > - if (!initialized) > - return; > - > - atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); > - > - /* > - * This can't be called if any interfaces exist, so no worry > - * about shutting down the interfaces. > - */ > + if (initialized) { > + atomic_notifier_chain_unregister(&panic_notifier_list, > + &panic_block); > > - /* > - * Tell the timer to stop, then wait for it to stop. This > - * avoids problems with race conditions removing the timer > - * here. > - */ > - atomic_inc(&stop_operation); > - del_timer_sync(&ipmi_timer); > + /* > + * This can't be called if any interfaces exist, so no worry > + * about shutting down the interfaces. > + */ > > - driver_unregister(&ipmidriver.driver); > + /* > + * Tell the timer to stop, then wait for it to stop. This > + * avoids problems with race conditions removing the timer > + * here. > + */ > + atomic_inc(&stop_operation); > + del_timer_sync(&ipmi_timer); > > - initialized = 0; > + initialized = false; > > - /* Check for buffer leaks. */ > - count = atomic_read(&smi_msg_inuse_count); > - if (count != 0) > - pr_warn("SMI message count %d at exit\n", count); > - count = atomic_read(&recv_msg_inuse_count); > - if (count != 0) > - pr_warn("recv message count %d at exit\n", count); > + /* Check for buffer leaks. */ > + count = atomic_read(&smi_msg_inuse_count); > + if (count != 0) > + pr_warn("SMI message count %d at exit\n", count); > + count = atomic_read(&recv_msg_inuse_count); > + if (count != 0) > + pr_warn("recv message count %d at exit\n", count); > + } > + if (drvregistered) > + driver_unregister(&ipmidriver.driver); > } > module_exit(cleanup_ipmi); > > -- > 2.17.1 > _______________________________________________ Openipmi-developer mailing list Openipmi-developer@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openipmi-developer