aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2006-07-18 12:24:04 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-07-20 00:11:15 -0400
commit34e22bed19013c77f942083e25cfc7adf6c71a8f (patch)
tree18c44bb1e3e3d40fc04f61020497f935a97df576 /fs/dlm
parent3b4a0a74949cf4f87f7ca84cc0457eb5687b2923 (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>
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/lock.c7
-rw-r--r--fs/dlm/user.c16
2 files changed, 20 insertions, 3 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 82e1ac25184..22744321816 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 1f05960a916..fd19caf9af9 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}