[bug report] ubi: use blk_mq_alloc_disk and blk_cleanup_disk

Dan Carpenter dan.carpenter at linaro.org
Mon Jul 24 22:40:11 PDT 2023


Hello Christoph Hellwig,

The patch 77567b25ab9f: "ubi: use blk_mq_alloc_disk and
blk_cleanup_disk" from Jun 2, 2021 (linux-next), leads to the
following Smatch static checker warning:

	drivers/mtd/ubi/block.c:390 ubiblock_create()
	warn: pointer dereferenced without being set 'dev->gd'

drivers/mtd/ubi/block.c
    349 int ubiblock_create(struct ubi_volume_info *vi)
    350 {
    351         struct ubiblock *dev;
    352         struct gendisk *gd;
    353         u64 disk_capacity;
    354         int ret;
    355 
    356         ret = calc_disk_capacity(vi, &disk_capacity);
    357         if (ret) {
    358                 return ret;
    359         }
    360 
    361         /* Check that the volume isn't already handled */
    362         mutex_lock(&devices_mutex);
    363         if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
    364                 ret = -EEXIST;
    365                 goto out_unlock;
    366         }
    367 
    368         dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
    369         if (!dev) {
    370                 ret = -ENOMEM;
    371                 goto out_unlock;
    372         }
    373 
    374         mutex_init(&dev->dev_mutex);
    375 
    376         dev->ubi_num = vi->ubi_num;
    377         dev->vol_id = vi->vol_id;
    378         dev->leb_size = vi->usable_leb_size;
    379 
    380         dev->tag_set.ops = &ubiblock_mq_ops;
    381         dev->tag_set.queue_depth = 64;
    382         dev->tag_set.numa_node = NUMA_NO_NODE;
    383         dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
    384         dev->tag_set.cmd_size = sizeof(struct ubiblock_pdu);
    385         dev->tag_set.driver_data = dev;
    386         dev->tag_set.nr_hw_queues = 1;
    387 
    388         ret = blk_mq_alloc_tag_set(&dev->tag_set);
    389         if (ret) {
--> 390                 dev_err(disk_to_dev(dev->gd), "blk_mq_alloc_tag_set failed");

dev->gd is NULL so this will crash.  Although maybe it won't crash
because the dev_err() macro has special code to handle weird addresses
below PAGE_SIZE.

    391                 goto out_free_dev;
    392         }
    393 
    394 
    395         /* Initialize the gendisk of this ubiblock device */
    396         gd = blk_mq_alloc_disk(&dev->tag_set, dev);
    397         if (IS_ERR(gd)) {
    398                 ret = PTR_ERR(gd);
    399                 goto out_free_tags;
    400         }
    401 
    402         gd->fops = &ubiblock_ops;
    403         gd->major = ubiblock_major;
    404         gd->minors = 1;
    405         gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL);
    406         if (gd->first_minor < 0) {
    407                 dev_err(disk_to_dev(gd),
    408                         "block: dynamic minor allocation failed");
    409                 ret = -ENODEV;
    410                 goto out_cleanup_disk;
    411         }
    412         gd->flags |= GENHD_FL_NO_PART;
    413         gd->private_data = dev;
    414         sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
    415         set_capacity(gd, disk_capacity);
    416         dev->gd = gd;
    417 
    418         dev->rq = gd->queue;
    419         blk_queue_max_segments(dev->rq, UBI_MAX_SG_COUNT);
    420 
    421         list_add_tail(&dev->list, &ubiblock_devices);
    422 
    423         /* Must be the last step: anyone can call file ops from now on */
    424         ret = device_add_disk(vi->dev, dev->gd, NULL);
    425         if (ret)
    426                 goto out_remove_minor;
    427 
    428         dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
    429                  dev->ubi_num, dev->vol_id, vi->name);
    430         mutex_unlock(&devices_mutex);
    431         return 0;
    432 
    433 out_remove_minor:
    434         list_del(&dev->list);
    435         idr_remove(&ubiblock_minor_idr, gd->first_minor);
    436 out_cleanup_disk:
    437         put_disk(dev->gd);
    438 out_free_tags:
    439         blk_mq_free_tag_set(&dev->tag_set);
    440 out_free_dev:
    441         kfree(dev);
    442 out_unlock:
    443         mutex_unlock(&devices_mutex);
    444 
    445         return ret;
    446 }

regards,
dan carpenter



More information about the linux-mtd mailing list