linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PULL] NBD for 4.6
@ 2016-02-21 14:01 Markus Pargmann
  2016-02-21 14:01 ` [PATCH 1/7] nbd: Fix debugfs error handling Markus Pargmann
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel, Markus Pargmann

Hi Jens,

This pull request contains 7 patches for 4.6.

Patch 1 fixes some unnecessarily complicated code I introduced some versions
ago for debugfs.

Patch 2 removes the criticised signal usage within NBD to kill the NBD threads
after a timeout. This code was used for the last years and is now replaced by
simply killing the tcp connection.

Patches 3-6 are some smaller cleanups.

Patch 7 uevents for the userspace. This way udev/systemd can react on connected
NBD devices.

Best Regards,

Markus



The following changes since commit 92e963f50fc74041b5e9e744c330dca48e04f08d:

  Linux 4.5-rc1 (2016-01-24 13:06:47 -0800)

are available in the git repository at:

  git://git.pengutronix.de/git/mpa/linux-nbd.git tags/nbd-for-4.6

for you to fetch changes up to 37091fdd831f28a6509008542174ed324dd645bc:

  nbd: Create size change events for userspace (2016-02-15 10:35:47 +0100)

----------------------------------------------------------------
NBD for 4.6

----------------------------------------------------------------
Dan Streetman (1):
      nbd: ratelimit error msgs after socket close

Markus Pargmann (6):
      nbd: Fix debugfs error handling
      nbd: Remove signal usage
      nbd: Timeouts are not user requested disconnects
      nbd: Cleanup reset of nbd and bdev after a disconnect
      nbd: Move flag parsing to a function
      nbd: Create size change events for userspace

 drivers/block/nbd.c | 335 ++++++++++++++++++++++++++--------------------------
 1 file changed, 170 insertions(+), 165 deletions(-)

-- 
2.7.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/7] nbd: Fix debugfs error handling
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-02-21 14:01 ` [PATCH 2/7] nbd: Remove signal usage Markus Pargmann
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel, Markus Pargmann

Static checker complains about the implemented error handling. It is
indeed wrong. We don't care about the return values of created debugfs
files.

We only have to check the return values of created dirs for NULL
pointer. If we use a null pointer as parent directory for files, this
may lead to debugfs files in wrong places.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 drivers/block/nbd.c | 55 ++++++++++++++---------------------------------------
 1 file changed, 14 insertions(+), 41 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index e4c5cc107934..d61a04155d99 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -892,50 +892,23 @@ static const struct file_operations nbd_dbg_flags_ops = {
 static int nbd_dev_dbg_init(struct nbd_device *nbd)
 {
 	struct dentry *dir;
-	struct dentry *f;
+
+	if (!nbd_dbg_dir)
+		return -EIO;
 
 	dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
-	if (IS_ERR_OR_NULL(dir)) {
-		dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s' (%ld)\n",
-			nbd_name(nbd), PTR_ERR(dir));
-		return PTR_ERR(dir);
+	if (!dir) {
+		dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n",
+			nbd_name(nbd));
+		return -EIO;
 	}
 	nbd->dbg_dir = dir;
 
-	f = debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
-	if (IS_ERR_OR_NULL(f)) {
-		dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'tasks', %ld\n",
-			PTR_ERR(f));
-		return PTR_ERR(f);
-	}
-
-	f = debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
-	if (IS_ERR_OR_NULL(f)) {
-		dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'size_bytes', %ld\n",
-			PTR_ERR(f));
-		return PTR_ERR(f);
-	}
-
-	f = debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
-	if (IS_ERR_OR_NULL(f)) {
-		dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'timeout', %ld\n",
-			PTR_ERR(f));
-		return PTR_ERR(f);
-	}
-
-	f = debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
-	if (IS_ERR_OR_NULL(f)) {
-		dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'blocksize', %ld\n",
-			PTR_ERR(f));
-		return PTR_ERR(f);
-	}
-
-	f = debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
-	if (IS_ERR_OR_NULL(f)) {
-		dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'flags', %ld\n",
-			PTR_ERR(f));
-		return PTR_ERR(f);
-	}
+	debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
+	debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
+	debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
+	debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
+	debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
 
 	return 0;
 }
