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 <mpa@...1897...> > --- > 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