From 051f0adeb0615da83c819ff74da467bb4117ae63 Mon Sep 17 00:00:00 2001 From: Mr NeilBrown Date: Wed, 23 Oct 2019 11:30:50 +1100 Subject: [PATCH] LU-12780 osp: don't use ptlrpc_thread for lwp_notify_main() Instead of ptlrpc_thread, use native kthread functionality. - There is no need to synchronise on start-up. But we do need to ensure class_export_get/put are balanced, and we cannot be certain that the thread function will run. So call class_export_get() before starting the thread, and class_export_put() after it has finished. - As the thread exits independantly, waiting for it to finish is a little more complex than just using kthread_stop(). If the thread stops before lwp_device_fini() runs, it sets ->lpd_notify_task to NULL, and lwp_device_fini() doesn't wait. If lwp_device_fini() runs first, it set ->lpd_notify_task to NULL and calls kthread_stop(). The thread notices this, and deliberately waits for kthread_should_stop() to avoid any races in kthread code. xchg() is used to ensure exactly one of the thread and lwp_device_fini() sets lpd_notify_task to NULL. Signed-off-by: Mr NeilBrown Change-Id: I45621f325d14194af5a44f86f7e605bdafbbb9be Reviewed-on: https://review.whamcloud.com/36266 Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/osp/lwp_dev.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/lustre/osp/lwp_dev.c b/lustre/osp/lwp_dev.c index 4c5828e..6fdf950 100644 --- a/lustre/osp/lwp_dev.c +++ b/lustre/osp/lwp_dev.c @@ -50,7 +50,7 @@ struct lwp_device { struct lu_device lpd_dev; struct obd_device *lpd_obd; /* corresponding OBD device */ struct obd_export *lpd_exp; /* export of LWP */ - struct ptlrpc_thread lpd_notify_thread; /* notify thread */ + struct task_struct *lpd_notify_task; /* notify thread */ int lpd_connects; /* use count, 0 or 1 */ }; @@ -87,8 +87,7 @@ static int lwp_setup(const struct lu_env *env, struct lwp_device *lwp, int rc; ENTRY; - thread_set_flags(&lwp->lpd_notify_thread, SVC_STOPPED); - init_waitqueue_head(&lwp->lpd_notify_thread.t_ctl_waitq); + lwp->lpd_notify_task = NULL; OBD_ALLOC_PTR(bufs); if (bufs == NULL) @@ -368,11 +367,15 @@ static struct lu_device *lwp_device_fini(const struct lu_env *env, struct lu_device *ludev) { struct lwp_device *m = lu2lwp_dev(ludev); - struct ptlrpc_thread *thread = &m->lpd_notify_thread; + struct task_struct *task = NULL; int rc; ENTRY; - wait_event_idle(thread->t_ctl_waitq, thread_is_stopped(thread)); + task = xchg(&m->lpd_notify_task, NULL); + if (task) { + kthread_stop(task); + class_export_put(m->lpd_exp); + } if (m->lpd_exp != NULL) class_disconnect(m->lpd_exp); @@ -405,22 +408,23 @@ static int lwp_notify_main(void *args) { struct obd_export *exp = (struct obd_export *)args; struct lwp_device *lwp; - struct ptlrpc_thread *thread; LASSERT(exp != NULL); - class_export_get(exp); lwp = lu2lwp_dev(exp->exp_obd->obd_lu_dev); - thread = &lwp->lpd_notify_thread; - - thread_set_flags(thread, SVC_RUNNING); - wake_up(&thread->t_ctl_waitq); lustre_notify_lwp_list(exp); - class_export_put(exp); - thread_set_flags(thread, SVC_STOPPED); - wake_up(&thread->t_ctl_waitq); + if (xchg(&lwp->lpd_notify_task, NULL) == NULL) + /* lwp_device_fini() is waiting for me + * Note that the wakeup comes direct from + * kthread_stop, not from wake_up_var(). + * lwp_device_fini() will call class_export_put(). + */ + wait_var_event(lwp, kthread_should_stop()); + else + class_export_put(exp); + return 0; } @@ -432,33 +436,31 @@ static int lwp_notify_main(void *args) static void lwp_notify_users(struct obd_export *exp) { struct lwp_device *lwp; - struct ptlrpc_thread *thread; struct task_struct *task; char name[MTI_NAME_MAXLEN]; LASSERT(exp != NULL); lwp = lu2lwp_dev(exp->exp_obd->obd_lu_dev); - thread = &lwp->lpd_notify_thread; snprintf(name, MTI_NAME_MAXLEN, "lwp_notify_%s", exp->exp_obd->obd_name); /* Notify happens only on LWP setup, so there shouldn't * be notify thread running */ - if (!thread_is_stopped(thread)) { + if (lwp->lpd_notify_task) { CERROR("LWP notify thread: %s wasn't stopped\n", name); return; } - task = kthread_run(lwp_notify_main, exp, name); + task = kthread_create(lwp_notify_main, exp, name); if (IS_ERR(task)) { - thread_set_flags(thread, SVC_STOPPED); CERROR("Failed to start LWP notify thread:%s. %lu\n", name, PTR_ERR(task)); + } else { + lwp->lpd_notify_task = task; + class_export_get(exp); + wake_up_process(task); } - - wait_event_idle(thread->t_ctl_waitq, - thread_is_running(thread) || thread_is_stopped(thread)); } /** -- 1.8.3.1