[RFC 2/4] nbd: Split 'DO_IT' into three functions
From: Markus Pargmann
Date: Tue Jan 13 2015 - 08:45:10 EST
The DO_IT ioctl does a lot of things to handle the connection. This
patch splits the DO_IT ioctl routine into three functions
nbd_connection_start()/run()/stop(). This makes it easier to read and
allows other functions to call the same code. This patch prepares the
DO_IT code for nbd-root device.
Signed-off-by: Markus Pargmann <mpa@xxxxxxxxxxxxxx>
---
drivers/block/nbd.c | 146 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 91 insertions(+), 55 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 6bd7df2ff648..0ff6ebbec252 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -596,6 +596,95 @@ static void do_nbd_request(struct request_queue *q)
}
}
+static int nbd_connection_start(struct block_device *bdev,
+ struct nbd_device *nbd)
+{
+ 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);
+ return 0;
+}
+
+static int nbd_connection_run(struct nbd_device *nbd)
+{
+ struct task_struct *thread;
+ int error;
+
+ thread = kthread_run(nbd_thread, nbd, "%s", nbd->disk->disk_name);
+ if (IS_ERR(thread)) {
+ mutex_lock(&nbd->tx_lock);
+ return PTR_ERR(thread);
+ }
+
+ error = nbd_do_it(nbd);
+
+ kthread_stop(thread);
+
+ return error;
+}
+
+/*
+ * Call with tx_lock held
+ */
+static int nbd_connection_stop(struct block_device *bdev,
+ struct nbd_device *nbd)
+{
+ struct socket *sock;
+
+ sock_shutdown(nbd, 0);
+ sock = nbd->sock;
+ nbd->sock = NULL;
+ nbd_clear_que(nbd);
+ dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
+ 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;
+ set_capacity(nbd->disk, 0);
+
+ if (max_part > 0)
+ ioctl_by_bdev(bdev, BLKRRPART, 0);
+ if (nbd->disconnect) /* user requested, ignore socket errors */
+ return 0;
+
+ return nbd->harderror;
+}
+
+/*
+ * Call with tx_lock held
+ */
+static int nbd_connection_handler(struct block_device *bdev,
+ struct nbd_device *nbd)
+{
+ int error;
+
+ mutex_unlock(&nbd->tx_lock);
+
+ error = nbd_connection_start(bdev, nbd);
+ if (error)
+ return error;
+
+ error = nbd_connection_run(nbd);
+
+ mutex_lock(&nbd->tx_lock);
+ if (error)
+ return error;
+
+ error = nbd_connection_stop(bdev, nbd);
+
+ return error;
+}
+
/* Must be called with tx_lock held */
static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
@@ -684,61 +773,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
set_capacity(nbd->disk, nbd->bytesize >> 9);
return 0;
- case NBD_DO_IT: {
- struct task_struct *thread;
- struct socket *sock;
- int error;
-
- if (nbd->pid)
- return -EBUSY;
- if (!nbd->sock)
- return -EINVAL;
-
- 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);
-
- thread = kthread_run(nbd_thread, nbd, "%s",
- nbd->disk->disk_name);
- if (IS_ERR(thread)) {
- mutex_lock(&nbd->tx_lock);
- return PTR_ERR(thread);
- }
-
- error = nbd_do_it(nbd);
- kthread_stop(thread);
-
- mutex_lock(&nbd->tx_lock);
- if (error)
- return error;
- sock_shutdown(nbd, 0);
- sock = nbd->sock;
- nbd->sock = NULL;
- nbd_clear_que(nbd);
- dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
- 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;
- set_capacity(nbd->disk, 0);
- if (max_part > 0)
- ioctl_by_bdev(bdev, BLKRRPART, 0);
- if (nbd->disconnect) /* user requested, ignore socket errors */
- return 0;
- return nbd->harderror;
- }
+ case NBD_DO_IT:
+ return nbd_connection_handler(bdev, nbd);
case NBD_CLEAR_QUE:
/*
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/