@@ -950,8 +923,8 @@ static int nbd_dbg_init(void)
 	struct dentry *dbg_dir;
 
 	dbg_dir = debugfs_create_dir("nbd", NULL);
-	if (IS_ERR(dbg_dir))
-		return PTR_ERR(dbg_dir);
+	if (!dbg_dir)
+		return -EIO;
 
 	nbd_dbg_dir = dbg_dir;
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/7] nbd: Remove signal usage
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
  2016-02-21 14:01 ` [PATCH 1/7] nbd: Fix debugfs error handling Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-02-21 14:01 ` [PATCH 3/7] nbd: Timeouts are not user requested disconnects Markus Pargmann
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-kernel, nbd-general, kernel, Markus Pargmann,
	Oleg Nesterov, Christoph Hellwig

As discussed on the mailing list, the usage of signals for timeout
handling has a lot of potential issues. The nbd driver used for some
time signals for timeouts. These signals where able to get the threads
out of the blocking socket operations.

This patch removes all signal usage and uses a socket shutdown instead.
The socket descriptor itself is cleared later when the whole nbd device
is closed.

The tasks_lock is removed as we do not depend on this anymore. Instead
a new lock for the socket is introduced so we can safely work with the
socket in the timeout handler outside of the two main threads.

Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 drivers/block/nbd.c | 126 ++++++++++++++++++++--------------------------------
 1 file changed, 48 insertions(+), 78 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index d61a04155d99..438f4dc549db 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -60,7 +60,8 @@ struct nbd_device {
 	bool disconnect; /* a disconnect has been requested by user */
 
 	struct timer_list timeout_timer;
-	spinlock_t tasks_lock;
+	/* protects initialization and shutdown of the socket */
+	spinlock_t sock_lock;
 	struct task_struct *task_recv;
 	struct task_struct *task_send;
 
@@ -129,13 +130,20 @@ static void nbd_end_request(struct nbd_device *nbd, struct request *req)
  */
 static void sock_shutdown(struct nbd_device *nbd)
 {
-	if (!nbd->sock)
+	spin_lock_irq(&nbd->sock_lock);
+
+	if (!nbd->sock) {
+		spin_unlock_irq(&nbd->sock_lock);
 		return;
+	}
 
 	dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
 	kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
+	sockfd_put(nbd->sock);
 	nbd->sock = NULL;
-	del_timer_sync(&nbd->timeout_timer);
+	spin_unlock_irq(&nbd->sock_lock);
+
+	del_timer(&nbd->timeout_timer);
 }
 
 static void nbd_xmit_timeout(unsigned long arg)
@@ -148,17 +156,15 @@ static void nbd_xmit_timeout(unsigned long arg)
 
 	nbd->disconnect = true;
 
-	spin_lock_irqsave(&nbd->tasks_lock, flags);
+	spin_lock_irqsave(&nbd->sock_lock, flags);
 
-	if (nbd->task_recv)
-		force_sig(SIGKILL, nbd->task_recv);
 
-	if (nbd->task_send)
-		force_sig(SIGKILL, nbd->task_send);
+	if (nbd->sock)
+		kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
 
-	spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+	spin_unlock_irqrestore(&nbd->sock_lock, flags);
 
-	dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
+	dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
 }
 
 /*
@@ -171,7 +177,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
 	int result;
 	struct msghdr msg;
 	struct kvec iov;
-	sigset_t blocked, oldset;
 	unsigned long pflags = current->flags;
 
 	if (unlikely(!sock)) {
@@ -181,11 +186,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
 		return -EINVAL;
 	}
 
-	/* Allow interception of SIGKILL only
-	 * Don't allow other signals to interrupt the transmission */
-	siginitsetinv(&blocked, sigmask(SIGKILL));
-	sigprocmask(SIG_SETMASK, &blocked, &oldset);
-
 	current->flags |= PF_MEMALLOC;
 	do {
 		sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
@@ -212,7 +212,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
 		buf += result;
 	} while (size > 0);
 
