On Mon, Jul 27, 2015 at 09:12:56AM +0200, Markus Pargmann wrote:
> The userspace needs to know when nbd devices are ready for use.
> Currently no events are created for the userspace which doesn't work for
> systemd.
> 
> See the discussion here: https://github.com/systemd/systemd/pull/358
> 
> This patch uses a central point to setup the nbd-internal sizes. A ioctl
> to set a size does not lead to a visible size change. The size of the
> block device will be kept at 0 until nbd is connected. As soon as it
> connects, the size will be changed to the real value and a uevent is
> created. When disconnecting, the blockdevice is set to 0 size and
> another uevent is generated.
> 
> Signed-off-by: Markus Pargmann <[email protected]>
> ---
>  drivers/block/nbd.c | 74 
> ++++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 54 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> index 1176a3b27a7e..95eb2904c324 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -97,6 +97,11 @@ static inline struct device *nbd_to_dev(struct nbd_device 
> *nbd)
>       return disk_to_dev(nbd->disk);
>  }
>  
> +static bool nbd_is_connected(struct nbd_device *nbd)
> +{
> +     return !!nbd->task_recv;
> +}
> +
>  static const char *nbdcmd_to_ascii(int cmd)
>  {
>       switch (cmd) {
> @@ -109,6 +114,43 @@ static const char *nbdcmd_to_ascii(int cmd)
>       return "invalid";
>  }
>  
> +static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev)
> +{
> +     bdev->bd_inode->i_size = 0;
> +     set_blocksize(bdev, 0);
> +     set_capacity(nbd->disk, 0);
> +     kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
> +
> +     return 0;
> +}
> +
> +static int nbd_size_update(struct nbd_device *nbd, struct block_device *bdev)
> +{
> +     int ret;
> +
> +     if (!nbd_is_connected(nbd))
> +             return 0;
> +
> +     ret = set_blocksize(bdev, nbd->blksize);
> +     if (ret)
> +             return ret;
> +
> +     bdev->bd_inode->i_size = nbd->bytesize;
> +     set_capacity(nbd->disk, nbd->bytesize >> 9);
> +     kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
> +
> +     return 0;
> +}
> +
> +static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
> +                     int blocksize, int nr_blocks)
> +{
> +     nbd->blksize = blocksize;
> +     nbd->bytesize = blocksize * nr_blocks;
> +
> +     return nbd_size_update(nbd, bdev);
> +}
> +
>  static void nbd_end_request(struct nbd_device *nbd, struct request *req)
>  {
>       int error = req->errors ? -EIO : 0;
> @@ -399,7 +441,7 @@ static struct device_attribute pid_attr = {
>       .show = pid_show,
>  };
>  
> -static int nbd_thread_recv(struct nbd_device *nbd)
> +static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
>  {
>       struct request *req;
>       int ret;
> @@ -417,6 +459,8 @@ static int nbd_thread_recv(struct nbd_device *nbd)
>               return ret;
>       }
>  
> +     nbd_size_update(nbd, bdev);
> +
>       while (1) {
>               req = nbd_read_stat(nbd);
>               if (IS_ERR(req)) {
> @@ -427,6 +471,8 @@ static int nbd_thread_recv(struct nbd_device *nbd)
>               nbd_end_request(nbd, req);
>       }
>  
> +     nbd_size_clear(nbd, bdev);
> +
>       device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
>  
>       nbd->task_recv = NULL;
> @@ -681,19 +727,14 @@ static int __nbd_ioctl(struct block_device *bdev, 
> struct nbd_device *nbd,
>       }
>  
>       case NBD_SET_BLKSIZE:
> -             nbd->blksize = arg;
> -             nbd->bytesize &= ~(nbd->blksize-1);
> -             bdev->bd_inode->i_size = nbd->bytesize;
> -             set_blocksize(bdev, nbd->blksize);
> -             set_capacity(nbd->disk, nbd->bytesize >> 9);
> -             return 0;
> +             return nbd_size_set(nbd, bdev, arg, nbd->bytesize / arg);

This does not work for 32bit systems. Have to use do_div() for this.
Will fix that for the next version.

Best regards,

Markus

>  
>       case NBD_SET_SIZE:
> -             nbd->bytesize = arg & ~(nbd->blksize-1);
> -             bdev->bd_inode->i_size = nbd->bytesize;
> -             set_blocksize(bdev, nbd->blksize);
> -             set_capacity(nbd->disk, nbd->bytesize >> 9);
> -             return 0;
> +             return nbd_size_set(nbd, bdev, nbd->blksize,
> +                                 arg / nbd->blksize);
> +
> +     case NBD_SET_SIZE_BLOCKS:
> +             return nbd_size_set(nbd, bdev, nbd->blksize, arg);
>  
>       case NBD_SET_TIMEOUT:
>               nbd->xmit_timeout = arg * HZ;
> @@ -709,13 +750,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct 
> nbd_device *nbd,
>               nbd->flags = arg;
>               return 0;
>  
> -     case NBD_SET_SIZE_BLOCKS:
> -             nbd->bytesize = ((u64) arg) * nbd->blksize;
> -             bdev->bd_inode->i_size = nbd->bytesize;
> -             set_blocksize(bdev, nbd->blksize);
> -             set_capacity(nbd->disk, nbd->bytesize >> 9);
> -             return 0;
> -
>       case NBD_DO_IT: {
>               struct task_struct *thread;
>               struct socket *sock;
> @@ -746,7 +780,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct 
> nbd_device *nbd,
>               }
>  
>               nbd_dev_dbg_init(nbd);
> -             error = nbd_thread_recv(nbd);
> +             error = nbd_thread_recv(nbd, bdev);
>               nbd_dev_dbg_close(nbd);
>               kthread_stop(thread);
>  
> -- 
> 2.1.4
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Attachment: signature.asc
Description: Digital signature

------------------------------------------------------------------------------
_______________________________________________
Nbd-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/nbd-general

Reply via email to