Showing error 1517

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: net/llc/llc_proc.c
Line in file: 54
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2012-05-21 20:30:05 UTC


Source:

  1/*
  2 * proc_llc.c - proc interface for LLC
  3 *
  4 * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
  5 *                 2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  6 *
  7 * This program can be redistributed or modified under the terms of the
  8 * GNU General Public License as published by the Free Software Foundation.
  9 * This program is distributed without any warranty or implied warranty
 10 * of merchantability or fitness for a particular purpose.
 11 *
 12 * See the GNU General Public License for more details.
 13 */
 14
 15#include <linux/init.h>
 16#include <linux/kernel.h>
 17#include <linux/proc_fs.h>
 18#include <linux/errno.h>
 19#include <linux/seq_file.h>
 20#include <net/net_namespace.h>
 21#include <net/sock.h>
 22#include <net/llc.h>
 23#include <net/llc_c_ac.h>
 24#include <net/llc_c_ev.h>
 25#include <net/llc_c_st.h>
 26#include <net/llc_conn.h>
 27
 28static void llc_ui_format_mac(struct seq_file *seq, u8 *addr)
 29{
 30        DECLARE_MAC_BUF(mac);
 31        seq_printf(seq, "%s", print_mac(mac, addr));
 32}
 33
 34static struct sock *llc_get_sk_idx(loff_t pos)
 35{
 36        struct list_head *sap_entry;
 37        struct llc_sap *sap;
 38        struct hlist_node *node;
 39        struct sock *sk = NULL;
 40
 41        list_for_each(sap_entry, &llc_sap_list) {
 42                sap = list_entry(sap_entry, struct llc_sap, node);
 43
 44                read_lock_bh(&sap->sk_list.lock);
 45                sk_for_each(sk, node, &sap->sk_list.list) {
 46                        if (!pos)
 47                                goto found;
 48                        --pos;
 49                }
 50                read_unlock_bh(&sap->sk_list.lock);
 51        }
 52        sk = NULL;
 53found:
 54        return sk;
 55}
 56
 57static void *llc_seq_start(struct seq_file *seq, loff_t *pos)
 58{
 59        loff_t l = *pos;
 60
 61        read_lock_bh(&llc_sap_list_lock);
 62        return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN;
 63}
 64
 65static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 66{
 67        struct sock* sk, *next;
 68        struct llc_sock *llc;
 69        struct llc_sap *sap;
 70
 71        ++*pos;
 72        if (v == SEQ_START_TOKEN) {
 73                sk = llc_get_sk_idx(0);
 74                goto out;
 75        }
 76        sk = v;
 77        next = sk_next(sk);
 78        if (next) {
 79                sk = next;
 80                goto out;
 81        }
 82        llc = llc_sk(sk);
 83        sap = llc->sap;
 84        read_unlock_bh(&sap->sk_list.lock);
 85        sk = NULL;
 86        for (;;) {
 87                if (sap->node.next == &llc_sap_list)
 88                        break;
 89                sap = list_entry(sap->node.next, struct llc_sap, node);
 90                read_lock_bh(&sap->sk_list.lock);
 91                if (!hlist_empty(&sap->sk_list.list)) {
 92                        sk = sk_head(&sap->sk_list.list);
 93                        break;
 94                }
 95                read_unlock_bh(&sap->sk_list.lock);
 96        }
 97out:
 98        return sk;
 99}
