diff options
| author | David Teigland <teigland@redhat.com> | 2006-07-18 12:24:04 -0400 |
|---|---|---|
| committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-07-20 00:11:15 -0400 |
| commit | 34e22bed19013c77f942083e25cfc7adf6c71a8f (patch) | |
| tree | 18c44bb1e3e3d40fc04f61020497f935a97df576 | |
| parent | 3b4a0a74949cf4f87f7ca84cc0457eb5687b2923 (diff) | |
[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>
| -rw-r--r-- | fs/dlm/lock.c | 7 | ||||
| -rw-r--r-- | fs/dlm/user.c | 16 |
2 files changed, 20 insertions, 3 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 82e1ac2518..2274432181 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -526,6 +526,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) | |||
| 526 | lkb->lkb_nodeid = -1; | 526 | lkb->lkb_nodeid = -1; |
| 527 | lkb->lkb_grmode = DLM_LOCK_IV; | 527 | lkb->lkb_grmode = DLM_LOCK_IV; |
| 528 | kref_init(&lkb->lkb_ref); | 528 | kref_init(&lkb->lkb_ref); |
| 529 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); | ||
| 529 | 530 | ||
| 530 | get_random_bytes(&bucket, sizeof(bucket)); | 531 | get_random_bytes(&bucket, sizeof(bucket)); |
| 531 | bucket &= (ls->ls_lkbtbl_size - 1); | 532 | 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 | goto out_put; | 3706 | goto out_put; |
| 3706 | 3707 | ||
| 3707 | spin_lock(&ua->proc->locks_spin); | 3708 | spin_lock(&ua->proc->locks_spin); |
| 3708 | list_del(&lkb->lkb_ownqueue); | 3709 | list_del_init(&lkb->lkb_ownqueue); |
| 3709 | spin_unlock(&ua->proc->locks_spin); | 3710 | spin_unlock(&ua->proc->locks_spin); |
| 3710 | 3711 | ||
| 3711 | /* this removes the reference for the proc->locks list added by | 3712 | /* 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 | /* this lkb was removed from the WAITING queue */ | 3750 | /* this lkb was removed from the WAITING queue */ |
| 3750 | if (lkb->lkb_grmode == DLM_LOCK_IV) { | 3751 | if (lkb->lkb_grmode == DLM_LOCK_IV) { |
| 3751 | spin_lock(&ua->proc->locks_spin); | 3752 | spin_lock(&ua->proc->locks_spin); |
| 3752 | list_del(&lkb->lkb_ownqueue); | 3753 | list_del_init(&lkb->lkb_ownqueue); |
| 3753 | spin_unlock(&ua->proc->locks_spin); | 3754 | spin_unlock(&ua->proc->locks_spin); |
| 3754 | unhold_lkb(lkb); | 3755 | unhold_lkb(lkb); |
| 3755 | } | 3756 | } |
| @@ -3817,7 +3818,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
| 3817 | unhold_lkb(lkb); | 3818 | unhold_lkb(lkb); |
| 3818 | } | 3819 | } |
| 3819 | 3820 | ||
| 3820 | list_del(&lkb->lkb_ownqueue); | 3821 | list_del_init(&lkb->lkb_ownqueue); |
| 3821 | 3822 | ||
| 3822 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) { | 3823 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) { |
| 3823 | lkb->lkb_flags |= DLM_IFL_ORPHAN; | 3824 | lkb->lkb_flags |= DLM_IFL_ORPHAN; |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 1f05960a91..fd19caf9af 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
| @@ -133,6 +133,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | |||
| 133 | struct dlm_ls *ls; | 133 | struct dlm_ls *ls; |
| 134 | struct dlm_user_args *ua; | 134 | struct dlm_user_args *ua; |
| 135 | struct dlm_user_proc *proc; | 135 | struct dlm_user_proc *proc; |
| 136 | int remove_ownqueue = 0; | ||
| 136 | 137 | ||
| 137 | /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each | 138 | /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each |
| 138 | lkb before dealing with it. We need to check this | 139 | 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 | wake_up_interruptible(&proc->wait); | 172 | wake_up_interruptible(&proc->wait); |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 175 | /* noqueue requests that fail may need to be removed from the | ||
| 176 | proc's locks list, there should be a better way of detecting | ||
| 177 | this situation than checking all these things... */ | ||
| 178 | |||
| 179 | if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV && | ||
| 180 | ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue)) | ||
| 181 | remove_ownqueue = 1; | ||
| 182 | |||
| 174 | /* We want to copy the lvb to userspace when the completion | 183 | /* We want to copy the lvb to userspace when the completion |
| 175 | ast is read if the status is 0, the lock has an lvb and | 184 | ast is read if the status is 0, the lock has an lvb and |
| 176 | lvb_ops says we should. We could probably have set_lvb_lock() | 185 | 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 | ua->update_user_lvb = 0; | 194 | ua->update_user_lvb = 0; |
| 186 | 195 | ||
| 187 | spin_unlock(&proc->asts_spin); | 196 | spin_unlock(&proc->asts_spin); |
| 197 | |||
| 198 | if (remove_ownqueue) { | ||
| 199 | spin_lock(&ua->proc->locks_spin); | ||
| 200 | list_del_init(&lkb->lkb_ownqueue); | ||
| 201 | spin_unlock(&ua->proc->locks_spin); | ||
| 202 | dlm_put_lkb(lkb); | ||
| 203 | } | ||
| 188 | out: | 204 | out: |
| 189 | mutex_unlock(&ls->ls_clear_proc_locks); | 205 | mutex_unlock(&ls->ls_clear_proc_locks); |
| 190 | } | 206 | } |