-	sigprocmask(SIG_SETMASK, &oldset, NULL);
 	tsk_restore_flags(current, pflags, PF_MEMALLOC);
 
 	if (!send && nbd->xmit_timeout)
@@ -406,23 +405,18 @@ static int nbd_thread_recv(struct nbd_device *nbd)
 {
 	struct request *req;
 	int ret;
-	unsigned long flags;
 
 	BUG_ON(nbd->magic != NBD_MAGIC);
 
 	sk_set_memalloc(nbd->sock->sk);
 
-	spin_lock_irqsave(&nbd->tasks_lock, flags);
 	nbd->task_recv = current;
-	spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
 	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
 	if (ret) {
 		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
 
-		spin_lock_irqsave(&nbd->tasks_lock, flags);
 		nbd->task_recv = NULL;
-		spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
 		return ret;
 	}
@@ -439,19 +433,7 @@ static int nbd_thread_recv(struct nbd_device *nbd)
 
 	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
 
-	spin_lock_irqsave(&nbd->tasks_lock, flags);
 	nbd->task_recv = NULL;
-	spin_unlock_irqrestore(&nbd->tasks_lock, flags);
-
-	if (signal_pending(current)) {
-		ret = kernel_dequeue_signal(NULL);
-		dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
-			 task_pid_nr(current), current->comm, ret);
-		mutex_lock(&nbd->tx_lock);
-		sock_shutdown(nbd);
-		mutex_unlock(&nbd->tx_lock);
-		ret = -ETIMEDOUT;
-	}
 
 	return ret;
 }
@@ -544,11 +526,8 @@ static int nbd_thread_send(void *data)
 {
 	struct nbd_device *nbd = data;
 	struct request *req;
-	unsigned long flags;
 
-	spin_lock_irqsave(&nbd->tasks_lock, flags);
 	nbd->task_send = current;
-	spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
 	set_user_nice(current, MIN_NICE);
 	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -557,17 +536,6 @@ static int nbd_thread_send(void *data)
 					 kthread_should_stop() ||
 					 !list_empty(&nbd->waiting_queue));
 
-		if (signal_pending(current)) {
-			int ret = kernel_dequeue_signal(NULL);
-
-			dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n",
-				 task_pid_nr(current), current->comm, ret);
-			mutex_lock(&nbd->tx_lock);
-			sock_shutdown(nbd);
-			mutex_unlock(&nbd->tx_lock);
-			break;
-		}
-
 		/* extract request */
 		if (list_empty(&nbd->waiting_queue))
 			continue;
@@ -582,13 +550,7 @@ static int nbd_thread_send(void *data)
 		nbd_handle_req(nbd, req);
 	}
 
-	spin_lock_irqsave(&nbd->tasks_lock, flags);
 	nbd->task_send = NULL;
-	spin_unlock_irqrestore(&nbd->tasks_lock, flags);
-
-	/* Clear maybe pending signals */
-	if (signal_pending(current))
-		kernel_dequeue_signal(NULL);
 
 	return 0;
 }
@@ -636,6 +598,25 @@ static void nbd_request_handler(struct request_queue *q)
 	}
 }
 
+static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock)
+{
+	int ret = 0;
+
+	spin_lock_irq(&nbd->sock_lock);
+
+	if (nbd->sock) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	nbd->sock = sock;
+
+out:
+	spin_unlock_irq(&nbd->sock_lock);
+
+	return ret;
+}
+
 static int nbd_dev_dbg_init(struct nbd_device *nbd);
 static void nbd_dev_dbg_close(struct nbd_device *nbd);
 
@@ -668,32 +649,26 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		return 0;
 	}
  
