diff options
author | Pete Zaitcev <zaitcev@redhat.com> | 2006-12-31 01:43:10 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:44:34 -0500 |
commit | 6f23ee1fefdc1f80bd8a3ab04a1c41ab2dec14c9 (patch) | |
tree | 36a5241c29333580de3e3c75e2c62edc1cdf583c /drivers/usb/mon/mon_main.c | |
parent | a8ef36bc0a5fe973bddaa54a5a07cda29e04a602 (diff) |
USB: add binary API to usbmon
This patch adds a new, "binary" API in addition to the old, text API usbmon
had before. The new API allows for less CPU use, and it allows to capture
all data from a packet where old API only captured 32 bytes at most. There
are some limitations and conditions to this, e.g. in case someone constructs
a URB with 1GB of data, it's not likely to be captured, because even the
huge buffers of the new reader are finite. Nonetheless, I expect this new
capability to capture all data for all real life scenarios.
The downside is, a special user mode application is required where cat(1)
worked before. I have sample code at http://people.redhat.com/zaitcev/linux/
and Paolo Abeni is working on patching libpcap.
This patch was initially written by Paolo and later I tweaked it, and
we had a little back-and-forth. So this is a jointly authored patch, but
I am submitting this I am responsible for the bugs.
Signed-off-by: Paolo Abeni <paolo.abeni@email.it>
Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/mon/mon_main.c')
-rw-r--r-- | drivers/usb/mon/mon_main.c | 97 |
1 files changed, 48 insertions, 49 deletions
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 394bbf2f68d4..c9739e7b35e5 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/usb.h> | 11 | #include <linux/usb.h> |
12 | #include <linux/debugfs.h> | ||
13 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
14 | #include <linux/notifier.h> | 13 | #include <linux/notifier.h> |
15 | #include <linux/mutex.h> | 14 | #include <linux/mutex.h> |
@@ -22,11 +21,10 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb); | |||
22 | static void mon_stop(struct mon_bus *mbus); | 21 | static void mon_stop(struct mon_bus *mbus); |
23 | static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); | 22 | static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); |
24 | static void mon_bus_drop(struct kref *r); | 23 | static void mon_bus_drop(struct kref *r); |
25 | static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus); | 24 | static void mon_bus_init(struct usb_bus *ubus); |
26 | 25 | ||
27 | DEFINE_MUTEX(mon_lock); | 26 | DEFINE_MUTEX(mon_lock); |
28 | 27 | ||
29 | static struct dentry *mon_dir; /* /dbg/usbmon */ | ||
30 | static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ | 28 | static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ |
31 | 29 | ||
32 | /* | 30 | /* |
@@ -200,7 +198,7 @@ static void mon_stop(struct mon_bus *mbus) | |||
200 | */ | 198 | */ |
201 | static void mon_bus_add(struct usb_bus *ubus) | 199 | static void mon_bus_add(struct usb_bus *ubus) |
202 | { | 200 | { |
203 | mon_bus_init(mon_dir, ubus); | 201 | mon_bus_init(ubus); |
204 | } | 202 | } |
205 | 203 | ||
206 | /* | 204 | /* |
@@ -212,8 +210,8 @@ static void mon_bus_remove(struct usb_bus *ubus) | |||
212 | 210 | ||
213 | mutex_lock(&mon_lock); | 211 | mutex_lock(&mon_lock); |
214 | list_del(&mbus->bus_link); | 212 | list_del(&mbus->bus_link); |
215 | debugfs_remove(mbus->dent_t); | 213 | if (mbus->text_inited) |
216 | debugfs_remove(mbus->dent_s); | 214 | mon_text_del(mbus); |
217 | 215 | ||
218 | mon_dissolve(mbus, ubus); | 216 | mon_dissolve(mbus, ubus); |
219 | kref_put(&mbus->ref, mon_bus_drop); | 217 | kref_put(&mbus->ref, mon_bus_drop); |
@@ -281,13 +279,9 @@ static void mon_bus_drop(struct kref *r) | |||
281 | * - refcount USB bus struct | 279 | * - refcount USB bus struct |
282 | * - link | 280 | * - link |
283 | */ | 281 | */ |
284 | static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) | 282 | static void mon_bus_init(struct usb_bus *ubus) |
285 | { | 283 | { |
286 | struct dentry *d; | ||
287 | struct mon_bus *mbus; | 284 | struct mon_bus *mbus; |
288 | enum { NAMESZ = 10 }; | ||
289 | char name[NAMESZ]; | ||
290 | int rc; | ||
291 | 285 | ||
292 | if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) | 286 | if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) |
293 | goto err_alloc; | 287 | goto err_alloc; |
@@ -303,57 +297,54 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) | |||
303 | ubus->mon_bus = mbus; | 297 | ubus->mon_bus = mbus; |
304 | mbus->uses_dma = ubus->uses_dma; | 298 | mbus->uses_dma = ubus->uses_dma; |
305 | 299 | ||
306 | rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); | 300 | mbus->text_inited = mon_text_add(mbus, ubus); |
307 | if (rc <= 0 || rc >= NAMESZ) | 301 | // mon_bin_add(...) |
308 | goto err_print_t; | ||
309 | d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text); | ||
310 | if (d == NULL) | ||
311 | goto err_create_t; | ||
312 | mbus->dent_t = d; | ||
313 | |||
314 | rc = snprintf(name, NAMESZ, "%ds", ubus->busnum); | ||
315 | if (rc <= 0 || rc >= NAMESZ) | ||
316 | goto err_print_s; | ||
317 | d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat); | ||
318 | if (d == NULL) | ||
319 | goto err_create_s; | ||
320 | mbus->dent_s = d; | ||
321 | 302 | ||
322 | mutex_lock(&mon_lock); | 303 | mutex_lock(&mon_lock); |
323 | list_add_tail(&mbus->bus_link, &mon_buses); | 304 | list_add_tail(&mbus->bus_link, &mon_buses); |
324 | mutex_unlock(&mon_lock); | 305 | mutex_unlock(&mon_lock); |
325 | return; | 306 | return; |
326 | 307 | ||
327 | err_create_s: | ||
328 | err_print_s: | ||
329 | debugfs_remove(mbus->dent_t); | ||
330 | err_create_t: | ||
331 | err_print_t: | ||
332 | kfree(mbus); | ||
333 | err_alloc: | 308 | err_alloc: |
334 | return; | 309 | return; |
335 | } | 310 | } |
336 | 311 | ||
312 | /* | ||
313 | * Search a USB bus by number. Notice that USB bus numbers start from one, | ||
314 | * which we may later use to identify "all" with zero. | ||
315 | * | ||
316 | * This function must be called with mon_lock held. | ||
317 | * | ||
318 | * This is obviously inefficient and may be revised in the future. | ||
319 | */ | ||
320 | struct mon_bus *mon_bus_lookup(unsigned int num) | ||
321 | { | ||
322 | struct list_head *p; | ||
323 | struct mon_bus *mbus; | ||
324 | |||
325 | list_for_each (p, &mon_buses) { | ||
326 | mbus = list_entry(p, struct mon_bus, bus_link); | ||
327 | if (mbus->u_bus->busnum == num) { | ||
328 | return mbus; | ||
329 | } | ||
330 | } | ||
331 | return NULL; | ||
332 | } | ||
333 | |||
337 | static int __init mon_init(void) | 334 | static int __init mon_init(void) |
338 | { | 335 | { |
339 | struct usb_bus *ubus; | 336 | struct usb_bus *ubus; |
340 | struct dentry *mondir; | 337 | int rc; |
341 | 338 | ||
342 | mondir = debugfs_create_dir("usbmon", NULL); | 339 | if ((rc = mon_text_init()) != 0) |
343 | if (IS_ERR(mondir)) { | 340 | goto err_text; |
344 | printk(KERN_NOTICE TAG ": debugfs is not available\n"); | 341 | if ((rc = mon_bin_init()) != 0) |
345 | return -ENODEV; | 342 | goto err_bin; |
346 | } | ||
347 | if (mondir == NULL) { | ||
348 | printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); | ||
349 | return -ENODEV; | ||
350 | } | ||
351 | mon_dir = mondir; | ||
352 | 343 | ||
353 | if (usb_mon_register(&mon_ops_0) != 0) { | 344 | if (usb_mon_register(&mon_ops_0) != 0) { |
354 | printk(KERN_NOTICE TAG ": unable to register with the core\n"); | 345 | printk(KERN_NOTICE TAG ": unable to register with the core\n"); |
355 | debugfs_remove(mondir); | 346 | rc = -ENODEV; |
356 | return -ENODEV; | 347 | goto err_reg; |
357 | } | 348 | } |
358 | // MOD_INC_USE_COUNT(which_module?); | 349 | // MOD_INC_USE_COUNT(which_module?); |
359 | 350 | ||
@@ -361,10 +352,17 @@ static int __init mon_init(void) | |||
361 | 352 | ||
362 | mutex_lock(&usb_bus_list_lock); | 353 | mutex_lock(&usb_bus_list_lock); |
363 | list_for_each_entry (ubus, &usb_bus_list, bus_list) { | 354 | list_for_each_entry (ubus, &usb_bus_list, bus_list) { |
364 | mon_bus_init(mondir, ubus); | 355 | mon_bus_init(ubus); |
365 | } | 356 | } |
366 | mutex_unlock(&usb_bus_list_lock); | 357 | mutex_unlock(&usb_bus_list_lock); |
367 | return 0; | 358 | return 0; |
359 | |||
360 | err_reg: | ||
361 | mon_bin_exit(); | ||
362 | err_bin: | ||
363 | mon_text_exit(); | ||
364 | err_text: | ||
365 | return rc; | ||
368 | } | 366 | } |
369 | 367 | ||
370 | static void __exit mon_exit(void) | 368 | static void __exit mon_exit(void) |
@@ -381,8 +379,8 @@ static void __exit mon_exit(void) | |||
381 | mbus = list_entry(p, struct mon_bus, bus_link); | 379 | mbus = list_entry(p, struct mon_bus, bus_link); |
382 | list_del(p); | 380 | list_del(p); |
383 | 381 | ||
384 | debugfs_remove(mbus->dent_t); | 382 | if (mbus->text_inited) |
385 | debugfs_remove(mbus->dent_s); | 383 | mon_text_del(mbus); |
386 | 384 | ||
387 | /* | 385 | /* |
388 | * This never happens, because the open/close paths in | 386 | * This never happens, because the open/close paths in |
@@ -401,7 +399,8 @@ static void __exit mon_exit(void) | |||
401 | } | 399 | } |
402 | mutex_unlock(&mon_lock); | 400 | mutex_unlock(&mon_lock); |
403 | 401 | ||
404 | debugfs_remove(mon_dir); | 402 | mon_text_exit(); |
403 | mon_bin_exit(); | ||
405 | } | 404 | } |
406 | 405 | ||
407 | module_init(mon_init); | 406 | module_init(mon_init); |