CTC++ Coverage Report - Execution Profile    #727/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/usb/mon/mon_main.c
Instrumentation mode: function-decision-multicondition
TER: 13 % ( 21/166)

Start/ End/    
True False - Line Source

  1 /*
  2  * The USB Monitor, inspired by Dave Harding's USBMon.
  3  *
  4  * mon_main.c: Main file, module initiation and exit, registrations, etc.
  5  *
  6  * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
  7  */
  8 
  9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/usb.h>
  12 #include <linux/debugfs.h>
  13 #include <linux/smp_lock.h>
  14 #include <linux/notifier.h>
  15 
  16 #include "usb_mon.h"
  17 #include "../core/hcd.h"
  18 
  19 static void mon_submit(struct usb_bus *ubus, struct urb *urb);
  20 static void mon_complete(struct usb_bus *ubus, struct urb *urb);
  21 static void mon_stop(struct mon_bus *mbus);
  22 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
  23 static void mon_bus_drop(struct kref *r);
  24 static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus);
  25 
  26 DECLARE_MUTEX(mon_lock);
  27 
  28 static struct dentry *mon_dir;      /* /dbg/usbmon */
  29 static LIST_HEAD(mon_buses);      /* All buses we know: struct mon_bus */
  30 
  31 /*
  32  * Link a reader into the bus.
  33  *
  34  * This must be called with mon_lock taken because of mbus->ref.
  35  */
 
- 36 void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
  37 {
  38    unsigned long flags;
  39    struct usb_bus *ubus;
  40 
    41    spin_lock_irqsave(&mbus->lock, flags);
    41   do
    41     do
- 41     do-while (0)
- 41   do-while (0)
    41   do
    41     do
- 41     do-while (0)
- 41   do-while (0)
- 41 do-while (0)
- 42    if (mbus->nreaders == 0) {
  43       ubus = mbus->u_bus;
- 44       if (ubus->monitored) {
  45          /*
  46           * Something is really broken, refuse to go on and
  47           * possibly corrupt ops pointers or worse.
  48           */
  49          printk(KERN_ERR TAG ": bus %d is already monitored\n",
  50              ubus->busnum);
    51          spin_unlock_irqrestore(&mbus->lock, flags);
    51       do
    51         do
- 51         do-while (0)
- 51       do-while (0)
- 51     do-while (0)
 - 52          return;
  53       }
  54       ubus->monitored = 1;
  55    }
  56    mbus->nreaders++;
  57    list_add_tail(&r->r_link, &mbus->r_list);
    58    spin_unlock_irqrestore(&mbus->lock, flags);
    58   do
    58     do
- 58     do-while (0)
- 58   do-while (0)
- 58 do-while (0)
  59 
  60    kref_get(&mbus->ref);
  61 }
  62 
  63 /*
  64  * Unlink reader from the bus.
  65  *
  66  * This is called with mon_lock taken, so we can decrement mbus->ref.
  67  */
 
- 68 void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
  69 {
  70    unsigned long flags;
  71 
    72    spin_lock_irqsave(&mbus->lock, flags);
    72   do
    72     do
- 72     do-while (0)
- 72   do-while (0)
    72   do
    72     do
- 72     do-while (0)
- 72   do-while (0)
- 72 do-while (0)
  73    list_del(&r->r_link);
  74    --mbus->nreaders;
- 75    if (mbus->nreaders == 0)
  76       mon_stop(mbus);
    77    spin_unlock_irqrestore(&mbus->lock, flags);
    77   do
    77     do
- 77     do-while (0)
- 77   do-while (0)
- 77 do-while (0)
  78 
  79    kref_put(&mbus->ref, mon_bus_drop);
  80 }
  81 
  82 /*
  83  */
 
- 84 static void mon_submit(struct usb_bus *ubus, struct urb *urb)
  85 {
  86    struct mon_bus *mbus;
  87    unsigned long flags;
  88    struct list_head *pos;
  89    struct mon_reader *r;
  90 
  91    mbus = ubus->mon_bus;
- 92    if (mbus == NULL)
 - 93       goto out_unlocked;
  94 
    95    spin_lock_irqsave(&mbus->lock, flags);
    95   do
    95     do
- 95     do-while (0)
- 95   do-while (0)
    95   do
    95     do
- 95     do-while (0)
- 95   do-while (0)
- 95 do-while (0)
- 96    if (mbus->nreaders == 0)
 - 97       goto out_locked;
  98 
- 99    list_for_each (pos, &mbus->r_list) {
  100       r = list_entry(pos, struct mon_reader, r_link);
  101       r->rnf_submit(r->r_data, urb);
  102    }
  103 
    104    spin_unlock_irqrestore(&mbus->lock, flags);
    104   do
    104     do
- 104     do-while (0)
- 104   do-while (0)
- 104 do-while (0)
 - 105    return;
  106 
  107 out_locked:
    108    spin_unlock_irqrestore(&mbus->lock, flags);
    108   do
    108     do
- 108     do-while (0)
- 108   do-while (0)
- 108 do-while (0)
  109 out_unlocked:
 - 110    return;
  111 }
  112 
  113 /*
  114  */
 
