]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rnbd-srv: Fix server side setting of bi_size for special IOs
authorFlorian-Ewald Mueller <florian-ewald.mueller@ionos.com>
Fri, 5 Dec 2025 12:47:32 +0000 (13:47 +0100)
committerJens Axboe <axboe@kernel.dk>
Tue, 6 Jan 2026 12:28:10 +0000 (05:28 -0700)
On rnbd-srv, the bi_size of the bio is set during the bio_add_page
function, to which datalen is passed. But for special IOs like DISCARD
and WRITE_ZEROES, datalen is 0, since there is no data to write. For
these special IOs, use the bi_size of the rnbd_msg_io.

Fixes: f6f84be089c9 ("block/rnbd-srv: Add sanity check and remove redundant assignment")
Signed-off-by: Florian-Ewald Mueller <florian-ewald.mueller@ionos.com>
Signed-off-by: Md Haris Iqbal <haris.iqbal@ionos.com>
Signed-off-by: Grzegorz Prajsner <grzegorz.prajsner@ionos.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/rnbd/rnbd-srv.c

index 2df8941a6b1463ab42f5083697dd3a3fa9dff1da..9b3fdc202e1521be9e146ba4ac755a5badfc00b5 100644 (file)
@@ -145,18 +145,30 @@ static int process_rdma(struct rnbd_srv_session *srv_sess,
        priv->sess_dev = sess_dev;
        priv->id = id;
 
-       bio = bio_alloc(file_bdev(sess_dev->bdev_file), 1,
+       bio = bio_alloc(file_bdev(sess_dev->bdev_file), !!datalen,
                        rnbd_to_bio_flags(le32_to_cpu(msg->rw)), GFP_KERNEL);
-       bio_add_virt_nofail(bio, data, datalen);
-
-       bio->bi_opf = rnbd_to_bio_flags(le32_to_cpu(msg->rw));
-       if (bio_has_data(bio) &&
-           bio->bi_iter.bi_size != le32_to_cpu(msg->bi_size)) {
-               rnbd_srv_err_rl(sess_dev, "Datalen mismatch:  bio bi_size (%u), bi_size (%u)\n",
-                               bio->bi_iter.bi_size, msg->bi_size);
-               err = -EINVAL;
-               goto bio_put;
+       if (unlikely(!bio)) {
+               err = -ENOMEM;
+               goto put_sess_dev;
        }
+
+       if (!datalen) {
+               /*
+                * For special requests like DISCARD and WRITE_ZEROES, the datalen is zero.
+                */
+               bio->bi_iter.bi_size = le32_to_cpu(msg->bi_size);
+       } else {
+               bio_add_virt_nofail(bio, data, datalen);
+               bio->bi_opf = rnbd_to_bio_flags(le32_to_cpu(msg->rw));
+               if (bio->bi_iter.bi_size != le32_to_cpu(msg->bi_size)) {
+                       rnbd_srv_err_rl(sess_dev,
+                                       "Datalen mismatch:  bio bi_size (%u), bi_size (%u)\n",
+                                       bio->bi_iter.bi_size, msg->bi_size);
+                       err = -EINVAL;
+                       goto bio_put;
+               }
+       }
+
        bio->bi_end_io = rnbd_dev_bi_end_io;
        bio->bi_private = priv;
        bio->bi_iter.bi_sector = le64_to_cpu(msg->sector);
@@ -170,6 +182,7 @@ static int process_rdma(struct rnbd_srv_session *srv_sess,
 
 bio_put:
        bio_put(bio);
+put_sess_dev:
        rnbd_put_sess_dev(sess_dev);
 err:
        kfree(priv);