From: Mike S. <sh...@us...> - 2003-04-22 23:17:02
|
Update of /cvsroot/lustre/lustre/ldlm In directory sc8-pr-cvs1:/tmp/cvs-serv2542 Modified Files: Tag: b_devel ldlm_lockd.c Log Message: b=1127: Run expired-lock recovery on a (new) DLM thread, rather than in the timer context, because it will schedule when it sends ASTs, etc. Index: ldlm_lockd.c =================================================================== RCS file: /cvsroot/lustre/lustre/ldlm/ldlm_lockd.c,v retrieving revision 1.131.2.18 retrieving revision 1.131.2.19 diff -u -w -b -B -p -r1.131.2.18 -r1.131.2.19 --- ldlm_lockd.c 22 Apr 2003 20:06:39 -0000 1.131.2.18 +++ ldlm_lockd.c 22 Apr 2003 23:16:58 -0000 1.131.2.19 @@ -28,6 +28,7 @@ # include <linux/module.h> # include <linux/slab.h> # include <linux/init.h> +# include <linux/wait.h> #else # include <liblustre.h> #endif @@ -53,6 +53,86 @@ static spinlock_t waiting_locks_spinlock static struct timer_list waiting_locks_timer; static int ldlm_already_setup = 0; +#ifdef __KERNEL__ + +static struct expired_lock_thread { + wait_queue_head_t elt_waitq; + int elt_state; + struct list_head elt_expired_locks; + spinlock_t elt_lock; +} expired_lock_thread; + +#define ELT_STOPPED 0 +#define ELT_READY 1 +#define ELT_TERMINATE 2 + +static inline int have_expired_locks(void) +{ + int need_to_run; + + spin_lock_bh(&expired_lock_thread.elt_lock); + need_to_run = !list_empty(&expired_lock_thread.elt_expired_locks); + spin_unlock_bh(&expired_lock_thread.elt_lock); + + RETURN(need_to_run); +} + +static int expired_lock_main(void *arg) +{ + struct list_head *expired = &expired_lock_thread.elt_expired_locks; + struct l_wait_info lwi = { 0 }; + unsigned long flags; + + ENTRY; + lock_kernel(); + daemonize(); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + sigfillset(¤t->blocked); + recalc_sigpending(); +#else + spin_lock_irqsave(¤t->sigmask_lock, flags); + sigfillset(¤t->blocked); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); +#endif + + strcpy(current->comm, "ldlm_elt"); + unlock_kernel(); + + expired_lock_thread.elt_state = ELT_READY; + wake_up(&expired_lock_thread.elt_waitq); + + while (1) { + l_wait_event(expired_lock_thread.elt_waitq, + have_expired_locks() || + expired_lock_thread.elt_state == ELT_TERMINATE, + &lwi); + + spin_lock_bh(&expired_lock_thread.elt_lock); + while (!list_empty(expired)) { + struct ldlm_lock *lock = list_entry(expired->next, + struct ldlm_lock, + l_pending_chain); + spin_unlock_bh(&expired_lock_thread.elt_lock); + + ptlrpc_fail_export(lock->l_export); + + spin_lock_bh(&expired_lock_thread.elt_lock); + } + spin_unlock_bh(&expired_lock_thread.elt_lock); + + if (expired_lock_thread.elt_state == ELT_TERMINATE) + break; + } + + expired_lock_thread.elt_state = ELT_STOPPED; + wake_up(&expired_lock_thread.elt_waitq); + RETURN(0); +} + +#endif /* __KERNEL__ */ + static void waiting_locks_callback(unsigned long unused) { struct ldlm_lock *lock; @@ -77,9 +157,11 @@ static void waiting_locks_callback(unsig LDLM_DEBUG(lock, "timer expired"); /* ptlrpc_fail_export must be called with this lock released */ - spin_unlock_bh(&waiting_locks_spinlock); - ptlrpc_fail_export(lock->l_export); - spin_lock_bh(&waiting_locks_spinlock); + spin_lock_bh(&expired_lock_thread.elt_lock); + list_del(&lock->l_pending_chain); + list_add(&lock->l_pending_chain, + &expired_lock_thread.elt_expired_locks); + spin_unlock_bh(&expired_lock_thread.elt_lock); } spin_unlock_bh(&waiting_locks_spinlock); @@ -109,6 +191,8 @@ static int ldlm_add_waiting_lock(struct } list_add_tail(&lock->l_pending_chain, &waiting_locks_list); /* FIFO */ spin_unlock_bh(&waiting_locks_spinlock); + /* We drop this ref when we get removed from the list. */ + class_export_get(lock->l_export); RETURN(1); } @@ -146,6 +230,8 @@ int ldlm_del_waiting_lock(struct ldlm_lo } list_del_init(&lock->l_pending_chain); spin_unlock_bh(&waiting_locks_spinlock); + /* We got this ref when we were added to the list. */ + class_export_put(lock->l_export); RETURN(1); } @@ -816,6 +902,19 @@ static int ldlm_setup(struct obd_device } } + rc = kernel_thread(expired_lock_main, NULL, CLONE_VM | CLONE_FS); + if (rc < 0) { + CERROR("Cannot start ldlm expired-lock thread: %d\n", rc); + GOTO(out_thread, rc); + } + + INIT_LIST_HEAD(&expired_lock_thread.elt_expired_locks); + spin_lock_init(&expired_lock_thread.elt_lock); + expired_lock_thread.elt_state = ELT_STOPPED; + init_waitqueue_head(&expired_lock_thread.elt_waitq); + + wait_event(expired_lock_thread.elt_waitq, + expired_lock_thread.elt_state == ELT_READY); #endif INIT_LIST_HEAD(&waiting_locks_list); spin_lock_init(&waiting_locks_spinlock); @@ -865,6 +964,11 @@ static int ldlm_cleanup(struct obd_devic ptlrpc_stop_all_threads(ldlm->ldlm_cancel_service); ptlrpc_unregister_service(ldlm->ldlm_cancel_service); ldlm_proc_cleanup(obddev); + + expired_lock_thread.elt_state = ELT_TERMINATE; + wake_up(&expired_lock_thread.elt_waitq); + wait_event(expired_lock_thread.elt_waitq, + expired_lock_thread.elt_state == ELT_STOPPED); inter_module_unregister("ldlm_namespace_cleanup"); inter_module_unregister("ldlm_cli_cancel_unused"); |