Skip to content

Commit 37091fd

Browse files
author
Markus Pargmann
committed
nbd: Create size change events for userspace
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: systemd/systemd#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]>
1 parent da6ccaa commit 37091fd

File tree

1 file changed

+58
-21
lines changed

1 file changed

+58
-21
lines changed

drivers/block/nbd.c

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ static inline struct device *nbd_to_dev(struct nbd_device *nbd)
100100
return disk_to_dev(nbd->disk);
101101
}
102102

103+
static bool nbd_is_connected(struct nbd_device *nbd)
104+
{
105+
return !!nbd->task_recv;
106+
}
107+
103108
static const char *nbdcmd_to_ascii(int cmd)
104109
{
105110
switch (cmd) {
@@ -112,6 +117,42 @@ static const char *nbdcmd_to_ascii(int cmd)
112117
return "invalid";
113118
}
114119

120+
static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev)
121+
{
122+
bdev->bd_inode->i_size = 0;
123+
set_capacity(nbd->disk, 0);
124+
kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
125+
126+
return 0;
127+
}
128+
129+
static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev)
130+
{
131+
if (!nbd_is_connected(nbd))
132+
return;
133+
134+
bdev->bd_inode->i_size = nbd->bytesize;
135+
set_capacity(nbd->disk, nbd->bytesize >> 9);
136+
kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
137+
}
138+
139+
static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
140+
int blocksize, int nr_blocks)
141+
{
142+
int ret;
143+
144+
ret = set_blocksize(bdev, blocksize);
145+
if (ret)
146+
return ret;
147+
148+
nbd->blksize = blocksize;
149+
nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks;
150+
151+
nbd_size_update(nbd, bdev);
152+
153+
return 0;
154+
}
155+
115156
static void nbd_end_request(struct nbd_device *nbd, struct request *req)
116157
{
117158
int error = req->errors ? -EIO : 0;
@@ -401,7 +442,7 @@ static struct device_attribute pid_attr = {
401442
.show = pid_show,
402443
};
403444

404-
static int nbd_thread_recv(struct nbd_device *nbd)
445+
static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
405446
{
406447
struct request *req;
407448
int ret;
@@ -421,6 +462,8 @@ static int nbd_thread_recv(struct nbd_device *nbd)
421462
return ret;
422463
}
423464

465+
nbd_size_update(nbd, bdev);
466+
424467
while (1) {
425468
req = nbd_read_stat(nbd);
426469
if (IS_ERR(req)) {
@@ -431,6 +474,8 @@ static int nbd_thread_recv(struct nbd_device *nbd)
431474
nbd_end_request(nbd, req);
432475
}
433476

477+
nbd_size_clear(nbd, bdev);
478+
434479
device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
435480

436481
nbd->task_recv = NULL;
@@ -707,20 +752,19 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
707752
return err;
708753
}
709754

710-
case NBD_SET_BLKSIZE:
711-
nbd->blksize = arg;
712-
nbd->bytesize &= ~(nbd->blksize-1);
713-
bdev->bd_inode->i_size = nbd->bytesize;
714-
set_blocksize(bdev, nbd->blksize);
715-
set_capacity(nbd->disk, nbd->bytesize >> 9);
716-
return 0;
755+
case NBD_SET_BLKSIZE: {
756+
loff_t bsize = nbd->bytesize;
757+
do_div(bsize, arg);
758+
759+
return nbd_size_set(nbd, bdev, arg, bsize);
760+
}
717761

718762
case NBD_SET_SIZE:
719-
nbd->bytesize = arg & ~(nbd->blksize-1);
720-
bdev->bd_inode->i_size = nbd->bytesize;
721-
set_blocksize(bdev, nbd->blksize);
722-
set_capacity(nbd->disk, nbd->bytesize >> 9);
723-
return 0;
763+
return nbd_size_set(nbd, bdev, nbd->blksize,
764+
arg / nbd->blksize);
765+
766+
case NBD_SET_SIZE_BLOCKS:
767+
return nbd_size_set(nbd, bdev, nbd->blksize, arg);
724768

725769
case NBD_SET_TIMEOUT:
726770
nbd->xmit_timeout = arg * HZ;
@@ -736,13 +780,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
736780
nbd->flags = arg;
737781
return 0;
738782

739-
case NBD_SET_SIZE_BLOCKS:
740-
nbd->bytesize = ((u64) arg) * nbd->blksize;
741-
bdev->bd_inode->i_size = nbd->bytesize;
742-
set_blocksize(bdev, nbd->blksize);
743-
set_capacity(nbd->disk, nbd->bytesize >> 9);
744-
return 0;
745-
746783
case NBD_DO_IT: {
747784
struct task_struct *thread;
748785
int error;
@@ -764,7 +801,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
764801
}
765802

766803
nbd_dev_dbg_init(nbd);
767-
error = nbd_thread_recv(nbd);
804+
error = nbd_thread_recv(nbd, bdev);
768805
nbd_dev_dbg_close(nbd);
769806
kthread_stop(thread);
770807

0 commit comments

Comments
 (0)