-	case NBD_CLEAR_SOCK: {
-		struct socket *sock = nbd->sock;
-		nbd->sock = NULL;
+	case NBD_CLEAR_SOCK:
+		sock_shutdown(nbd);
 		nbd_clear_que(nbd);
 		BUG_ON(!list_empty(&nbd->queue_head));
 		BUG_ON(!list_empty(&nbd->waiting_queue));
 		kill_bdev(bdev);
-		if (sock)
-			sockfd_put(sock);
 		return 0;
-	}
 
 	case NBD_SET_SOCK: {
-		struct socket *sock;
 		int err;
-		if (nbd->sock)
-			return -EBUSY;
-		sock = sockfd_lookup(arg, &err);
-		if (sock) {
-			nbd->sock = sock;
-			if (max_part > 0)
-				bdev->bd_invalidated = 1;
-			nbd->disconnect = false; /* we're connected now */
-			return 0;
-		}
-		return -EINVAL;
+		struct socket *sock = sockfd_lookup(arg, &err);
+
+		if (!sock)
+			return err;
+
+		err = nbd_set_socket(nbd, sock);
+		if (!err && max_part)
+			bdev->bd_invalidated = 1;
+
+		return err;
 	}
 
 	case NBD_SET_BLKSIZE:
@@ -734,7 +709,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 
 	case NBD_DO_IT: {
 		struct task_struct *thread;
-		struct socket *sock;
 		int error;
 
 		if (nbd->task_recv)
@@ -769,14 +743,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		mutex_lock(&nbd->tx_lock);
 
 		sock_shutdown(nbd);
-		sock = nbd->sock;
-		nbd->sock = NULL;
 		nbd_clear_que(nbd);
 		kill_bdev(bdev);
 		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
 		set_device_ro(bdev, false);
-		if (sock)
-			sockfd_put(sock);
 		nbd->flags = 0;
 		nbd->bytesize = 0;
 		bdev->bd_inode->i_size = 0;
@@ -1042,7 +1012,7 @@ static int __init nbd_init(void)
 		nbd_dev[i].magic = NBD_MAGIC;
 		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
 		spin_lock_init(&nbd_dev[i].queue_lock);
-		spin_lock_init(&nbd_dev[i].tasks_lock);
+		spin_lock_init(&nbd_dev[i].sock_lock);
 		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
 		mutex_init(&nbd_dev[i].tx_lock);
 		init_timer(&nbd_dev[i].timeout_timer);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/7] nbd: Timeouts are not user requested disconnects
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
  2016-02-21 14:01 ` [PATCH 1/7] nbd: Fix debugfs error handling Markus Pargmann
  2016-02-21 14:01 ` [PATCH 2/7] nbd: Remove signal usage Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-02-21 14:01 ` [PATCH 4/7] nbd: Cleanup reset of nbd and bdev after a disconnect Markus Pargmann
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel, Markus Pargmann

It may be useful to know in the client that a connection timed out. The
current code returns success for a timeout.

This patch reports the error code -ETIMEDOUT for a timeout.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 drivers/block/nbd.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 438f4dc549db..2e14e51b5ea3 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -57,6 +57,7 @@ struct nbd_device {
 	int blksize;
 	loff_t bytesize;
 	int xmit_timeout;
+	bool timedout;
 	bool disconnect; /* a disconnect has been requested by user */
 
 	struct timer_list timeout_timer;
@@ -154,10 +155,9 @@ static void nbd_xmit_timeout(unsigned long arg)
 	if (list_empty(&nbd->queue_head))
 		return;
 
-	nbd->disconnect = true;
-
 	spin_lock_irqsave(&nbd->sock_lock, flags);
 
+	nbd->timedout = true;
 
 	if (nbd->sock)
 		kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
@@ -754,7 +754,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		if (max_part > 0)
 			blkdev_reread_part(bdev);
 		if (nbd->disconnect) /* user requested, ignore socket errors */
-			return 0;
+			error = 0;
+		if (nbd->timedout)
+			error = -ETIMEDOUT;
+
 		return error;
 	}
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/7] nbd: Cleanup reset of nbd and bdev after a disconnect
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
                   ` (2 preceding siblings ...)
  2016-02-21 14:01 ` [PATCH 3/7] nbd: Timeouts are not user requested disconnects Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-02-21 14:01 ` [PATCH 5/7] nbd: Move flag parsing to a function Markus Pargmann
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel, Markus Pargmann

Group all variables that are reset after a disconnect into reset
functions. This patch adds two of these functions, nbd_reset() and
nbd_bdev_reset().

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 drivers/block/nbd.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 2e14e51b5ea3..34a46c32c24f 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -617,6 +617,30 @@ out:
 	return ret;
 }
 
