ACK: [SRU][Xenial][PATCH 1/1] nbd: Create size change events for userspace
Kleber Souza
kleber.souza at canonical.com
Mon Oct 23 11:22:39 UTC 2017
On 10/20/17 19:33, Joseph Salisbury wrote:
> From: Markus Pargmann <mpa at pengutronix.de>
>
> BugLink: http://bugs.launchpad.net/bugs/696435
>
> 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 <mpa at pengutronix.de>
> (cherry picked from commit 37091fdd831f28a6509008542174ed324dd645bc)
> Signed-off-by: Joseph Salisbury <joseph.salisbury at canonical.com>
Clean cherry-pick, good test results, fixing 6 y/o bug :-).
Acked-by: Kleber Sacilotto de Souza <kleber.souza at canonical.com>
> ---
> drivers/block/nbd.c | 79 +++++++++++++++++++++++++++++++++++++++--------------
> 1 file changed, 58 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> index b05226d..5f807a6 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -98,6 +98,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) {
> @@ -110,6 +115,42 @@ 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_capacity(nbd->disk, 0);
> + kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
> +
> + return 0;
> +}
> +
> +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;
> + 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,
> + int blocksize, int nr_blocks)
> +{
> + int ret;
> +
> + ret = set_blocksize(bdev, blocksize);
> + if (ret)
> + return ret;
> +
> + nbd->blksize = blocksize;
> + nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks;
> +
> + nbd_size_update(nbd, bdev);
> +
> + return 0;
> +}
> +
> static void nbd_end_request(struct nbd_device *nbd, struct request *req)
> {
> int error = req->errors ? -EIO : 0;
> @@ -402,7 +443,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;
> @@ -427,6 +468,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)) {
> @@ -437,6 +480,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);
>
> spin_lock_irqsave(&nbd->tasks_lock, flags);
> @@ -696,20 +741,19 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
> return -EINVAL;
> }
>
> - 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;
> + case NBD_SET_BLKSIZE: {
> + loff_t bsize = nbd->bytesize;
> + do_div(bsize, arg);
> +
> + return nbd_size_set(nbd, bdev, arg, bsize);
> + }
>
> 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;
> @@ -725,13 +769,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;
> @@ -762,7 +799,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);
>
>
More information about the kernel-team
mailing list