Showing error 1335

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


Source:

  1/* /proc interface for AFS
  2 *
  3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
  4 * Written by David Howells (dhowells@redhat.com)
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version
  9 * 2 of the License, or (at your option) any later version.
 10 */
 11
 12#include <linux/slab.h>
 13#include <linux/module.h>
 14#include <linux/proc_fs.h>
 15#include <linux/seq_file.h>
 16#include <linux/sched.h>
 17#include <asm/uaccess.h>
 18#include "internal.h"
 19
 20static struct proc_dir_entry *proc_afs;
 21
 22
 23static int afs_proc_cells_open(struct inode *inode, struct file *file);
 24static void *afs_proc_cells_start(struct seq_file *p, loff_t *pos);
 25static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos);
 26static void afs_proc_cells_stop(struct seq_file *p, void *v);
 27static int afs_proc_cells_show(struct seq_file *m, void *v);
 28static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
 29                                    size_t size, loff_t *_pos);
 30
 31static struct seq_operations afs_proc_cells_ops = {
 32        .start        = afs_proc_cells_start,
 33        .next        = afs_proc_cells_next,
 34        .stop        = afs_proc_cells_stop,
 35        .show        = afs_proc_cells_show,
 36};
 37
 38static const struct file_operations afs_proc_cells_fops = {
 39        .open                = afs_proc_cells_open,
 40        .read                = seq_read,
 41        .write                = afs_proc_cells_write,
 42        .llseek                = seq_lseek,
 43        .release        = seq_release,
 44        .owner                = THIS_MODULE,
 45};
 46
 47static int afs_proc_rootcell_open(struct inode *inode, struct file *file);
 48static int afs_proc_rootcell_release(struct inode *inode, struct file *file);
 49static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
 50                                      size_t size, loff_t *_pos);
 51static ssize_t afs_proc_rootcell_write(struct file *file,
 52                                       const char __user *buf,
 53                                       size_t size, loff_t *_pos);
 54
 55static const struct file_operations afs_proc_rootcell_fops = {
 56        .open                = afs_proc_rootcell_open,
 57        .read                = afs_proc_rootcell_read,
 58        .write                = afs_proc_rootcell_write,
 59        .llseek                = no_llseek,
 60        .release        = afs_proc_rootcell_release,
 61        .owner                = THIS_MODULE,
 62};
 63
 64static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
 65static int afs_proc_cell_volumes_release(struct inode *inode,
 66                                         struct file *file);
 67static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
 68static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
 69                                        loff_t *pos);
 70static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v);
 71static int afs_proc_cell_volumes_show(struct seq_file *m, void *v);
 72
 73static struct seq_operations afs_proc_cell_volumes_ops = {
 74        .start        = afs_proc_cell_volumes_start,
 75        .next        = afs_proc_cell_volumes_next,
 76        .stop        = afs_proc_cell_volumes_stop,
 77        .show        = afs_proc_cell_volumes_show,
 78};
 79
 80static const struct file_operations afs_proc_cell_volumes_fops = {
 81        .open                = afs_proc_cell_volumes_open,
 82        .read                = seq_read,
 83        .llseek                = seq_lseek,
 84        .release        = afs_proc_cell_volumes_release,
 85        .owner                = THIS_MODULE,
 86};
 87
 88static int afs_proc_cell_vlservers_open(struct inode *inode,
 89                                        struct file *file);
 90static int afs_proc_cell_vlservers_release(struct inode *inode,
 91                                           struct file *file);
 92static void *afs_proc_cell_vlservers_start(struct seq_file *p, loff_t *pos);
 93static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
 94                                          loff_t *pos);
 95static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v);
 96static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v);
 97
 98static struct seq_operations afs_proc_cell_vlservers_ops = {
 99        .start        = afs_proc_cell_vlservers_start,
100        .next        = afs_proc_cell_vlservers_next,
101        .stop        = afs_proc_cell_vlservers_stop,
102        .show        = afs_proc_cell_vlservers_show,
103};
104
105static const struct file_operations afs_proc_cell_vlservers_fops = {
106        .open                = afs_proc_cell_vlservers_open,
107        .read                = seq_read,
108        .llseek                = seq_lseek,
109        .release        = afs_proc_cell_vlservers_release,
110        .owner                = THIS_MODULE,
111};
112
113static int afs_proc_cell_servers_open(struct inode *inode, struct file *file);
114static int afs_proc_cell_servers_release(struct inode *inode,
115                                         struct file *file);
116static void *afs_proc_cell_servers_start(struct seq_file *p, loff_t *pos);
117static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
118                                        loff_t *pos);
119static void afs_proc_cell_servers_stop(struct seq_file *p, void *v);
120static int afs_proc_cell_servers_show(struct seq_file *m, void *v);
121
122static struct seq_operations afs_proc_cell_servers_ops = {
123        .start        = afs_proc_cell_servers_start,
124        .next        = afs_proc_cell_servers_next,
125        .stop        = afs_proc_cell_servers_stop,
126        .show        = afs_proc_cell_servers_show,
127};
128
129static const struct file_operations afs_proc_cell_servers_fops = {
130        .open                = afs_proc_cell_servers_open,
131        .read                = seq_read,
132        .llseek                = seq_lseek,
133        .release        = afs_proc_cell_servers_release,
134        .owner                = THIS_MODULE,
135};
136
137/*
138 * initialise the /proc/fs/afs/ directory
139 */
140int afs_proc_init(void)
141{
142        struct proc_dir_entry *p;
143
144        _enter("");
145
146        proc_afs = proc_mkdir("fs/afs", NULL);
147        if (!proc_afs)
148                goto error_dir;
149        proc_afs->owner = THIS_MODULE;
150
151        p = proc_create("cells", 0, proc_afs, &afs_proc_cells_fops);
152        if (!p)
153                goto error_cells;
154
155        p = proc_create("rootcell", 0, proc_afs, &afs_proc_rootcell_fops);
156        if (!p)
157                goto error_rootcell;
158
159        _leave(" = 0");
160        return 0;
161
162error_rootcell:
163         remove_proc_entry("cells", proc_afs);
164error_cells:
165        remove_proc_entry("fs/afs", NULL);
166error_dir:
167        _leave(" = -ENOMEM");
168        return -ENOMEM;
169}
170
171/*
172 * clean up the /proc/fs/afs/ directory
173 */
174void afs_proc_cleanup(void)
175{
176        remove_proc_entry("rootcell", proc_afs);
177        remove_proc_entry("cells", proc_afs);
178        remove_proc_entry("fs/afs", NULL);
179}
180
181/*
182 * open "/proc/fs/afs/cells" which provides a summary of extant cells
183 */
184static int afs_proc_cells_open(struct inode *inode, struct file *file)
185{
186        struct seq_file *m;
187        int ret;
188
189        ret = seq_open(file, &afs_proc_cells_ops);
190        if (ret < 0)
191                return ret;
192
193        m = file->private_data;
194        m->private = PDE(inode)->data;
195
196        return 0;
197}
198
199/*
200 * set up the iterator to start reading from the cells list and return the
201 * first item
202 */
203static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
204{
205        /* lock the list against modification */
206        down_read(&afs_proc_cells_sem);
207        return seq_list_start_head(&afs_proc_cells, *_pos);
208}
209
210/*
211 * move to next cell in cells list
212 */
213static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos)
214{
215        return seq_list_next(v, &afs_proc_cells, pos);
216}
217
218/*
219 * clean up after reading from the cells list
220 */
221static void afs_proc_cells_stop(struct seq_file *p, void *v)
222{
223        up_read(&afs_proc_cells_sem);
224}
225
226/*
227 * display a header line followed by a load of cell lines
228 */
229static int afs_proc_cells_show(struct seq_file *m, void *v)
230{
231        struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
232
233        if (v == &afs_proc_cells) {
234                /* display header on line 1 */
235                seq_puts(m, "USE NAME\n");
236                return 0;
237        }
238
239        /* display one cell per line on subsequent lines */
240        seq_printf(m, "%3d %s\n",
241                   atomic_read(&cell->usage), cell->name);
242        return 0;
243}
244
245/*
246 * handle writes to /proc/fs/afs/cells
247 * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]"
248 */
249static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
250                                    size_t size, loff_t *_pos)
251{
252        char *kbuf, *name, *args;
253        int ret;
254
255        /* start by dragging the command into memory */
256        if (size <= 1 || size >= PAGE_SIZE)
257                return -EINVAL;
258
259        kbuf = kmalloc(size + 1, GFP_KERNEL);
260        if (!kbuf)
261                return -ENOMEM;
262
263        ret = -EFAULT;
264        if (copy_from_user(kbuf, buf, size) != 0)
265                goto done;
266        kbuf[size] = 0;
267
268        /* trim to first NL */
269        name = memchr(kbuf, '\n', size);
270        if (name)
271                *name = 0;
272
273        /* split into command, name and argslist */
274        name = strchr(kbuf, ' ');
275        if (!name)
276                goto inval;
277        do {
278                *name++ = 0;
279        } while(*name == ' ');
280        if (!*name)
281                goto inval;
282
283        args = strchr(name, ' ');
284        if (!args)
285                goto inval;
286        do {
287                *args++ = 0;
288        } while(*args == ' ');
289        if (!*args)
290                goto inval;
291
292        /* determine command to perform */
293        _debug("cmd=%s name=%s args=%s", kbuf, name, args);
294
295        if (strcmp(kbuf, "add") == 0) {
296                struct afs_cell *cell;
297
298                cell = afs_cell_create(name, args);
299                if (IS_ERR(cell)) {
300                        ret = PTR_ERR(cell);
301                        goto done;
302                }
303
304                afs_put_cell(cell);
305                printk("kAFS: Added new cell '%s'\n", name);
306        } else {
307                goto inval;
308        }
309
310        ret = size;
311
312done:
313        kfree(kbuf);
314        _leave(" = %d", ret);
315        return ret;
316
317inval:
318        ret = -EINVAL;
319        printk("kAFS: Invalid Command on /proc/fs/afs/cells file\n");
320        goto done;
321}
322
323/*
324 * Stubs for /proc/fs/afs/rootcell
325 */
326static int afs_proc_rootcell_open(struct inode *inode, struct file *file)
327{
328        return 0;
329}
330
331static int afs_proc_rootcell_release(struct inode *inode, struct file *file)
332{
333        return 0;
334}
335
336static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
337                                      size_t size, loff_t *_pos)
338{
339        return 0;
340}
341
342/*
343 * handle writes to /proc/fs/afs/rootcell
344 * - to initialize rootcell: echo "cell.name:192.168.231.14"
345 */
346static ssize_t afs_proc_rootcell_write(struct file *file,
347                                       const char __user *buf,
348                                       size_t size, loff_t *_pos)
349{
350        char *kbuf, *s;
351        int ret;
352
353        /* start by dragging the command into memory */
354        if (size <= 1 || size >= PAGE_SIZE)
355                return -EINVAL;
356
357        ret = -ENOMEM;
358        kbuf = kmalloc(size + 1, GFP_KERNEL);
359        if (!kbuf)
360                goto nomem;
361
362        ret = -EFAULT;
363        if (copy_from_user(kbuf, buf, size) != 0)
364                goto infault;
365        kbuf[size] = 0;
366
367        /* trim to first NL */
368        s = memchr(kbuf, '\n', size);
369        if (s)
370                *s = 0;
371
372        /* determine command to perform */
373        _debug("rootcell=%s", kbuf);
374
375        ret = afs_cell_init(kbuf);
376        if (ret >= 0)
377                ret = size;        /* consume everything, always */
378
379infault:
380        kfree(kbuf);
381nomem:
382        _leave(" = %d", ret);
383        return ret;
384}
385
386/*
387 * initialise /proc/fs/afs/<cell>/
388 */
389int afs_proc_cell_setup(struct afs_cell *cell)
390{
391        struct proc_dir_entry *p;
392
393        _enter("%p{%s}", cell, cell->name);
394
395        cell->proc_dir = proc_mkdir(cell->name, proc_afs);
396        if (!cell->proc_dir)
397                goto error_dir;
398
399        p = proc_create_data("servers", 0, cell->proc_dir,
400                             &afs_proc_cell_servers_fops, cell);
401        if (!p)
402                goto error_servers;
403
404        p = proc_create_data("vlservers", 0, cell->proc_dir,
405                             &afs_proc_cell_vlservers_fops, cell);
406        if (!p)
407                goto error_vlservers;
408
409        p = proc_create_data("volumes", 0, cell->proc_dir,
410                             &afs_proc_cell_volumes_fops, cell);
411        if (!p)
412                goto error_volumes;
413
414        _leave(" = 0");
415        return 0;
416
417error_volumes:
418        remove_proc_entry("vlservers", cell->proc_dir);
419error_vlservers:
420        remove_proc_entry("servers", cell->proc_dir);
421error_servers:
422        remove_proc_entry(cell->name, proc_afs);
423error_dir:
424        _leave(" = -ENOMEM");
425        return -ENOMEM;
426}
427
428/*
429 * remove /proc/fs/afs/<cell>/
430 */
431void afs_proc_cell_remove(struct afs_cell *cell)
432{
433        _enter("");
434
435        remove_proc_entry("volumes", cell->proc_dir);
436        remove_proc_entry("vlservers", cell->proc_dir);
437        remove_proc_entry("servers", cell->proc_dir);
438        remove_proc_entry(cell->name, proc_afs);
439
440        _leave("");
441}
442
443/*
444 * open "/proc/fs/afs/<cell>/volumes" which provides a summary of extant cells
445 */
446static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file)
447{
448        struct afs_cell *cell;
449        struct seq_file *m;
450        int ret;
451
452        cell = PDE(inode)->data;
453        if (!cell)
454                return -ENOENT;
455
456        ret = seq_open(file, &afs_proc_cell_volumes_ops);
457        if (ret < 0)
458                return ret;
459
460        m = file->private_data;
461        m->private = cell;
462
463        return 0;
464}
465
466/*
467 * close the file and release the ref to the cell
468 */
469static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file)
470{
471        return seq_release(inode, file);
472}
473
474/*
475 * set up the iterator to start reading from the cells list and return the
476 * first item
477 */
478static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
479{
480        struct afs_cell *cell = m->private;
481
482        _enter("cell=%p pos=%Ld", cell, *_pos);
483
484        /* lock the list against modification */
485        down_read(&cell->vl_sem);
486        return seq_list_start_head(&cell->vl_list, *_pos);
487}
488
489/*
490 * move to next cell in cells list
491 */
492static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
493                                        loff_t *_pos)
494{
495        struct afs_cell *cell = p->private;
496
497        _enter("cell=%p pos=%Ld", cell, *_pos);
498        return seq_list_next(v, &cell->vl_list, _pos);
499}
500
501/*
502 * clean up after reading from the cells list
503 */
504static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
505{
506        struct afs_cell *cell = p->private;
507
508        up_read(&cell->vl_sem);
509}
510
511static const char afs_vlocation_states[][4] = {
512        [AFS_VL_NEW]                        = "New",
513        [AFS_VL_CREATING]                = "Crt",
514        [AFS_VL_VALID]                        = "Val",
515        [AFS_VL_NO_VOLUME]                = "NoV",
516        [AFS_VL_UPDATING]                = "Upd",
517        [AFS_VL_VOLUME_DELETED]                = "Del",
518        [AFS_VL_UNCERTAIN]                = "Unc",
519};
520
521/*
522 * display a header line followed by a load of volume lines
523 */
524static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
525{
526        struct afs_cell *cell = m->private;
527        struct afs_vlocation *vlocation =
528                list_entry(v, struct afs_vlocation, link);
529
530        /* display header on line 1 */
531        if (v == &cell->vl_list) {
532                seq_puts(m, "USE STT VLID[0]  VLID[1]  VLID[2]  NAME\n");
533                return 0;
534        }
535
536        /* display one cell per line on subsequent lines */
537        seq_printf(m, "%3d %s %08x %08x %08x %s\n",
538                   atomic_read(&vlocation->usage),
539                   afs_vlocation_states[vlocation->state],
540                   vlocation->vldb.vid[0],
541                   vlocation->vldb.vid[1],
542                   vlocation->vldb.vid[2],
543                   vlocation->vldb.name);
544
545        return 0;
546}
547
548/*
549 * open "/proc/fs/afs/<cell>/vlservers" which provides a list of volume
550 * location server
551 */
552static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file)
553{
554        struct afs_cell *cell;
555        struct seq_file *m;
556        int ret;
557
558        cell = PDE(inode)->data;
559        if (!cell)
560                return -ENOENT;
561
562        ret = seq_open(file, &afs_proc_cell_vlservers_ops);
563        if (ret<0)
564                return ret;
565
566        m = file->private_data;
567        m->private = cell;
568
569        return 0;
570}
571
572/*
573 * close the file and release the ref to the cell
574 */
575static int afs_proc_cell_vlservers_release(struct inode *inode,
576                                           struct file *file)
577{
578        return seq_release(inode, file);
579}
580
581/*
582 * set up the iterator to start reading from the cells list and return the
583 * first item
584 */
585static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
586{
587        struct afs_cell *cell = m->private;
588        loff_t pos = *_pos;
589
590        _enter("cell=%p pos=%Ld", cell, *_pos);
591
592        /* lock the list against modification */
593        down_read(&cell->vl_sem);
594
595        /* allow for the header line */
596        if (!pos)
597                return (void *) 1;
598        pos--;
599
600        if (pos >= cell->vl_naddrs)
601                return NULL;
602
603        return &cell->vl_addrs[pos];
604}
605
606/*
607 * move to next cell in cells list
608 */
609static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
610                                          loff_t *_pos)
611{
612        struct afs_cell *cell = p->private;
613        loff_t pos;
614
615        _enter("cell=%p{nad=%u} pos=%Ld", cell, cell->vl_naddrs, *_pos);
616
617        pos = *_pos;
618        (*_pos)++;
619        if (pos >= cell->vl_naddrs)
620                return NULL;
621
622        return &cell->vl_addrs[pos];
623}
624
625/*
626 * clean up after reading from the cells list
627 */
628static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v)
629{
630        struct afs_cell *cell = p->private;
631
632        up_read(&cell->vl_sem);
633}
634
635/*
636 * display a header line followed by a load of volume lines
637 */
638static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
639{
640        struct in_addr *addr = v;
641
642        /* display header on line 1 */
643        if (v == (struct in_addr *) 1) {
644                seq_puts(m, "ADDRESS\n");
645                return 0;
646        }
647
648        /* display one cell per line on subsequent lines */
649        seq_printf(m, "%u.%u.%u.%u\n", NIPQUAD(addr->s_addr));
650        return 0;
651}
652
653/*
654 * open "/proc/fs/afs/<cell>/servers" which provides a summary of active
655 * servers
656 */
657static int afs_proc_cell_servers_open(struct inode *inode, struct file *file)
658{
659        struct afs_cell *cell;
660        struct seq_file *m;
661        int ret;
662
663        cell = PDE(inode)->data;
664        if (!cell)
665                return -ENOENT;
666
667        ret = seq_open(file, &afs_proc_cell_servers_ops);
668        if (ret < 0)
669                return ret;
670
671        m = file->private_data;
672        m->private = cell;
673        return 0;
674}
675
676/*
677 * close the file and release the ref to the cell
678 */
679static int afs_proc_cell_servers_release(struct inode *inode,
680                                         struct file *file)
681{
682        return seq_release(inode, file);
683}
684
685/*
686 * set up the iterator to start reading from the cells list and return the
687 * first item
688 */
689static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
690        __acquires(m->private->servers_lock)
691{
692        struct afs_cell *cell = m->private;
693
694        _enter("cell=%p pos=%Ld", cell, *_pos);
695
696        /* lock the list against modification */
697        read_lock(&cell->servers_lock);
698        return seq_list_start_head(&cell->servers, *_pos);
699}
700
701/*
702 * move to next cell in cells list
703 */
704static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
705                                        loff_t *_pos)
706{
707        struct afs_cell *cell = p->private;
708
709        _enter("cell=%p pos=%Ld", cell, *_pos);
710        return seq_list_next(v, &cell->servers, _pos);
711}
712
713/*
714 * clean up after reading from the cells list
715 */
716static void afs_proc_cell_servers_stop(struct seq_file *p, void *v)
717        __releases(p->private->servers_lock)
718{
719        struct afs_cell *cell = p->private;
720
721        read_unlock(&cell->servers_lock);
722}
723
724/*
725 * display a header line followed by a load of volume lines
726 */
727static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
728{
729        struct afs_cell *cell = m->private;
730        struct afs_server *server = list_entry(v, struct afs_server, link);
731        char ipaddr[20];
732
733        /* display header on line 1 */
734        if (v == &cell->servers) {
735                seq_puts(m, "USE ADDR            STATE\n");
736                return 0;
737        }
738
739        /* display one cell per line on subsequent lines */
740        sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(server->addr));
741        seq_printf(m, "%3d %-15.15s %5d\n",
742                   atomic_read(&server->usage), ipaddr, server->fs_state);
743
744        return 0;
745}