+/* Reset all properties of an NBD device */
+static void nbd_reset(struct nbd_device *nbd)
+{
+	nbd->disconnect = false;
+	nbd->timedout = false;
+	nbd->blksize = 1024;
+	nbd->bytesize = 0;
+	set_capacity(nbd->disk, 0);
+	nbd->flags = 0;
+	nbd->xmit_timeout = 0;
+	queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
+	del_timer_sync(&nbd->timeout_timer);
+}
+
+static void nbd_bdev_reset(struct block_device *bdev)
+{
+	set_device_ro(bdev, false);
+	bdev->bd_inode->i_size = 0;
+	if (max_part > 0) {
+		blkdev_reread_part(bdev);
+		bdev->bd_invalidated = 1;
+	}
+}
+
 static int nbd_dev_dbg_init(struct nbd_device *nbd);
 static void nbd_dev_dbg_close(struct nbd_device *nbd);
 
@@ -745,19 +769,15 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		sock_shutdown(nbd);
 		nbd_clear_que(nbd);
 		kill_bdev(bdev);
-		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
-		set_device_ro(bdev, false);
-		nbd->flags = 0;
-		nbd->bytesize = 0;
-		bdev->bd_inode->i_size = 0;
-		set_capacity(nbd->disk, 0);
-		if (max_part > 0)
-			blkdev_reread_part(bdev);
+		nbd_bdev_reset(bdev);
+
 		if (nbd->disconnect) /* user requested, ignore socket errors */
 			error = 0;
 		if (nbd->timedout)
 			error = -ETIMEDOUT;
 
+		nbd_reset(nbd);
+
 		return error;
 	}
 
@@ -1023,14 +1043,12 @@ static int __init nbd_init(void)
 		nbd_dev[i].timeout_timer.data = (unsigned long)&nbd_dev[i];
 		init_waitqueue_head(&nbd_dev[i].active_wq);
 		init_waitqueue_head(&nbd_dev[i].waiting_wq);
-		nbd_dev[i].blksize = 1024;
-		nbd_dev[i].bytesize = 0;
 		disk->major = NBD_MAJOR;
 		disk->first_minor = i << part_shift;
 		disk->fops = &nbd_fops;
 		disk->private_data = &nbd_dev[i];
 		sprintf(disk->disk_name, "nbd%d", i);