- 115 static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err)
  116 {
  117    struct mon_bus *mbus;
  118 
  119    mbus = ubus->mon_bus;
- 120    if (mbus == NULL)
 - 121       goto out_unlocked;
  122 
  123    /*
  124     * XXX Capture the error code and the 'E' event.
  125     */
  126 
 - 127    return;
  128 
  129 out_unlocked:
 - 130    return;
  131 }
  132 
  133 /*
  134  */
 
- 135 static void mon_complete(struct usb_bus *ubus, struct urb *urb)
  136 {
  137    struct mon_bus *mbus;
  138    unsigned long flags;
  139    struct list_head *pos;
  140    struct mon_reader *r;
  141 
  142    mbus = ubus->mon_bus;
- 143    if (mbus == NULL) {
  144       /*
  145        * This should not happen.
  146        * At this point we do not even know the bus number...
  147        */
  148       printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n",
  149           urb->pipe);
 - 150       return;
  151    }
  152 
    153    spin_lock_irqsave(&mbus->lock, flags);
    153   do
    153     do
- 153     do-while (0)
- 153   do-while (0)
    153   do
    153     do
- 153     do-while (0)
- 153   do-while (0)
- 153 do-while (0)
- 154    list_for_each (pos, &mbus->r_list) {
  155       r = list_entry(pos, struct mon_reader, r_link);
  156       r->rnf_complete(r->r_data, urb);
  157    }
    158    spin_unlock_irqrestore(&mbus->lock, flags);
    158   do
    158     do
- 158     do-while (0)
- 158   do-while (0)
- 158 do-while (0)
  159 }
  160 
  161 /* int (*unlink_urb) (struct urb *urb, int status); */
  162 
  163 /*
  164  * Stop monitoring.
  165  * Obviously this must be well locked, so no need to play with mb's.
  166  */
 
- 167 static void mon_stop(struct mon_bus *mbus)
  168 {
  169    struct usb_bus *ubus = mbus->u_bus;
  170 
  171    /*
  172     * A stop can be called for a dissolved mon_bus in case of
  173     * a reader staying across an rmmod foo_hcd.
  174     */
- 175    if (ubus != NULL) {
  176       ubus->monitored = 0;
  177       mb();
  178    }
  179 }
  180 
  181 /*
  182  * Add a USB bus (usually by a modprobe foo-hcd)
  183  *
  184  * This does not return an error code because the core cannot care less
  185  * if monitoring is not established.
  186  */
 
24 24   187 static void mon_bus_add(struct usb_bus *ubus)
  188 {
  189    mon_bus_init(mon_dir, ubus);
  190 }
  191 
  192 /*
  193  * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
  194  */
 
- 195 static void mon_bus_remove(struct usb_bus *ubus)
  196 {
  197    struct mon_bus *mbus = ubus->mon_bus;
  198 
  199    down(&mon_lock);
  200    list_del(&mbus->bus_link);
  201    debugfs_remove(mbus->dent_t);
  202    debugfs_remove(mbus->dent_s);
  203 
  204    mon_dissolve(mbus, ubus);
  205    kref_put(&mbus->ref, mon_bus_drop);
  206    up(&mon_lock);
  207 }
  208 
 
62   209 static int mon_notify(struct notifier_block *self, unsigned long action,
  210             void *dev)
  211 {
    212    switch (action) {
24    213    case USB_BUS_ADD:
  214       mon_bus_add(dev);
24    215       break;
 - 216    case USB_BUS_REMOVE:
  217       mon_bus_remove(dev);
  218    }
62    219    return NOTIFY_OK;
  220 }
  221 
  222 static struct notifier_block mon_nb = {
  223    .notifier_call =    mon_notify,
  224 };
  225 
  226 /*
  227  * Ops
  228  */
  229 static struct usb_mon_operations mon_ops_0 = {
  230    .urb_submit =   mon_submit,
  231    .urb_submit_error = mon_submit_error,
  232    .urb_complete =   mon_complete,
  233 };
  234 
  235 /*
  236  * Tear usb_bus and mon_bus apart.
  237  */
 
- 238 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
  239 {
  240 
  241    /*
  242     * Never happens, but...
  243     */
- 244    if (ubus->monitored) {
  245       printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n",
  246           ubus->busnum);
  247       ubus->monitored = 0;
  248       mb();
  249    }
  250 
  251    ubus->mon_bus = NULL;
  252    mbus->u_bus = NULL;
  253    mb();
  254    // usb_bus_put(ubus);
  255 }
  256 
  257 /*
  258  */
 
