Re: [syzbot] [block?] INFO: task hung in bdev_release

From: syzbot
Date: Sat Dec 16 2023 - 22:11:13 EST


For archival purposes, forwarding an incoming command email to
linux-kernel@xxxxxxxxxxxxxxx.

***

Subject: [block?] INFO: task hung in bdev_release
Author: eadavis@xxxxxx

please test task hung in bdev_release

#syz test https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 8c9660f65153

diff --git a/block/bdev.c b/block/bdev.c
index 6f73b02d549c..95be32bc8dea 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -938,6 +938,7 @@ struct bdev_handle *bdev_open_by_path(const char *path, blk_mode_t mode,
if (error)
return ERR_PTR(error);

+ printk("dev: %u, path: %s, holder: %p, %s\n", dev, path, holder, __func__);
handle = bdev_open_by_dev(dev, mode, holder, hops);
if (!IS_ERR(handle) && (mode & BLK_OPEN_WRITE) &&
bdev_read_only(handle->bdev)) {
@@ -964,6 +965,7 @@ void bdev_release(struct bdev_handle *handle)
if (atomic_read(&bdev->bd_openers) == 1)
sync_blockdev(bdev);

+ printk("nxt om, b: %p, dk: %p, %s\n", bdev, disk, __func__);
mutex_lock(&disk->open_mutex);
bdev_yield_write_access(bdev, handle->mode);

@@ -982,6 +984,7 @@ void bdev_release(struct bdev_handle *handle)
else
blkdev_put_whole(bdev);
mutex_unlock(&disk->open_mutex);
+ printk("out om, b: %p, dk: %p, %s\n", bdev, disk, __func__);

module_put(disk->fops->owner);
blkdev_put_no_open(bdev);
@@ -1092,7 +1095,8 @@ void sync_bdevs(bool wait)
old_inode = inode;
bdev = I_BDEV(inode);

- mutex_lock(&bdev->bd_disk->open_mutex);
+ printk("in, b: %p, dk: %p, %s\n", bdev, bdev->bd_disk, __func__);
+ mutex_lock(&bdev->bd_disk->sync_mutex);
if (!atomic_read(&bdev->bd_openers)) {
; /* skip */
} else if (wait) {
@@ -1106,7 +1110,8 @@ void sync_bdevs(bool wait)
} else {
filemap_fdatawrite(inode->i_mapping);
}
- mutex_unlock(&bdev->bd_disk->open_mutex);
+ mutex_unlock(&bdev->bd_disk->sync_mutex);
+ printk("out, b: %p, dk: %p, %s\n", bdev, bdev->bd_disk, __func__);

spin_lock(&blockdev_superblock->s_inode_list_lock);
}
diff --git a/block/genhd.c b/block/genhd.c
index 13db3a7943d8..da44d4739915 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1355,6 +1355,7 @@ struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,

disk->node_id = node_id;
mutex_init(&disk->open_mutex);
+ mutex_init(&disk->sync_mutex);
xa_init(&disk->part_tbl);
if (xa_insert(&disk->part_tbl, 0, disk->part0, GFP_KERNEL))
goto out_destroy_part_tbl;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index b6414e1e645b..c302df0caebf 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -475,10 +475,11 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
*/
struct nbd_sock *nsock = config->socks[cmd->index];
cmd->retries++;
- dev_info(nbd_to_dev(nbd), "Possible stuck request %p: control (%s@%llu,%uB). Runtime %u seconds\n",
+ dev_info(nbd_to_dev(nbd), "Possible stuck request %p: control (%s@%llu,%uB). Runtime %u seconds, nbd: %p, d: %p\n",
req, nbdcmd_to_ascii(req_to_nbd_cmd_type(req)),
(unsigned long long)blk_rq_pos(req) << 9,
- blk_rq_bytes(req), (req->timeout / HZ) * cmd->retries);
+ blk_rq_bytes(req), (req->timeout / HZ) * cmd->retries,
+ nbd, nbd->disk);

mutex_lock(&nsock->tx_lock);
if (cmd->cookie != nsock->cookie) {
@@ -1425,6 +1426,7 @@ static int nbd_start_device(struct nbd_device *nbd)
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
+ printk("bs: %lld, blks: %lld, %s\n", config->bytesize, nbd_blksize(config), __func__);
return nbd_set_size(nbd, config->bytesize, nbd_blksize(config));
}

diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 3f8a21cd9233..31c6a7d6a74c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -161,6 +161,7 @@ struct gendisk {
#define GD_OWNS_QUEUE 6

struct mutex open_mutex; /* open/close mutex */
+ struct mutex sync_mutex; /* sync mutex */
unsigned open_partitions; /* number of open partitions */

struct backing_dev_info *bdi;