-		set_capacity(disk, 0);
+		nbd_reset(&nbd_dev[i]);
 		add_disk(disk);
 	}
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/7] nbd: Move flag parsing to a function
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
                   ` (3 preceding siblings ...)
  2016-02-21 14:01 ` [PATCH 4/7] nbd: Cleanup reset of nbd and bdev after a disconnect Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-02-21 14:01 ` [PATCH 6/7] nbd: ratelimit error msgs after socket close Markus Pargmann
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel, Markus Pargmann

nbd changes properties of the blockdevice depending on flags that were
received. This patch moves this flag parsing into a separate function
nbd_parse_flags().

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 drivers/block/nbd.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 34a46c32c24f..b67500d5b338 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -641,6 +641,18 @@ static void nbd_bdev_reset(struct block_device *bdev)
 	}
 }
 
+static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev)
+{
+	if (nbd->flags & NBD_FLAG_READ_ONLY)
+		set_device_ro(bdev, true);
+	if (nbd->flags & NBD_FLAG_SEND_TRIM)
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
+	if (nbd->flags & NBD_FLAG_SEND_FLUSH)
+		blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
+	else
+		blk_queue_flush(nbd->disk->queue, 0);
+}
+
 static int nbd_dev_dbg_init(struct nbd_device *nbd);
 static void nbd_dev_dbg_close(struct nbd_device *nbd);
 
@@ -742,15 +754,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 
 		mutex_unlock(&nbd->tx_lock);
 
-		if (nbd->flags & NBD_FLAG_READ_ONLY)
-			set_device_ro(bdev, true);
-		if (nbd->flags & NBD_FLAG_SEND_TRIM)
-			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
-				nbd->disk->queue);
-		if (nbd->flags & NBD_FLAG_SEND_FLUSH)
-			blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
-		else
-			blk_queue_flush(nbd->disk->queue, 0);
+		nbd_parse_flags(nbd, bdev);
 
 		thread = kthread_run(nbd_thread_send, nbd, "%s",
 				     nbd_name(nbd));
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/7] nbd: ratelimit error msgs after socket close
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
                   ` (4 preceding siblings ...)
  2016-02-21 14:01 ` [PATCH 5/7] nbd: Move flag parsing to a function Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-02-21 14:01 ` [PATCH 7/7] nbd: Create size change events for userspace Markus Pargmann
  2016-03-03  7:48 ` [PULL] NBD for 4.6 Markus Pargmann
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-kernel, nbd-general, kernel, Dan Streetman, Markus Pargmann

From: Dan Streetman <dan.streetman@canonical.com>

Make the "Attempted send on closed socket" error messages generated in
nbd_request_handler() ratelimited.

When the nbd socket is shutdown, the nbd_request_handler() function emits
an error message for every request remaining in its queue.  If the queue
is large, this will spam a large amount of messages to the log.  There's
no need for a separate error message for each request, so this patch
ratelimits it.

In the specific case this was found, the system was virtual and the error
messages were logged to the serial port, which overwhelmed it.

Fixes: 4d48a542b427 ("nbd: fix I/O hang on disconnected nbds")
Signed-off-by: Dan Streetman <dan.streetman@canonical.com>
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 drivers/block/nbd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index b67500d5b338..4c5d94146aa3 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -580,8 +580,8 @@ static void nbd_request_handler(struct request_queue *q)
 			req, req->cmd_type);
 
 		if (unlikely(!nbd->sock)) {
-			dev_err(disk_to_dev(nbd->disk),
-				"Attempted send on closed socket\n");
+			dev_err_ratelimited(disk_to_dev(nbd->disk),
+					    "Attempted send on closed socket\n");
 			req->errors++;
 			nbd_end_request(nbd, req);
 			spin_lock_irq(q->queue_lock);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/7] nbd: Create size change events for userspace
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
                   ` (5 preceding siblings ...)
  2016-02-21 14:01 ` [PATCH 6/7] nbd: ratelimit error msgs after socket close Markus Pargmann
@ 2016-02-21 14:01 ` Markus Pargmann
  2016-03-03  7:48 ` [PULL] NBD for 4.6 Markus Pargmann
  7 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-02-21 14:01 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel, Markus Pargmann

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@pengutronix.de>
---
 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 4c5d94146aa3..f6b51d76e578 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -100,6 +100,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) {
@@ -112,6 +117,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;
@@ -401,7 +442,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;
@@ -421,6 +462,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)) {
@@ -431,6 +474,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;
@@ -707,20 +752,19 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		return err;
 	}
 
-	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;
@@ -736,13 +780,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;
 		int error;
@@ -764,7 +801,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.7.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PULL] NBD for 4.6
  2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
                   ` (6 preceding siblings ...)
  2016-02-21 14:01 ` [PATCH 7/7] nbd: Create size change events for userspace Markus Pargmann
@ 2016-03-03  7:48 ` Markus Pargmann
  2016-03-03 13:53   ` Jens Axboe
  7 siblings, 1 reply; 11+ messages in thread
From: Markus Pargmann @ 2016-03-03  7:48 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel

[-- Attachment #1: Type: text/plain, Size: 2144 bytes --]

Hi Jens,

On Sunday, February 21, 2016 03:01:20 PM Markus Pargmann wrote:
> Hi Jens,
> 
> This pull request contains 7 patches for 4.6.

any news on this pull request?

Best Regards,

Markus

> 
> Patch 1 fixes some unnecessarily complicated code I introduced some versions
> ago for debugfs.
> 
> Patch 2 removes the criticised signal usage within NBD to kill the NBD threads
> after a timeout. This code was used for the last years and is now replaced by
> simply killing the tcp connection.
> 
> Patches 3-6 are some smaller cleanups.
> 
> Patch 7 uevents for the userspace. This way udev/systemd can react on connected
> NBD devices.
> 
> Best Regards,
> 
> Markus
> 
> 
> 
> The following changes since commit 92e963f50fc74041b5e9e744c330dca48e04f08d:
> 
>   Linux 4.5-rc1 (2016-01-24 13:06:47 -0800)
> 
> are available in the git repository at:
> 
>   git://git.pengutronix.de/git/mpa/linux-nbd.git tags/nbd-for-4.6
> 
> for you to fetch changes up to 37091fdd831f28a6509008542174ed324dd645bc:
> 
>   nbd: Create size change events for userspace (2016-02-15 10:35:47 +0100)
> 
> ----------------------------------------------------------------
> NBD for 4.6
> 
> ----------------------------------------------------------------
> Dan Streetman (1):
>       nbd: ratelimit error msgs after socket close
> 
> Markus Pargmann (6):
>       nbd: Fix debugfs error handling
>       nbd: Remove signal usage
>       nbd: Timeouts are not user requested disconnects
>       nbd: Cleanup reset of nbd and bdev after a disconnect
>       nbd: Move flag parsing to a function
>       nbd: Create size change events for userspace
> 
>  drivers/block/nbd.c | 335 ++++++++++++++++++++++++++--------------------------
>  1 file changed, 170 insertions(+), 165 deletions(-)
> 
> 

-- 
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 #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PULL] NBD for 4.6
  2016-03-03  7:48 ` [PULL] NBD for 4.6 Markus Pargmann
