Re: [PATCH] bsg referencing bus driver module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



+linux-block

On Tue, Apr 17, 2018 at 1:05 PM, Anatoliy Glagolev <glagolig@xxxxxxxxx> wrote:
> Description: bsg_release may crash while decrementing reference to the
> parent device with the following stack:
>
> [16834.636216,07] Call Trace:
>                              ...   scsi_proc_hostdir_rm
> [16834.641944,07]  [<ffffffff8141723f>] scsi_host_dev_release+0x3f/0x130
> [16834.647740,07]  [<ffffffff813e4f82>] device_release+0x32/0xa0
> [16834.653423,07]  [<ffffffff812dc6c7>] kobject_cleanup+0x77/0x190
> [16834.659002,07]  [<ffffffff812dc585>] kobject_put+0x25/0x50
> [16834.664430,07]  [<ffffffff813e5277>] put_device+0x17/0x20
> [16834.669740,07]  [<ffffffff812d0334>] bsg_kref_release_function+0x24/0x30
> [16834.675007,07]  [<ffffffff812d14a6>] bsg_release+0x166/0x1d0
> [16834.680148,07]  [<ffffffff8119ba2b>] __fput+0xcb/0x1d0
> [16834.685156,07]  [<ffffffff8119bb6e>] ____fput+0xe/0x10
> [16834.690017,07]  [<ffffffff81077476>] task_work_run+0x86/0xb0
> [16834.694781,07]  [<ffffffff81057043>] exit_to_usermode_loop+0x6b/0x9a
> [16834.699466,07]  [<ffffffff81002875>] syscall_return_slowpath+0x55/0x60
> [16834.704110,07]  [<ffffffff8172d615>] int_ret_from_sys_call+0x25/0x9f
>
> if the parent driver implementing the device has unloaded. To address
> the problem, taking a reference to the parent driver module.
>
> Note: this is a follow-up to earlier discussion "[PATCH] Waiting for
> scsi_host_template release".
>
> ---
>  block/bsg.c                      | 31 +++++++++++++++++++++++++++----
>  drivers/scsi/scsi_transport_fc.c |  3 ++-
>  include/linux/bsg.h              |  5 +++++
>  3 files changed, 34 insertions(+), 5 deletions(-)
>
> diff --git a/block/bsg.c b/block/bsg.c
> index b9a5361..0aa7d74 100644
> --- a/block/bsg.c
> +++ b/block/bsg.c
> @@ -798,7 +798,8 @@ found:
>   return bd;
>  }
>
> -static struct bsg_device *bsg_get_device(struct inode *inode, struct
> file *file)
> +static struct bsg_device *bsg_get_device(struct inode *inode, struct
> file *file,
> + struct bsg_class_device **pbcd)
>  {
>   struct bsg_device *bd;
>   struct bsg_class_device *bcd;
> @@ -814,6 +815,7 @@ static struct bsg_device *bsg_get_device(struct
> inode *inode, struct file *file)
>
>   if (!bcd)
>   return ERR_PTR(-ENODEV);
> + *pbcd = bcd;
>
>   bd = __bsg_get_device(iminor(inode), bcd->queue);
>   if (bd)
> @@ -829,22 +831,34 @@ static struct bsg_device *bsg_get_device(struct
> inode *inode, struct file *file)
>  static int bsg_open(struct inode *inode, struct file *file)
>  {
>   struct bsg_device *bd;
> + struct bsg_class_device *bcd;
>
> - bd = bsg_get_device(inode, file);
> + bd = bsg_get_device(inode, file, &bcd);
>
>   if (IS_ERR(bd))
>   return PTR_ERR(bd);
>
>   file->private_data = bd;
> + if (bcd->parent_module) {
> + if (!try_module_get(bcd->parent_module)) {
> + bsg_put_device(bd);
> + return -ENODEV;
> + }
> + }
>   return 0;
>  }
>
>  static int bsg_release(struct inode *inode, struct file *file)
>  {
> + int ret;
>   struct bsg_device *bd = file->private_data;
> + struct module *parent_module = bd->queue->bsg_dev.parent_module;
>
>   file->private_data = NULL;
> - return bsg_put_device(bd);
> + ret = bsg_put_device(bd);
> + if (parent_module)
> + module_put(parent_module);
> + return ret;
>  }
>
>  static unsigned int bsg_poll(struct file *file, poll_table *wait)
> @@ -977,6 +991,14 @@ EXPORT_SYMBOL_GPL(bsg_unregister_queue);
>  int bsg_register_queue(struct request_queue *q, struct device *parent,
>         const char *name, void (*release)(struct device *))
>  {
> + return bsg_register_queue_ex(q, parent, name, release, NULL);
> +}
> +EXPORT_SYMBOL_GPL(bsg_register_queue);
> +
> +int bsg_register_queue_ex(struct request_queue *q, struct device *parent,
> +          const char *name, void (*release)(struct device *),
> +          struct module *parent_module)
> +{
>   struct bsg_class_device *bcd;
>   dev_t dev;
>   int ret;
> @@ -1012,6 +1034,7 @@ int bsg_register_queue(struct request_queue *q,
> struct device *parent,
>   bcd->queue = q;
>   bcd->parent = get_device(parent);
>   bcd->release = release;
> + bcd->parent_module = parent_module;
>   kref_init(&bcd->ref);
>   dev = MKDEV(bsg_major, bcd->minor);
>   class_dev = device_create(bsg_class, parent, dev, NULL, "%s", devname);
> @@ -1039,7 +1062,7 @@ unlock:
>   mutex_unlock(&bsg_mutex);
>   return ret;
>  }
> -EXPORT_SYMBOL_GPL(bsg_register_queue);
> +EXPORT_SYMBOL_GPL(bsg_register_queue_ex);
>
>  static struct cdev bsg_cdev;
>
> diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
> index 24eaaf6..c153f80 100644
> --- a/drivers/scsi/scsi_transport_fc.c
> +++ b/drivers/scsi/scsi_transport_fc.c
> @@ -4064,7 +4064,8 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct
> fc_host_attrs *fc_host)
>   blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
>   blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT);
>
> - err = bsg_register_queue(q, dev, bsg_name, NULL);
> + err = bsg_register_queue_ex(q, dev, bsg_name, NULL,
> + shost->hostt->module);
>   if (err) {
>   printk(KERN_ERR "fc_host%d: bsg interface failed to "
>   "initialize - register queue\n",
> diff --git a/include/linux/bsg.h b/include/linux/bsg.h
> index 7173f6e..fe41e83 100644
> --- a/include/linux/bsg.h
> +++ b/include/linux/bsg.h
> @@ -12,11 +12,16 @@ struct bsg_class_device {
>   struct request_queue *queue;
>   struct kref ref;
>   void (*release)(struct device *);
> + struct module *parent_module;
>  };
>
>  extern int bsg_register_queue(struct request_queue *q,
>        struct device *parent, const char *name,
>        void (*release)(struct device *));
> +extern int bsg_register_queue_ex(struct request_queue *q,
> +         struct device *parent, const char *name,
> +         void (*release)(struct device *),
> +         struct module *parent_module);
>  extern void bsg_unregister_queue(struct request_queue *);
>  #else
>  static inline int bsg_register_queue(struct request_queue *q,
> --
> 1.9.1



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux