Re: RFC: libusual piggybacks the class mechanism

From: Greg KH
Date: Tue Oct 31 2006 - 16:23:47 EST


On Mon, Oct 16, 2006 at 04:37:22PM -0700, Pete Zaitcev wrote:
> Hi, Greg:
>
> I would like you to opine about a fix which I wrote for libusual.
> First, the patch:
>
> diff -urp -X dontdiff linux-2.6.18/drivers/usb/storage/libusual.c linux-2.6.18-ub/drivers/usb/storage/libusual.c
> --- linux-2.6.18/drivers/usb/storage/libusual.c 2006-04-10 23:26:03.000000000 -0700
> +++ linux-2.6.18-ub/drivers/usb/storage/libusual.c 2006-10-15 23:46:52.000000000 -0700
> @@ -5,6 +5,7 @@
> */
> #include <linux/kernel.h>
> #include <linux/module.h>
> +#include <linux/device.h>
> #include <linux/usb.h>
> #include <linux/usb_usual.h>
> #include <linux/vmalloc.h>
> @@ -13,6 +14,7 @@
> */
> #define USU_MOD_FL_THREAD 1 /* Thread is running */
> #define USU_MOD_FL_PRESENT 2 /* The module is loaded */
> +#define USU_MOD_FL_FAILED 3 /* The module failed to load */
>
> struct mod_status {
> unsigned long fls;
> @@ -33,8 +35,12 @@ static DECLARE_MUTEX_LOCKED(usu_init_not
> static DECLARE_COMPLETION(usu_end_notify);
> static atomic_t total_threads = ATOMIC_INIT(0);
>
> +static int usu_kick(unsigned long type);
> static int usu_probe_thread(void *arg);
>
> +static struct class *usu_class;
> +static struct class_device *usu_class_device;

Use a "struct device" instead please. class_device is going away.

> /*
> * The table.
> */
> @@ -113,16 +119,44 @@ EXPORT_SYMBOL_GPL(usb_usual_check_type);
>
> /*
> */
> +static int usu_uevent(struct class_device *class_dev,
> + char **envp, int num_envp, char *buffer, int buffer_size)
> +{
> + unsigned long flags;
> + int i;
> +
> + /* P3 */ printk("libusual: uevent\n");
> + for (i = 1; i < 3; i++) {
> + spin_lock_irqsave(&usu_lock, flags);
> + if (stat[i].fls & USU_MOD_FL_FAILED) {
> + /* P3 */ printk("libusual: kicking %s\n", bias_names[i]);
> + stat[i].fls &= ~USU_MOD_FL_FAILED;
> + spin_unlock_irqrestore(&usu_lock, flags);
> + usu_kick(i);
> + } else {
> + spin_unlock_irqrestore(&usu_lock, flags);
> + }
> + }
> + return 0;
> +}
> +
> +/*
> + */
> static int usu_probe(struct usb_interface *intf,
> const struct usb_device_id *id)
> {
> unsigned long type;
> - int rc;
> - unsigned long flags;
>
> type = USB_US_TYPE(id->driver_info);
> if (type == 0)
> type = atomic_read(&usu_bias);
> + return usu_kick(type);
> +}
> +
> +static int usu_kick(unsigned long type)
> +{
> + int rc;
> + unsigned long flags;
>
> spin_lock_irqsave(&usu_lock, flags);
> if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
> @@ -186,10 +220,14 @@ static int usu_probe_thread(void *arg)
> if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
> /*
> * This should not happen, but let us keep tabs on it.
> + * One common source of this a user who builds USB statically,
> + * then uses initrd, and has a USB device. When static devices
> + * are probed, request_module() calls a fake modprobe and fails.
> */
> printk(KERN_NOTICE "libusual: "
> - "modprobe for %s succeeded, but module is not present\n",
> + "request for %s succeeded, but module is not present\n",
> bias_names[type]);
> + st->fls |= USU_MOD_FL_FAILED;
> }
> st->fls &= ~USU_MOD_FL_THREAD;
> spin_unlock_irqrestore(&usu_lock, flags);
> @@ -203,9 +241,27 @@ static int __init usb_usual_init(void)
> {
> int rc;
>
> + usu_class = class_create(THIS_MODULE, "libusual");
> + if (IS_ERR(usu_class)) {
> + rc = PTR_ERR(usu_class_device);
> + goto err_class;
> + }
> + usu_class_device = class_device_create(usu_class, NULL, 0, NULL, "0");
> + if (IS_ERR(usu_class_device)) {
> + rc = PTR_ERR(usu_class_device);
> + goto err_classdev;
> + }
> + usu_class_device->uevent = usu_uevent;
> +
> rc = usb_register(&usu_driver);
> up(&usu_init_notify);
> return rc;
> +
> + // class_device_destroy(usu_class, 0);
> +err_classdev:
> + class_destroy(usu_class);
> +err_class:
> + return rc;
> }
>
> static void __exit usb_usual_exit(void)
> @@ -221,6 +277,9 @@ static void __exit usb_usual_exit(void)
> wait_for_completion(&usu_end_notify);
> atomic_dec(&total_threads);
> }
> +
> + class_device_destroy(usu_class, 0);
> + class_destroy(usu_class);
> }
>
> /*
>
> This is a patch for our bug 204396:
> https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=204396
> The summary is: a USB storage device is not recognized if plugged in
> before a reboot on a Fedora Core 6 Test 3.
>
> As usual, several circumstances have to occur for this to happen.
> What makes Fedora differend is how its USB core is built in statically.
> This makes libusual to be static (it's an artefact of my ineptness with
> Kconfig language, and also nash's modprobe not loading dependencies),
> and this splits it off storage (sub)modules.
>
> The patch abuses the class mechanism to receive a signal from udev
> when it's ready and thus request_module can be retried.
>
> How acceptable is this?

It's a hack and you know it :)

I don't think this is what you need to do here, sorry. I suggest fixing
your boot scrips to load the dependant modules properly. Or something
else, but abusing sysfs for something like this isn't very nice.

thanks,

greg k-h
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/