Skip to content
Snippets Groups Projects
Commit bc4e78a6 authored by Johann Lombardi's avatar Johann Lombardi
Browse files

Branch b1_6

b=17385
i=green
i=shadow

grab lock reference when the lock is added to the waiting or expired list.
parent bd78a8a4
No related branches found
No related tags found
No related merge requests found
...@@ -202,11 +202,19 @@ static int expired_lock_main(void *arg) ...@@ -202,11 +202,19 @@ static int expired_lock_main(void *arg)
lock->l_export); lock->l_export);
lock->l_export = NULL; lock->l_export = NULL;
LDLM_ERROR(lock, "free export"); LDLM_ERROR(lock, "free export");
/* release extra ref grabbed by
* ldlm_add_waiting_lock() or
* ldlm_failed_ast() */
LDLM_LOCK_PUT(lock);
continue; continue;
} }
export = class_export_get(lock->l_export); export = class_export_get(lock->l_export);
spin_unlock_bh(&waiting_locks_spinlock); spin_unlock_bh(&waiting_locks_spinlock);
/* release extra ref grabbed by ldlm_add_waiting_lock()
* or ldlm_failed_ast() */
LDLM_LOCK_PUT(lock);
do_dump++; do_dump++;
class_fail_export(export); class_fail_export(export);
class_export_put(export); class_export_put(export);
...@@ -268,6 +276,9 @@ static void waiting_locks_callback(unsigned long unused) ...@@ -268,6 +276,9 @@ static void waiting_locks_callback(unsigned long unused)
} }
last = lock; last = lock;
/* no needs to take an extra ref on the lock since it was in
* the waiting_locks_list and ldlm_add_waiting_lock()
* already grabbed a ref */
list_del(&lock->l_pending_chain); list_del(&lock->l_pending_chain);
list_add(&lock->l_pending_chain, list_add(&lock->l_pending_chain,
&expired_lock_thread.elt_expired_locks); &expired_lock_thread.elt_expired_locks);
...@@ -299,6 +310,8 @@ static void waiting_locks_callback(unsigned long unused) ...@@ -299,6 +310,8 @@ static void waiting_locks_callback(unsigned long unused)
* lock. We add it to the pending-callback chain, and schedule the lock-timeout * lock. We add it to the pending-callback chain, and schedule the lock-timeout
* timer to fire appropriately. (We round up to the next second, to avoid * timer to fire appropriately. (We round up to the next second, to avoid
* floods of timer firings during periods of high lock contention and traffic). * floods of timer firings during periods of high lock contention and traffic).
* As done by ldlm_add_waiting_lock(), the caller must grab a lock reference
* if it has been added to the waiting list (1 is returned).
* *
* Called with the namespace lock held. * Called with the namespace lock held.
*/ */
...@@ -346,6 +359,10 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock) ...@@ -346,6 +359,10 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
} }
ret = __ldlm_add_waiting_lock(lock); ret = __ldlm_add_waiting_lock(lock);
if (ret)
/* grab ref on the lock if it has been added to the
* waiting list */
LDLM_LOCK_GET(lock);
spin_unlock_bh(&waiting_locks_spinlock); spin_unlock_bh(&waiting_locks_spinlock);
LDLM_DEBUG(lock, "%sadding to wait list", LDLM_DEBUG(lock, "%sadding to wait list",
...@@ -357,10 +374,12 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock) ...@@ -357,10 +374,12 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
* Remove a lock from the pending list, likely because it had its cancellation * Remove a lock from the pending list, likely because it had its cancellation
* callback arrive without incident. This adjusts the lock-timeout timer if * callback arrive without incident. This adjusts the lock-timeout timer if
* needed. Returns 0 if the lock wasn't pending after all, 1 if it was. * needed. Returns 0 if the lock wasn't pending after all, 1 if it was.
* As done by ldlm_del_waiting_lock(), the caller must release the lock
* reference when the lock is removed from any list (1 is returned).
* *
* Called with namespace lock held. * Called with namespace lock held.
*/ */
int __ldlm_del_waiting_lock(struct ldlm_lock *lock) static int __ldlm_del_waiting_lock(struct ldlm_lock *lock)
{ {
struct list_head *list_next; struct list_head *list_next;
...@@ -399,6 +418,10 @@ int ldlm_del_waiting_lock(struct ldlm_lock *lock) ...@@ -399,6 +418,10 @@ int ldlm_del_waiting_lock(struct ldlm_lock *lock)
spin_lock_bh(&waiting_locks_spinlock); spin_lock_bh(&waiting_locks_spinlock);
ret = __ldlm_del_waiting_lock(lock); ret = __ldlm_del_waiting_lock(lock);
spin_unlock_bh(&waiting_locks_spinlock); spin_unlock_bh(&waiting_locks_spinlock);
if (ret)
/* release lock ref if it has indeed been removed
* from a list */
LDLM_LOCK_PUT(lock);
LDLM_DEBUG(lock, "%s", ret == 0 ? "wasn't waiting" : "removed"); LDLM_DEBUG(lock, "%s", ret == 0 ? "wasn't waiting" : "removed");
return ret; return ret;
...@@ -425,6 +448,8 @@ int ldlm_refresh_waiting_lock(struct ldlm_lock *lock) ...@@ -425,6 +448,8 @@ int ldlm_refresh_waiting_lock(struct ldlm_lock *lock)
return 0; return 0;
} }
/* we remove/add the lock to the waiting list, so no needs to
* release/take a lock reference */
__ldlm_del_waiting_lock(lock); __ldlm_del_waiting_lock(lock);
__ldlm_add_waiting_lock(lock); __ldlm_add_waiting_lock(lock);
spin_unlock_bh(&waiting_locks_spinlock); spin_unlock_bh(&waiting_locks_spinlock);
...@@ -467,6 +492,10 @@ static void ldlm_failed_ast(struct ldlm_lock *lock, int rc, ...@@ -467,6 +492,10 @@ static void ldlm_failed_ast(struct ldlm_lock *lock, int rc,
libcfs_debug_dumplog(); libcfs_debug_dumplog();
#ifdef __KERNEL__ #ifdef __KERNEL__
spin_lock_bh(&waiting_locks_spinlock); spin_lock_bh(&waiting_locks_spinlock);
if (__ldlm_del_waiting_lock(lock) == 0)
/* the lock was not in any list, grab an extra ref before adding
* the lock to the expired list */
LDLM_LOCK_GET(lock);
list_add(&lock->l_pending_chain, &expired_lock_thread.elt_expired_locks); list_add(&lock->l_pending_chain, &expired_lock_thread.elt_expired_locks);
cfs_waitq_signal(&expired_lock_thread.elt_waitq); cfs_waitq_signal(&expired_lock_thread.elt_waitq);
spin_unlock_bh(&waiting_locks_spinlock); spin_unlock_bh(&waiting_locks_spinlock);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment