[DLM] fix leaking user locks

User NOQUEUE lock requests to a remote node that failed with -EAGAIN were
never being removed from a process's list of locks.

Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
David Teigland
2006-07-18 11:24:04 -05:00
committed by Steven Whitehouse
parent 3b4a0a7494
commit 34e22bed19
2 changed files with 20 additions and 3 deletions

View File

@@ -526,6 +526,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
lkb->lkb_nodeid = -1; lkb->lkb_nodeid = -1;
lkb->lkb_grmode = DLM_LOCK_IV; lkb->lkb_grmode = DLM_LOCK_IV;
kref_init(&lkb->lkb_ref); kref_init(&lkb->lkb_ref);
INIT_LIST_HEAD(&lkb->lkb_ownqueue);
get_random_bytes(&bucket, sizeof(bucket)); get_random_bytes(&bucket, sizeof(bucket));
bucket &= (ls->ls_lkbtbl_size - 1); bucket &= (ls->ls_lkbtbl_size - 1);
@@ -3705,7 +3706,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
goto out_put; goto out_put;
spin_lock(&ua->proc->locks_spin); spin_lock(&ua->proc->locks_spin);
list_del(&lkb->lkb_ownqueue); list_del_init(&lkb->lkb_ownqueue);
spin_unlock(&ua->proc->locks_spin); spin_unlock(&ua->proc->locks_spin);
/* this removes the reference for the proc->locks list added by /* this removes the reference for the proc->locks list added by
@@ -3749,7 +3750,7 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
/* this lkb was removed from the WAITING queue */ /* this lkb was removed from the WAITING queue */
if (lkb->lkb_grmode == DLM_LOCK_IV) { if (lkb->lkb_grmode == DLM_LOCK_IV) {
spin_lock(&ua->proc->locks_spin); spin_lock(&ua->proc->locks_spin);
list_del(&lkb->lkb_ownqueue); list_del_init(&lkb->lkb_ownqueue);
spin_unlock(&ua->proc->locks_spin); spin_unlock(&ua->proc->locks_spin);
unhold_lkb(lkb); unhold_lkb(lkb);
} }
@@ -3817,7 +3818,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
unhold_lkb(lkb); unhold_lkb(lkb);
} }
list_del(&lkb->lkb_ownqueue); list_del_init(&lkb->lkb_ownqueue);
if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) { if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) {
lkb->lkb_flags |= DLM_IFL_ORPHAN; lkb->lkb_flags |= DLM_IFL_ORPHAN;

View File

@@ -133,6 +133,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
struct dlm_ls *ls; struct dlm_ls *ls;
struct dlm_user_args *ua; struct dlm_user_args *ua;
struct dlm_user_proc *proc; struct dlm_user_proc *proc;
int remove_ownqueue = 0;
/* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each
lkb before dealing with it. We need to check this lkb before dealing with it. We need to check this
@@ -171,6 +172,14 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
wake_up_interruptible(&proc->wait); wake_up_interruptible(&proc->wait);
} }
/* noqueue requests that fail may need to be removed from the
proc's locks list, there should be a better way of detecting
this situation than checking all these things... */
if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV &&
ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue))
remove_ownqueue = 1;
/* We want to copy the lvb to userspace when the completion /* We want to copy the lvb to userspace when the completion
ast is read if the status is 0, the lock has an lvb and ast is read if the status is 0, the lock has an lvb and
lvb_ops says we should. We could probably have set_lvb_lock() lvb_ops says we should. We could probably have set_lvb_lock()
@@ -185,6 +194,13 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
ua->update_user_lvb = 0; ua->update_user_lvb = 0;
spin_unlock(&proc->asts_spin); spin_unlock(&proc->asts_spin);
if (remove_ownqueue) {
spin_lock(&ua->proc->locks_spin);
list_del_init(&lkb->lkb_ownqueue);
spin_unlock(&ua->proc->locks_spin);
dlm_put_lkb(lkb);
}
out: out:
mutex_unlock(&ls->ls_clear_proc_locks); mutex_unlock(&ls->ls_clear_proc_locks);
} }