100
101static void llc_seq_stop(struct seq_file *seq, void *v)
102{
103        if (v && v != SEQ_START_TOKEN) {
104                struct sock *sk = v;
105                struct llc_sock *llc = llc_sk(sk);
106                struct llc_sap *sap = llc->sap;
107
108                read_unlock_bh(&sap->sk_list.lock);
109        }
110        read_unlock_bh(&llc_sap_list_lock);
111}
112
113static int llc_seq_socket_show(struct seq_file *seq, void *v)
114{
115        struct sock* sk;
116        struct llc_sock *llc;
117
118        if (v == SEQ_START_TOKEN) {
119                seq_puts(seq, "SKt Mc local_mac_sap        remote_mac_sap   "
120                              "    tx_queue rx_queue st uid link\n");
121                goto out;
122        }
123        sk = v;
124        llc = llc_sk(sk);
125
126        /* FIXME: check if the address is multicast */
127        seq_printf(seq, "%2X  %2X ", sk->sk_type, 0);
128
129        if (llc->dev)
130                llc_ui_format_mac(seq, llc->dev->dev_addr);
131        else {
132                u8 addr[6] = {0,0,0,0,0,0};
133                llc_ui_format_mac(seq, addr);
134        }
135        seq_printf(seq, "@%02X ", llc->sap->laddr.lsap);
136        llc_ui_format_mac(seq, llc->daddr.mac);
137        seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
138                   atomic_read(&sk->sk_wmem_alloc),
139                   atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq,
140                   sk->sk_state,
141                   sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
142                   llc->link);
143out:
144        return 0;
145}
146
147static char *llc_conn_state_names[] = {
148        [LLC_CONN_STATE_ADM] =        "adm",
149        [LLC_CONN_STATE_SETUP] =      "setup",
150        [LLC_CONN_STATE_NORMAL] =     "normal",
151        [LLC_CONN_STATE_BUSY] =       "busy",
152        [LLC_CONN_STATE_REJ] =        "rej",
153        [LLC_CONN_STATE_AWAIT] =      "await",
154        [LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
155        [LLC_CONN_STATE_AWAIT_REJ] =  "await_rej",
156        [LLC_CONN_STATE_D_CONN]        =     "d_conn",
157        [LLC_CONN_STATE_RESET] =      "reset",
158        [LLC_CONN_STATE_ERROR] =      "error",
159        [LLC_CONN_STATE_TEMP] =       "temp",
160};
161
162static int llc_seq_core_show(struct seq_file *seq, void *v)
163{
164        struct sock* sk;
165        struct llc_sock *llc;
166
167        if (v == SEQ_START_TOKEN) {
168                seq_puts(seq, "Connection list:\n"
169                              "dsap state      retr txw rxw pf ff sf df rs cs "
170                              "tack tpfc trs tbs blog busr\n");
171                goto out;
172        }
173        sk = v;
174        llc = llc_sk(sk);
175
176        seq_printf(seq, " %02X  %-10s %3d  %3d %3d %2d %2d %2d %2d %2d %2d "
177                        "%4d %4d %3d %3d %4d %4d\n",
178                   llc->daddr.lsap, llc_conn_state_names[llc->state],
179                   llc->retry_count, llc->k, llc->rw, llc->p_flag, llc->f_flag,
180                   llc->s_flag, llc->data_flag, llc->remote_busy_flag,
181                   llc->cause_flag, timer_pending(&llc->ack_timer.timer),
182                   timer_pending(&llc->pf_cycle_timer.timer),
183                   timer_pending(&llc->rej_sent_timer.timer),
184                   timer_pending(&llc->busy_state_timer.timer),
185                   !!sk->sk_backlog.tail, !!sock_owned_by_user(sk));
186out:
187        return 0;
188}
189
190static const struct seq_operations llc_seq_socket_ops = {
191        .start  = llc_seq_start,
192        .next   = llc_seq_next,
193        .stop   = llc_seq_stop,
194        .show   = llc_seq_socket_show,
195};
196
197static const struct seq_operations llc_seq_core_ops = {
198        .start  = llc_seq_start,
199        .next   = llc_seq_next,
200        .stop   = llc_seq_stop,
201        .show   = llc_seq_core_show,
202};
203
204static int llc_seq_socket_open(struct inode *inode, struct file *file)
205{
206        return seq_open(file, &llc_seq_socket_ops);
207}
208
209static int llc_seq_core_open(struct inode *inode, struct file *file)
210{
211        return seq_open(file, &llc_seq_core_ops);
212}
213
214static const struct file_operations llc_seq_socket_fops = {
215        .owner                = THIS_MODULE,
216        .open                = llc_seq_socket_open,
217        .read                = seq_read,
218        .llseek                = seq_lseek,
219        .release        = seq_release,
220};
221
222static const struct file_operations llc_seq_core_fops = {
223        .owner                = THIS_MODULE,
224        .open                = llc_seq_core_open,
225        .read                = seq_read,
226        .llseek                = seq_lseek,
227        .release        = seq_release,
228};
229
230static struct proc_dir_entry *llc_proc_dir;
231
232int __init llc_proc_init(void)
233{
234        int rc = -ENOMEM;
235        struct proc_dir_entry *p;
236
237        llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
238        if (!llc_proc_dir)
239                goto out;
240        llc_proc_dir->owner = THIS_MODULE;
241
242        p = proc_create("socket", S_IRUGO, llc_proc_dir, &llc_seq_socket_fops);
243        if (!p)
244                goto out_socket;
245
246        p = proc_create("core", S_IRUGO, llc_proc_dir, &llc_seq_core_fops);
247        if (!p)
248                goto out_core;
249
250        rc = 0;
251out:
252        return rc;
253out_core:
254        remove_proc_entry("socket", llc_proc_dir);
255out_socket:
256        remove_proc_entry("llc", init_net.proc_net);
257        goto out;
258}
259
260void llc_proc_exit(void)
261{
262        remove_proc_entry("socket", llc_proc_dir);
263        remove_proc_entry("core", llc_proc_dir);
264        remove_proc_entry("llc", init_net.proc_net);
265}