- 259 static void mon_bus_drop(struct kref *r)
  260 {
  261    struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
  262    kfree(mbus);
  263 }
  264 
  265 /*
  266  * Initialize a bus for us:
  267  *  - allocate mon_bus
  268  *  - refcount USB bus struct
  269  *  - link
  270  */
 
24   271 static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
  272 {
  273    struct dentry *d;
  274    struct mon_bus *mbus;
  275    enum { NAMESZ = 10 };
  276    char name[NAMESZ];
  277    int rc;
  278 
24 - 279    if ((mbus = kmalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
 - 280       goto err_alloc;
  281    memset(mbus, 0, sizeof(struct mon_bus));
  282    kref_init(&mbus->ref);
    283    spin_lock_init(&mbus->lock);
24 - 283 do-while (0)
  284    INIT_LIST_HEAD(&mbus->r_list);
  285 
  286    /*
  287     * This usb_bus_get here is superfluous, because we receive
  288     * a notification if usb_bus is about to be removed.
  289     */
  290    // usb_bus_get(ubus);
  291    mbus->u_bus = ubus;
  292    ubus->mon_bus = mbus;
  293 
  294    rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
24 - 295    if (rc <= 0 || rc >= NAMESZ)
 - 295   T || _
 - 295   F || T
 24   295   F || F
 - 296       goto err_print_t;
  297    d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text);
24 - 298    if (d == NULL)
 - 299       goto err_create_t;
  300    mbus->dent_t = d;
  301 
  302    rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
24 - 303    if (rc <= 0 || rc >= NAMESZ)
 - 303   T || _
 - 303   F || T
 24   303   F || F
 - 304       goto err_print_s;
  305    d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat);
24 - 306    if (d == NULL)
 - 307       goto err_create_s;
  308    mbus->dent_s = d;
  309 
  310    down(&mon_lock);
  311    list_add_tail(&mbus->bus_link, &mon_buses);
  312    up(&mon_lock);
24    313    return;
  314 
  315 err_create_s:
  316 err_print_s:
  317    debugfs_remove(mbus->dent_t);
  318 err_create_t:
  319 err_print_t:
  320    kfree(mbus);
  321 err_alloc:
 - 322    return;
  323 }
  324 
 
  325 static int __init mon_init(void)
  326 {
  327    struct usb_bus *ubus;
  328    struct dentry *mondir;
  329 
  330    mondir = debugfs_create_dir("usbmon", NULL);
- 331    if (IS_ERR(mondir)) {
  332       printk(KERN_NOTICE TAG ": debugfs is not available\n");
 - 333       return -ENODEV;
  334    }
- 335    if (mondir == NULL) {
  336       printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
 - 337       return -ENODEV;
  338    }
  339    mon_dir = mondir;
  340 
- 341    if (usb_mon_register(&mon_ops_0) != 0) {
  342       printk(KERN_NOTICE TAG ": unable to register with the core\n");
  343       debugfs_remove(mondir);
 - 344       return -ENODEV;
  345    }
  346    // MOD_INC_USE_COUNT(which_module?);
  347 
  348    usb_register_notify(&mon_nb);
  349 
  350    down(&usb_bus_list_lock);
- 351    list_for_each_entry (ubus, &usb_bus_list, bus_list) {
  352       mon_bus_init(mondir, ubus);
  353    }
  354    up(&usb_bus_list_lock);
   355    return 0;
  356 }
  357 
 
- 358 static void __exit mon_exit(void)
  359 {
  360    struct mon_bus *mbus;
  361    struct list_head *p;
  362 
  363    usb_unregister_notify(&mon_nb);
  364    usb_mon_deregister();
  365 
  366    down(&mon_lock);
- 367    while (!list_empty(&mon_buses)) {
  368       p = mon_buses.next;
  369       mbus = list_entry(p, struct mon_bus, bus_link);
  370       list_del(p);
  371 
  372       debugfs_remove(mbus->dent_t);
  373       debugfs_remove(mbus->dent_s);
  374 
  375       /*
  376        * This never happens, because the open/close paths in
  377        * file level maintain module use counters and so rmmod fails
  378        * before reaching here. However, better be safe...
  379        */
- 380       if (mbus->nreaders) {
  381          printk(KERN_ERR TAG
  382              ": Outstanding opens (%d) on usb%d, leaking...\n",
  383              mbus->nreaders, mbus->u_bus->busnum);
  384          atomic_set(&mbus->ref.refcount, 2);   /* Force leak */
  385       }
  386 
  387       mon_dissolve(mbus, mbus->u_bus);
  388       kref_put(&mbus->ref, mon_bus_drop);
  389    }
  390    up(&mon_lock);
  391 
  392    debugfs_remove(mon_dir);
  393 }
  394 
  395 module_init(mon_init);
  396 module_exit(mon_exit);
  397 
  398 MODULE_LICENSE("GPL");
***TER 13% (21/166) of SOURCE FILE mon_main.c

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last | Top