From a8c2d3c6996d24a0b4e610a859d33746bc3e066d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Apr 2016 23:23:32 +0100 Subject: [PATCH] nbd: Create size change events for userspace (Closes: #812487) --- debian/changelog | 1 + ...ate-size-change-events-for-userspace.patch | 163 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 165 insertions(+) create mode 100644 debian/patches/features/all/nbd-create-size-change-events-for-userspace.patch diff --git a/debian/changelog b/debian/changelog index a70e6aea0..1ad8b0282 100644 --- a/debian/changelog +++ b/debian/changelog @@ -247,6 +247,7 @@ linux (4.5.1-1) UNRELEASED; urgency=medium * [armhf] Add support for octa-core big.LITTLE systems including Exynos (Closes: #819379) * [armhf] watchdog: Enable S3C2410_WATCHDOG as module (Closes: #819377) + * nbd: Create size change events for userspace (Closes: #812487) [ Aurelien Jarno ] * [mipsel/mips/config.loongson-2f] Disable VIDEO_CX23885, VIDEO_IVTV, diff --git a/debian/patches/features/all/nbd-create-size-change-events-for-userspace.patch b/debian/patches/features/all/nbd-create-size-change-events-for-userspace.patch new file mode 100644 index 000000000..0e6ef994c --- /dev/null +++ b/debian/patches/features/all/nbd-create-size-change-events-for-userspace.patch @@ -0,0 +1,163 @@ +From: Markus Pargmann +Date: Mon, 27 Jul 2015 07:36:49 +0200 +Subject: nbd: Create size change events for userspace +Origin: https://git.kernel.org/linus/37091fdd831f28a6509008542174ed324dd645bc +Bug-Debian: https://bugs.debian.org/812487 + +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 +--- + drivers/block/nbd.c | 79 +++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 58 insertions(+), 21 deletions(-) + +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -98,6 +98,11 @@ static inline struct device *nbd_to_dev( + 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 c + 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_de + 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_de + 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_devi + 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_devi + 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_devi + } + + nbd_dev_dbg_init(nbd); +- error = nbd_thread_recv(nbd); ++ error = nbd_thread_recv(nbd, bdev); + nbd_dev_dbg_close(nbd); + kthread_stop(thread); + diff --git a/debian/patches/series b/debian/patches/series index 26ee80df6..7bea7d953 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -144,3 +144,4 @@ bugfix/all/ipv4-don-t-do-expensive-useless-work-during-inetdev-.patch bugfix/x86/x86-mm-32-enable-full-randomization-on-i386-and-x86_.patch bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch +features/all/nbd-create-size-change-events-for-userspace.patch