[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