bcache: fix static checker warning in bcache_device_free()
authorColy Li <colyli@suse.de>
Wed, 13 Nov 2019 08:03:17 +0000 (16:03 +0800)
committerJens Axboe <axboe@kernel.dk>
Wed, 13 Nov 2019 22:42:50 +0000 (15:42 -0700)
Commit cafe56359144 ("bcache: A block layer cache") leads to the
following static checker warning:

    ./drivers/md/bcache/super.c:770 bcache_device_free()
    warn: variable dereferenced before check 'd->disk' (see line 766)

drivers/md/bcache/super.c
   762  static void bcache_device_free(struct bcache_device *d)
   763  {
   764          lockdep_assert_held(&bch_register_lock);
   765
   766          pr_info("%s stopped", d->disk->disk_name);
                                      ^^^^^^^^^
Unchecked dereference.

   767
   768          if (d->c)
   769                  bcache_device_detach(d);
   770          if (d->disk && d->disk->flags & GENHD_FL_UP)
                    ^^^^^^^
Check too late.

   771                  del_gendisk(d->disk);
   772          if (d->disk && d->disk->queue)
   773                  blk_cleanup_queue(d->disk->queue);
   774          if (d->disk) {
   775                  ida_simple_remove(&bcache_device_idx,
   776                                    first_minor_to_idx(d->disk->first_minor));
   777                  put_disk(d->disk);
   778          }
   779

It is not 100% sure that the gendisk struct of bcache device will always
be there, the warning makes sense when there is problem in block core.

This patch tries to remove the static checking warning by checking
d->disk to avoid NULL pointer deferences.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Coly Li <colyli@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/md/bcache/super.c

index ebb854e..7becced 100644 (file)
@@ -761,20 +761,28 @@ static inline int idx_to_first_minor(int idx)
 
 static void bcache_device_free(struct bcache_device *d)
 {
+       struct gendisk *disk = d->disk;
+
        lockdep_assert_held(&bch_register_lock);
 
-       pr_info("%s stopped", d->disk->disk_name);
+       if (disk)
+               pr_info("%s stopped", disk->disk_name);
+       else
+               pr_err("bcache device (NULL gendisk) stopped");
 
        if (d->c)
                bcache_device_detach(d);
-       if (d->disk && d->disk->flags & GENHD_FL_UP)
-               del_gendisk(d->disk);
-       if (d->disk && d->disk->queue)
-               blk_cleanup_queue(d->disk->queue);
-       if (d->disk) {
+
+       if (disk) {
+               if (disk->flags & GENHD_FL_UP)
+                       del_gendisk(disk);
+
+               if (disk->queue)
+                       blk_cleanup_queue(disk->queue);
+
                ida_simple_remove(&bcache_device_idx,
-                                 first_minor_to_idx(d->disk->first_minor));
-               put_disk(d->disk);
+                                 first_minor_to_idx(disk->first_minor));
+               put_disk(disk);
        }
 
        bioset_exit(&d->bio_split);