@ 2016-03-03 13:53   ` Jens Axboe
  2016-03-03 15:04     ` Markus Pargmann
  0 siblings, 1 reply; 11+ messages in thread
From: Jens Axboe @ 2016-03-03 13:53 UTC (permalink / raw)
  To: Markus Pargmann; +Cc: linux-kernel, nbd-general, kernel

On 03/03/2016 12:48 AM, Markus Pargmann wrote:
> Hi Jens,
>
> On Sunday, February 21, 2016 03:01:20 PM Markus Pargmann wrote:
>> Hi Jens,
>>
>> This pull request contains 7 patches for 4.6.
>
> any news on this pull request?

Sorry for the delay, pulled in, thanks.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PULL] NBD for 4.6
  2016-03-03 13:53   ` Jens Axboe
@ 2016-03-03 15:04     ` Markus Pargmann
  0 siblings, 0 replies; 11+ messages in thread
From: Markus Pargmann @ 2016-03-03 15:04 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-kernel, nbd-general, kernel

[-- Attachment #1: Type: text/plain, Size: 762 bytes --]

Hi,

On Thursday, March 03, 2016 06:53:28 AM Jens Axboe wrote:
> On 03/03/2016 12:48 AM, Markus Pargmann wrote:
> > Hi Jens,
> >
> > On Sunday, February 21, 2016 03:01:20 PM Markus Pargmann wrote:
> >> Hi Jens,
> >>
> >> This pull request contains 7 patches for 4.6.
> >
> > any news on this pull request?
> 
> Sorry for the delay, pulled in, thanks.

Thanks, I was just nervous to miss the merge window :).

Best Regards,

Markus

-- 
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 #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-03-03 15:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-21 14:01 [PULL] NBD for 4.6 Markus Pargmann
2016-02-21 14:01 ` [PATCH 1/7] nbd: Fix debugfs error handling Markus Pargmann
2016-02-21 14:01 ` [PATCH 2/7] nbd: Remove signal usage Markus Pargmann
2016-02-21 14:01 ` [PATCH 3/7] nbd: Timeouts are not user requested disconnects Markus Pargmann
2016-02-21 14:01 ` [PATCH 4/7] nbd: Cleanup reset of nbd and bdev after a disconnect Markus Pargmann
2016-02-21 14:01 ` [PATCH 5/7] nbd: Move flag parsing to a function Markus Pargmann
2016-02-21 14:01 ` [PATCH 6/7] nbd: ratelimit error msgs after socket close Markus Pargmann
2016-02-21 14:01 ` [PATCH 7/7] nbd: Create size change events for userspace Markus Pargmann
2016-03-03  7:48 ` [PULL] NBD for 4.6 Markus Pargmann
2016-03-03 13:53   ` Jens Axboe
2016-03-03 15:04     ` Markus Pargmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).