Showing error 1340

User: Jiri Slaby
Error type: Leaving function in locked state
Error type description: Some lock is not unlocked on all paths of a function, so it is leaked
File location: fs/dlm/ast.c
Line in file: 167
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2012-05-21 20:30:05 UTC


Source:

  1/******************************************************************************
  2*******************************************************************************
  3**
  4**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
  5**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
  6**
  7**  This copyrighted material is made available to anyone wishing to use,
  8**  modify, copy, or redistribute it subject to the terms and conditions
  9**  of the GNU General Public License v.2.
 10**
 11*******************************************************************************
 12******************************************************************************/
 13
 14#include "dlm_internal.h"
 15#include "lock.h"
 16#include "user.h"
 17#include "ast.h"
 18
 19#define WAKE_ASTS  0
 20
 21static struct list_head                ast_queue;
 22static spinlock_t                ast_queue_lock;
 23static struct task_struct *        astd_task;
 24static unsigned long                astd_wakeflags;
 25static struct mutex                astd_running;
 26
 27
 28void dlm_del_ast(struct dlm_lkb *lkb)
 29{
 30        spin_lock(&ast_queue_lock);
 31        if (lkb->lkb_ast_type & (AST_COMP | AST_BAST))
 32                list_del(&lkb->lkb_astqueue);
 33        spin_unlock(&ast_queue_lock);
 34}
 35
 36void dlm_add_ast(struct dlm_lkb *lkb, int type)
 37{
 38        if (lkb->lkb_flags & DLM_IFL_USER) {
 39                dlm_user_add_ast(lkb, type);
 40                return;
 41        }
 42
 43        spin_lock(&ast_queue_lock);
 44        if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
 45                kref_get(&lkb->lkb_ref);
 46                list_add_tail(&lkb->lkb_astqueue, &ast_queue);
 47        }
 48        lkb->lkb_ast_type |= type;
 49        spin_unlock(&ast_queue_lock);
 50
 51        set_bit(WAKE_ASTS, &astd_wakeflags);
 52        wake_up_process(astd_task);
 53}
 54
 55static void process_asts(void)
 56{
 57        struct dlm_ls *ls = NULL;
 58        struct dlm_rsb *r = NULL;
 59        struct dlm_lkb *lkb;
 60        void (*cast) (void *astparam);
 61        void (*bast) (void *astparam, int mode);
 62        int type = 0, found, bmode;
 63
 64        for (;;) {
 65                found = 0;
 66                spin_lock(&ast_queue_lock);
 67                list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
 68                        r = lkb->lkb_resource;
 69                        ls = r->res_ls;
 70
 71                        if (dlm_locking_stopped(ls))
 72                                continue;
 73
 74                        list_del(&lkb->lkb_astqueue);
 75                        type = lkb->lkb_ast_type;
 76                        lkb->lkb_ast_type = 0;
 77                        found = 1;
 78                        break;
 79                }
 80                spin_unlock(&ast_queue_lock);
 81
 82                if (!found)
 83                        break;
 84
 85                cast = lkb->lkb_astfn;
 86                bast = lkb->lkb_bastfn;
 87                bmode = lkb->lkb_bastmode;
 88
 89                if ((type & AST_COMP) && cast)
 90                        cast(lkb->lkb_astparam);
 91
 92                /* FIXME: Is it safe to look at lkb_grmode here
 93                   without doing a lock_rsb() ?
 94                   Look at other checks in v1 to avoid basts. */
 95
 96                if ((type & AST_BAST) && bast)
 97                        if (!dlm_modes_compat(lkb->lkb_grmode, bmode))
 98                                bast(lkb->lkb_astparam, bmode);
 99
100                /* this removes the reference added by dlm_add_ast
101                   and may result in the lkb being freed */
102                dlm_put_lkb(lkb);
103
104                schedule();
105        }
106}
107
108static inline int no_asts(void)
109{
110        int ret;
111
112        spin_lock(&ast_queue_lock);
113        ret = list_empty(&ast_queue);
114        spin_unlock(&ast_queue_lock);
115        return ret;
116}
117
118static int dlm_astd(void *data)
119{
120        while (!kthread_should_stop()) {
121                set_current_state(TASK_INTERRUPTIBLE);
122                if (!test_bit(WAKE_ASTS, &astd_wakeflags))
123                        schedule();
124                set_current_state(TASK_RUNNING);
125
126                mutex_lock(&astd_running);
127                if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
128                        process_asts();
129                mutex_unlock(&astd_running);
130        }
131        return 0;
132}
133
134void dlm_astd_wake(void)
135{
136        if (!no_asts()) {
137                set_bit(WAKE_ASTS, &astd_wakeflags);
138                wake_up_process(astd_task);
139        }
140}
141
142int dlm_astd_start(void)
143{
144        struct task_struct *p;
145        int error = 0;
146
147        INIT_LIST_HEAD(&ast_queue);
148        spin_lock_init(&ast_queue_lock);
149        mutex_init(&astd_running);
150
151        p = kthread_run(dlm_astd, NULL, "dlm_astd");
152        if (IS_ERR(p))
153                error = PTR_ERR(p);
154        else
155                astd_task = p;
156        return error;
157}
158
159void dlm_astd_stop(void)
160{
161        kthread_stop(astd_task);
162}
163
164void dlm_astd_suspend(void)
165{
166        mutex_lock(&astd_running);
167}
168
169void dlm_astd_resume(void)
170{
171        mutex_unlock(&astd_running);
172}
173