nbd: set the logical and physical blocksize properly
authorJosef Bacik <jbacik@fb.com>
Mon, 13 Feb 2017 15:39:47 +0000 (10:39 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Jan 2019 07:10:57 +0000 (08:10 +0100)
commit e544541b0765c341174613b416d4b074fa7571c2 upstream.

We noticed when trying to do O_DIRECT to an export on the server side
that we were getting requests smaller than the 4k sectorsize of the
device.  This is because the client isn't setting the logical and
physical blocksizes properly for the underlying device.  Fix this up by
setting the queue blocksizes and then calling bd_set_size.

Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/block/nbd.c

index 42a53956aefeac1ed831948803b424a0cd6c2668..2f4e5997cdb2225f16585a175561d07cbb828a8d 100644 (file)
@@ -108,7 +108,7 @@ static const char *nbdcmd_to_ascii(int cmd)
 
 static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev)
 {
-       bdev->bd_inode->i_size = 0;
+       bd_set_size(bdev, 0);
        set_capacity(nbd->disk, 0);
        kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
 
@@ -117,29 +117,20 @@ static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev)
 
 static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev)
 {
-       if (!nbd_is_connected(nbd))
-               return;
-
-       bdev->bd_inode->i_size = nbd->bytesize;
+       blk_queue_logical_block_size(nbd->disk->queue, nbd->blksize);
+       blk_queue_physical_block_size(nbd->disk->queue, nbd->blksize);
+       bd_set_size(bdev, nbd->bytesize);
        set_capacity(nbd->disk, nbd->bytesize >> 9);
        kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
 }
 
-static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
+static void nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
                        loff_t blocksize, loff_t nr_blocks)
 {
-       int ret;
-
-       ret = set_blocksize(bdev, blocksize);
-       if (ret)
-               return ret;
-
        nbd->blksize = blocksize;
        nbd->bytesize = blocksize * nr_blocks;
-
-       nbd_size_update(nbd, bdev);
-
-       return 0;
+       if (nbd_is_connected(nbd))
+               nbd_size_update(nbd, bdev);
 }
 
 static void nbd_end_request(struct nbd_cmd *cmd)
@@ -655,16 +646,17 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
        case NBD_SET_BLKSIZE: {
                loff_t bsize = div_s64(nbd->bytesize, arg);
 
-               return nbd_size_set(nbd, bdev, arg, bsize);
+               nbd_size_set(nbd, bdev, arg, bsize);
+               return 0;
        }
 
        case NBD_SET_SIZE:
-               return nbd_size_set(nbd, bdev, nbd->blksize,
-                                       div_s64(arg, nbd->blksize));
-
+               nbd_size_set(nbd, bdev, nbd->blksize,
+                            div_s64(arg, nbd->blksize));
+               return 0;
        case NBD_SET_SIZE_BLOCKS:
-               return nbd_size_set(nbd, bdev, nbd->blksize, arg);
-
+               nbd_size_set(nbd, bdev, nbd->blksize, arg);
+               return 0;
        case NBD_SET_TIMEOUT:
                if (arg) {
                        nbd->tag_set.timeout = arg * HZ;