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/ipx/ipx_proc.c |
Line in file: | 240 |
Project: | Linux Kernel |
Project version: | 2.6.28 |
Tools: |
Stanse
(1.2)
Smatch (1.59) |
Entered: | 2012-03-02 21:35:17 UTC |
1/* 2 * IPX proc routines 3 * 4 * Copyright(C) Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2002 5 */ 6 7#include <linux/init.h> 8#ifdef CONFIG_PROC_FS 9#include <linux/proc_fs.h> 10#include <linux/spinlock.h> 11#include <linux/seq_file.h> 12#include <net/net_namespace.h> 13#include <net/tcp_states.h> 14#include <net/ipx.h> 15 16static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos) 17{ 18 struct ipx_interface *i; 19 20 list_for_each_entry(i, &ipx_interfaces, node) 21 if (!pos--) 22 goto out; 23 i = NULL; 24out: 25 return i; 26} 27 28static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i) 29{ 30 struct ipx_interface *rc = NULL; 31 32 if (i->node.next != &ipx_interfaces) 33 rc = list_entry(i->node.next, struct ipx_interface, node); 34 return rc; 35} 36 37static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) 38{ 39 loff_t l = *pos; 40 41 spin_lock_bh(&ipx_interfaces_lock); 42 return l ? ipx_get_interface_idx(--l) : SEQ_START_TOKEN; 43} 44 45static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) 46{ 47 struct ipx_interface *i; 48 49 ++*pos; 50 if (v == SEQ_START_TOKEN) 51 i = ipx_interfaces_head(); 52 else 53 i = ipx_interfaces_next(v); 54 return i; 55} 56 57static void ipx_seq_interface_stop(struct seq_file *seq, void *v) 58{ 59 spin_unlock_bh(&ipx_interfaces_lock); 60} 61 62static int ipx_seq_interface_show(struct seq_file *seq, void *v) 63{ 64 struct ipx_interface *i; 65 66 if (v == SEQ_START_TOKEN) { 67 seq_puts(seq, "Network Node_Address Primary Device " 68 "Frame_Type"); 69#ifdef IPX_REFCNT_DEBUG 70 seq_puts(seq, " refcnt"); 71#endif 72 seq_puts(seq, "\n"); 73 goto out; 74 } 75 76 i = v; 77 seq_printf(seq, "%08lX ", (unsigned long int)ntohl(i->if_netnum)); 78 seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", 79 i->if_node[0], i->if_node[1], i->if_node[2], 80 i->if_node[3], i->if_node[4], i->if_node[5]); 81 seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No"); 82 seq_printf(seq, "%-11s", ipx_device_name(i)); 83 seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type)); 84#ifdef IPX_REFCNT_DEBUG 85 seq_printf(seq, "%6d", atomic_read(&i->refcnt)); 86#endif 87 seq_puts(seq, "\n"); 88out: 89 return 0; 90} 91 92static struct ipx_route *ipx_routes_head(void) 93{ 94 struct ipx_route *rc = NULL; 95 96 if (!list_empty(&ipx_routes)) 97 rc = list_entry(ipx_routes.next, struct ipx_route, node); 98 return rc; 99} 100 101static struct ipx_route *ipx_routes_next(struct ipx_route *r) 102{ 103 struct ipx_route *rc = NULL; 104 105 if (r->node.next != &ipx_routes) 106 rc = list_entry(r->node.next, struct ipx_route, node); 107 return rc; 108} 109 110static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos) 111{ 112 struct ipx_route *r; 113 114 list_for_each_entry(r, &ipx_routes, node) 115 if (!pos--) 116 goto out; 117 r = NULL; 118out: 119 return r; 120} 121 122static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) 123{ 124 loff_t l = *pos; 125 read_lock_bh(&ipx_routes_lock); 126 return l ? ipx_get_route_idx(--l) : SEQ_START_TOKEN; 127} 128 129static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) 130{ 131 struct ipx_route *r; 132 133 ++*pos; 134 if (v == SEQ_START_TOKEN) 135 r = ipx_routes_head(); 136 else 137 r = ipx_routes_next(v); 138 return r; 139} 140 141static void ipx_seq_route_stop(struct seq_file *seq, void *v) 142{ 143 read_unlock_bh(&ipx_routes_lock); 144} 145 146static int ipx_seq_route_show(struct seq_file *seq, void *v) 147{ 148 struct ipx_route *rt; 149 150 if (v == SEQ_START_TOKEN) { 151 seq_puts(seq, "Network Router_Net Router_Node\n"); 152 goto out; 153 } 154 rt = v; 155 seq_printf(seq, "%08lX ", (unsigned long int)ntohl(rt->ir_net)); 156 if (rt->ir_routed) 157 seq_printf(seq, "%08lX %02X%02X%02X%02X%02X%02X\n", 158 (long unsigned int)ntohl(rt->ir_intrfc->if_netnum), 159 rt->ir_router_node[0], rt->ir_router_node[1], 160 rt->ir_router_node[2], rt->ir_router_node[3], 161 rt->ir_router_node[4], rt->ir_router_node[5]); 162 else 163 seq_puts(seq, "Directly Connected\n"); 164out: 165 return 0; 166} 167 168static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) 169{ 170 struct sock *s = NULL; 171 struct hlist_node *node; 172 struct ipx_interface *i; 173 174 list_for_each_entry(i, &ipx_interfaces, node) { 175 spin_lock_bh(&i->if_sklist_lock); 176 sk_for_each(s, node, &i->if_sklist) { 177 if (!pos) 178 break; 179 --pos; 180 } 181 spin_unlock_bh(&i->if_sklist_lock); 182 if (!pos) { 183 if (node) 184 goto found; 185 break; 186 } 187 } 188 s = NULL; 189found: 190 return s; 191} 192 193static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos) 194{ 195 loff_t l = *pos; 196 197 spin_lock_bh(&ipx_interfaces_lock); 198 return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN; 199} 200 201static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) 202{ 203 struct sock* sk, *next; 204 struct ipx_interface *i; 205 struct ipx_sock *ipxs; 206 207 ++*pos; 208 if (v == SEQ_START_TOKEN) { 209 sk = NULL; 210 i = ipx_interfaces_head(); 211 if (!i) 212 goto out; 213 sk = sk_head(&i->if_sklist); 214 if (sk) 215 spin_lock_bh(&i->if_sklist_lock); 216 goto out; 217 } 218 sk = v; 219 next = sk_next(sk); 220 if (next) { 221 sk = next; 222 goto out; 223 } 224 ipxs = ipx_sk(sk); 225 i = ipxs->intrfc; 226 spin_unlock_bh(&i->if_sklist_lock); 227 sk = NULL; 228 for (;;) { 229 i = ipx_interfaces_next(i); 230 if (!i) 231 break; 232 spin_lock_bh(&i->if_sklist_lock); 233 if (!hlist_empty(&i->if_sklist)) { 234 sk = sk_head(&i->if_sklist); 235 break; 236 } 237 spin_unlock_bh(&i->if_sklist_lock); 238 } 239out: 240 return sk; 241} 242 243static int ipx_seq_socket_show(struct seq_file *seq, void *v) 244{ 245 struct sock *s; 246 struct ipx_sock *ipxs; 247 248 if (v == SEQ_START_TOKEN) { 249#ifdef CONFIG_IPX_INTERN 250 seq_puts(seq, "Local_Address " 251 "Remote_Address Tx_Queue " 252 "Rx_Queue State Uid\n"); 253#else 254 seq_puts(seq, "Local_Address Remote_Address " 255 "Tx_Queue Rx_Queue State Uid\n"); 256#endif 257 goto out; 258 } 259 260 s = v; 261 ipxs = ipx_sk(s); 262#ifdef CONFIG_IPX_INTERN 263 seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", 264 (unsigned long)ntohl(ipxs->intrfc->if_netnum), 265 ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3], 266 ipxs->node[4], ipxs->node[5], ntohs(ipxs->port)); 267#else 268 seq_printf(seq, "%08lX:%04X ", (unsigned long) ntohl(ipxs->intrfc->if_netnum), 269 ntohs(ipxs->port)); 270#endif /* CONFIG_IPX_INTERN */ 271 if (s->sk_state != TCP_ESTABLISHED) 272 seq_printf(seq, "%-28s", "Not_Connected"); 273 else { 274 seq_printf(seq, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", 275 (unsigned long)ntohl(ipxs->dest_addr.net), 276 ipxs->dest_addr.node[0], ipxs->dest_addr.node[1], 277 ipxs->dest_addr.node[2], ipxs->dest_addr.node[3], 278 ipxs->dest_addr.node[4], ipxs->dest_addr.node[5], 279 ntohs(ipxs->dest_addr.sock)); 280 } 281 282 seq_printf(seq, "%08X %08X %02X %03d\n", 283 atomic_read(&s->sk_wmem_alloc), 284 atomic_read(&s->sk_rmem_alloc), 285 s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); 286out: 287 return 0; 288} 289 290static const struct seq_operations ipx_seq_interface_ops = { 291 .start = ipx_seq_interface_start, 292 .next = ipx_seq_interface_next, 293 .stop = ipx_seq_interface_stop, 294 .show = ipx_seq_interface_show, 295}; 296 297static const struct seq_operations ipx_seq_route_ops = { 298 .start = ipx_seq_route_start, 299 .next = ipx_seq_route_next, 300 .stop = ipx_seq_route_stop, 301 .show = ipx_seq_route_show, 302}; 303 304static const struct seq_operations ipx_seq_socket_ops = { 305 .start = ipx_seq_socket_start, 306 .next = ipx_seq_socket_next, 307 .stop = ipx_seq_interface_stop, 308 .show = ipx_seq_socket_show, 309}; 310 311static int ipx_seq_route_open(struct inode *inode, struct file *file) 312{ 313 return seq_open(file, &ipx_seq_route_ops); 314} 315 316static int ipx_seq_interface_open(struct inode *inode, struct file *file) 317{ 318 return seq_open(file, &ipx_seq_interface_ops); 319} 320 321static int ipx_seq_socket_open(struct inode *inode, struct file *file) 322{ 323 return seq_open(file, &ipx_seq_socket_ops); 324} 325 326static const struct file_operations ipx_seq_interface_fops = { 327 .owner = THIS_MODULE, 328 .open = ipx_seq_interface_open, 329 .read = seq_read, 330 .llseek = seq_lseek, 331 .release = seq_release, 332}; 333 334static const struct file_operations ipx_seq_route_fops = { 335 .owner = THIS_MODULE, 336 .open = ipx_seq_route_open, 337 .read = seq_read, 338 .llseek = seq_lseek, 339 .release = seq_release, 340}; 341 342static const struct file_operations ipx_seq_socket_fops = { 343 .owner = THIS_MODULE, 344 .open = ipx_seq_socket_open, 345 .read = seq_read, 346 .llseek = seq_lseek, 347 .release = seq_release, 348}; 349 350static struct proc_dir_entry *ipx_proc_dir; 351 352int __init ipx_proc_init(void) 353{ 354 struct proc_dir_entry *p; 355 int rc = -ENOMEM; 356 357 ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net); 358 359 if (!ipx_proc_dir) 360 goto out; 361 p = proc_create("interface", S_IRUGO, 362 ipx_proc_dir, &ipx_seq_interface_fops); 363 if (!p) 364 goto out_interface; 365 366 p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops); 367 if (!p) 368 goto out_route; 369 370 p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops); 371 if (!p) 372 goto out_socket; 373 374 rc = 0; 375out: 376 return rc; 377out_socket: 378 remove_proc_entry("route", ipx_proc_dir); 379out_route: 380 remove_proc_entry("interface", ipx_proc_dir); 381out_interface: 382 remove_proc_entry("ipx", init_net.proc_net); 383 goto out; 384} 385 386void __exit ipx_proc_exit(void) 387{ 388 remove_proc_entry("interface", ipx_proc_dir); 389 remove_proc_entry("route", ipx_proc_dir); 390 remove_proc_entry("socket", ipx_proc_dir); 391 remove_proc_entry("ipx", init_net.proc_net); 392} 393 394#else /* CONFIG_PROC_FS */ 395 396int __init ipx_proc_init(void) 397{ 398 return 0; 399} 400 401void __exit ipx_proc_exit(void) 402{ 403} 404 405#endif /* CONFIG_PROC_FS */