提交 34e22bed 编写于 作者: D David Teigland 提交者: Steven Whitehouse

[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: NDavid Teigland <teigland@redhat.com>
Signed-off-by: NSteven Whitehouse <swhiteho@redhat.com>
上级 3b4a0a74
...@@ -526,6 +526,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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;
......
...@@ -133,6 +133,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) ...@@ -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) ...@@ -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) ...@@ -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);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册