11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Network block device - make block devices work over TCP
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that you can not swap over this thing, yet. Seems to work but
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * deadlocks sometimes - you can not swap over TCP in general.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7a2531293dbb7608fa672ff28efe3ab4027917a2fPavel Machek * Copyright 1997-2000, 2008 Pavel Machek <pavel@ucw.cz>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10dbf492d6c1a1bf5a8bda40274f479119f4c42ca4Pavel Machek * This file is released under GPLv2 or later.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12dbf492d6c1a1bf5a8bda40274f479119f4c42ca4Pavel Machek * (part of code stolen from loop.c)
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bio.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/file.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioctl.h>
272a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann#include <linux/mutex.h>
284b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <linux/compiler.h>
294b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <linux/err.h>
304b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <linux/kernel.h>
315a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sock.h>
3391cf45f02af5c871251165d000c3f42a2a0b0552Trond Myklebust#include <linux/net.h>
3448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier#include <linux/kthread.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/types.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/nbd.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao#define NBD_MAGIC 0x68797548
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NDEBUG
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(flags, fmt...)
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* NDEBUG */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(flags, fmt...) do { \
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (debugflags & (flags)) printk(KERN_DEBUG fmt); \
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} while (0)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_IOCTL       0x0004
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_INIT        0x0010
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_EXIT        0x0020
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_BLKDEV      0x0100
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_RX          0x0200
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_TX          0x0400
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int debugflags;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NDEBUG */
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
589c7a41691f37a1538a88e5eb9b0b73df1f834542Ingo van Lilstatic unsigned int nbds_max = 16;
5920a8143eaa3300a58326156eaf43e03db0fd2cb6Paul Clementsstatic struct nbd_device *nbd_dev;
60d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivierstatic int max_part;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use just one lock (or at most 1 per NIC). Two arguments for this:
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Each NIC is essentially a synchronization point for all servers
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    accessed through that NIC so there's no need to have more locks
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    than NICs anyway.
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. More locks lead to more "Dirty cache line bouncing" which will slow
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    down each lock to the point where they're actually slower than just
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    a single lock.
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this!
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(nbd_lock);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NDEBUG
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *ioctl_cmd_to_ascii(int cmd)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SOCK: return "set-sock";
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_BLKSIZE: return "set-blksize";
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE: return "set-size";
812f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements	case NBD_SET_TIMEOUT: return "set-timeout";
822f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements	case NBD_SET_FLAGS: return "set-flags";
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_DO_IT: return "do-it";
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_SOCK: return "clear-sock";
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_QUE: return "clear-que";
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_PRINT_DEBUG: return "print-debug";
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE_BLOCKS: return "set-size-blocks";
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_DISCONNECT: return "disconnect";
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BLKROSET: return "set-read-only";
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BLKFLSBUF: return "flush-buffer-cache";
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return "unknown";
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *nbdcmd_to_ascii(int cmd)
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  NBD_CMD_READ: return "read";
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CMD_WRITE: return "write";
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  NBD_CMD_DISC: return "disconnect";
10175f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	case NBD_CMD_FLUSH: return "flush";
102a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements	case  NBD_CMD_TRIM: return "trim/discard";
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return "invalid";
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NDEBUG */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void nbd_end_request(struct request *req)
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
110097c94a4e8bde978c8d12683d9a34048e9139e4bKiyoshi Ueda	int error = req->errors ? -EIO : 0;
111165125e1e480f9510a5ffcfbfee4e3ee38c05f23Jens Axboe	struct request_queue *q = req->q;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
115097c94a4e8bde978c8d12683d9a34048e9139e4bKiyoshi Ueda			req, error ? "failed" : "done");
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(q->queue_lock, flags);
1181011c1b9f2e45ce7c6e38888d2b83936aec38771Tejun Heo	__blk_end_request_all(req, error);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(q->queue_lock, flags);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void sock_shutdown(struct nbd_device *nbd, int lock)
1237fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements{
1247fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	/* Forcibly shutdown the socket causing all listeners
1257fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * to error
1267fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 *
1277fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * FIXME: This code is duplicated from sys_shutdown, but
1287fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * there should be a more generic interface rather than
1297fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * calling socket ops directly here */
1307fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	if (lock)
131f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_lock(&nbd->tx_lock);
132f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	if (nbd->sock) {
133f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
134f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
135f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->sock = NULL;
1367fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	}
1377fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	if (lock)
138f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_unlock(&nbd->tx_lock);
1397fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements}
1407fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1417fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clementsstatic void nbd_xmit_timeout(unsigned long arg)
1427fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements{
1437fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	struct task_struct *task = (struct task_struct *)arg;
1447fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1457fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d)\n",
1467fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		task->comm, task->pid);
1477fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	force_sig(SIGKILL, task);
1487fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements}
1497fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Send or receive packet.
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
153f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int msg_flags)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
156f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	struct socket *sock = nbd->sock;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct msghdr msg;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kvec iov;
160be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	sigset_t blocked, oldset;
1617f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman	unsigned long pflags = current->flags;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
163ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer	if (unlikely(!sock)) {
164f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
1657f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Attempted %s on closed socket in sock_xmit\n",
1667f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			(send ? "send" : "recv"));
167ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer		return -EINVAL;
168ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer	}
169ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow interception of SIGKILL only
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Don't allow other signals to interrupt the transmission */
172be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	siginitsetinv(&blocked, sigmask(SIGKILL));
173be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	sigprocmask(SIG_SETMASK, &blocked, &oldset);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1757f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman	current->flags |= PF_MEMALLOC;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
1777f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman		sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov.iov_base = buf;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov.iov_len = size;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_name = NULL;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_namelen = 0;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_control = NULL;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_controllen = 0;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_flags = msg_flags | MSG_NOSIGNAL;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1867fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		if (send) {
1877fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			struct timer_list ti;
1887fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
189f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			if (nbd->xmit_timeout) {
1907fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				init_timer(&ti);
1917fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				ti.function = nbd_xmit_timeout;
1927fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				ti.data = (unsigned long)current;
193f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao				ti.expires = jiffies + nbd->xmit_timeout;
1947fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				add_timer(&ti);
1957fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = kernel_sendmsg(sock, &msg, &iov, 1, size);
197f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			if (nbd->xmit_timeout)
1987fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				del_timer_sync(&ti);
1997fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		} else
20035fbf5bcf497d6ddbe7b6478141e7526d1474ff5Namhyung Kim			result = kernel_recvmsg(sock, &msg, &iov, 1, size,
20135fbf5bcf497d6ddbe7b6478141e7526d1474ff5Namhyung Kim						msg.msg_flags);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (signal_pending(current)) {
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			siginfo_t info;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
206ba25f9dcc4ea6e30839fcab5a5516f2176d5bfedPavel Emelyanov				task_pid_nr(current), current->comm,
207be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov				dequeue_signal_lock(current, &current->blocked, &info));
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = -EINTR;
209f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			sock_shutdown(nbd, !send);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (result <= 0) {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (result == 0)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				result = -EPIPE; /* short read */
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size -= result;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buf += result;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (size > 0);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	sigprocmask(SIG_SETMASK, &oldset, NULL);
2237f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman	tsk_restore_flags(current, pflags, PF_MEMALLOC);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
228f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec,
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int flags)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *kaddr = kmap(bvec->bv_page);
233f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset,
234f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			   bvec->bv_len, flags);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(bvec->bv_page);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2397fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements/* always call with the tx_lock held */
240f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int nbd_send_req(struct nbd_device *nbd, struct request *req)
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2425705f7021748a69d84d6567e68e8851dab551464NeilBrown	int result, flags;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nbd_request request;
2441011c1b9f2e45ce7c6e38888d2b83936aec38771Tejun Heo	unsigned long size = blk_rq_bytes(req);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24604cfac4e40b2b5dbaf8c0fc625878388a98bb9c6Hani Benhabiles	memset(&request, 0, sizeof(request));
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.magic = htonl(NBD_REQUEST_MAGIC);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.type = htonl(nbd_cmd(req));
24975f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh
25004cfac4e40b2b5dbaf8c0fc625878388a98bb9c6Hani Benhabiles	if (nbd_cmd(req) != NBD_CMD_FLUSH && nbd_cmd(req) != NBD_CMD_DISC) {
25175f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
25275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		request.len = htonl(size);
25375f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(request.handle, &req, sizeof(req));
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25683096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n",
257f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			nbd->disk->disk_name, req,
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nbdcmd_to_ascii(nbd_cmd(req)),
25983096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo			(unsigned long long)blk_rq_pos(req) << 9,
2601011c1b9f2e45ce7c6e38888d2b83936aec38771Tejun Heo			blk_rq_bytes(req));
261f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 1, &request, sizeof(request),
2627fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result <= 0) {
264f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
2657f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Send control failed (result %d)\n", result);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_out;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nbd_cmd(req) == NBD_CMD_WRITE) {
2705705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct req_iterator iter;
2717988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet		struct bio_vec bvec;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we are really probing at internals to determine
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * whether to set MSG_MORE or not...
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2765705f7021748a69d84d6567e68e8851dab551464NeilBrown		rq_for_each_segment(bvec, req, iter) {
2776c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			flags = 0;
2784550dd6c6b062fc5e5b647296d55da22616123c3Kent Overstreet			if (!rq_iter_last(bvec, iter))
2796c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				flags = MSG_MORE;
2806c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
2817988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet					nbd->disk->disk_name, req, bvec.bv_len);
2827988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet			result = sock_send_bvec(nbd, &bvec, flags);
2836c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (result <= 0) {
284f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao				dev_err(disk_to_dev(nbd->disk),
2857f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong					"Send data failed (result %d)\n",
2867f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong					result);
2876c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				goto error_out;
2886c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror_out:
29415746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek	return -EIO;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
297f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic struct request *nbd_find_request(struct nbd_device *nbd,
2980cbc591bf884a5662b2fbb21b5c09fa1c1c7b579Denis Cheng					struct request *xreq)
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
300d2c9740b499f959ed513375b6e35c2ab161921cbDenis Cheng	struct request *req, *tmp;
3014b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	int err;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
303f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq);
3044b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	if (unlikely(err))
3054b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		goto out;
3064b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
307f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	spin_lock(&nbd->queue_lock);
308f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) {
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (req != xreq)
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&req->queuelist);
312f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock(&nbd->queue_lock);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return req;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
315f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	spin_unlock(&nbd->queue_lock);
3164b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3174b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	err = -ENOENT;
3184b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3194b2f0260c74324abca76ccaa42d426af163125e7Herbert Xuout:
3204b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	return ERR_PTR(err);
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
323f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *kaddr = kmap(bvec->bv_page);
327f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MSG_WAITALL);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(bvec->bv_page);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* NULL returned = something went wrong, inform userspace */
334f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic struct request *nbd_read_stat(struct nbd_device *nbd)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nbd_reply reply;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	reply.magic = 0;
341f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result <= 0) {
343f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
3447f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Receive control failed (result %d)\n", result);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto harderror;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
347e4b57e0842621f597d744b193ea325d62724596bMichal Feix
348e4b57e0842621f597d744b193ea325d62724596bMichal Feix	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
349f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)\n",
350e4b57e0842621f597d744b193ea325d62724596bMichal Feix				(unsigned long)ntohl(reply.magic));
351e4b57e0842621f597d744b193ea325d62724596bMichal Feix		result = -EPROTO;
352e4b57e0842621f597d744b193ea325d62724596bMichal Feix		goto harderror;
353e4b57e0842621f597d744b193ea325d62724596bMichal Feix	}
354e4b57e0842621f597d744b193ea325d62724596bMichal Feix
355f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	req = nbd_find_request(nbd, *(struct request **)reply.handle);
356801678c5a3b4c79236970bcca27c733f5559e0d1Hirofumi Nakagawa	if (IS_ERR(req)) {
3574b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		result = PTR_ERR(req);
3584b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		if (result != -ENOENT)
3594b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu			goto harderror;
3604b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
361f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p)\n",
3627f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			reply.handle);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = -EBADR;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto harderror;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ntohl(reply.error)) {
368f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
3697f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			ntohl(reply.error));
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		req->errors++;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return req;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_RX, "%s: request %p: got reply\n",
375f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			nbd->disk->disk_name, req);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nbd_cmd(req) == NBD_CMD_READ) {
3775705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct req_iterator iter;
3787988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet		struct bio_vec bvec;
3795705f7021748a69d84d6567e68e8851dab551464NeilBrown
3805705f7021748a69d84d6567e68e8851dab551464NeilBrown		rq_for_each_segment(bvec, req, iter) {
3817988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet			result = sock_recv_bvec(nbd, &bvec);
3826c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (result <= 0) {
383f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao				dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
3847f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong					result);
3856c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				req->errors++;
3866c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				return req;
3876c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			}
3886c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
3897988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet				nbd->disk->disk_name, req, bvec.bv_len);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return req;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsharderror:
394f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->harderror = result;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
398edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t pid_show(struct device *dev,
399edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers			struct device_attribute *attr, char *buf)
4006b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements{
401edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers	struct gendisk *disk = dev_to_disk(dev);
402edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers
403edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers	return sprintf(buf, "%ld\n",
4046b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements		(long) ((struct nbd_device *)disk->private_data)->pid);
4056b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements}
4066b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
407edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute pid_attr = {
40801e8ef11bc1a74e65678ed55795f59266d4add01Parag Warudkar	.attr = { .name = "pid", .mode = S_IRUGO},
4096b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements	.show = pid_show,
4106b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements};
4116b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
412f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int nbd_do_it(struct nbd_device *nbd)
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
41584963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	int ret;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
417f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->magic != NBD_MAGIC);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4197f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman	sk_set_memalloc(nbd->sock->sk);
420f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->pid = task_pid_nr(current);
421f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
42284963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	if (ret) {
423f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
424f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->pid = 0;
42584963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		return ret;
42684963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	}
4276b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
428f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	while ((req = nbd_read_stat(nbd)) != NULL)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_end_request(req);
4306b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
431f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
432f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->pid = 0;
43384963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	return 0;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
436f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void nbd_clear_que(struct nbd_device *nbd)
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
440f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->magic != NBD_MAGIC);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4424b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	/*
443f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	 * Because we have set nbd->sock to NULL under the tx_lock, all
4444b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * modifications to the list must have completed by now.  For
4454b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * the same reason, the active_req must be NULL.
4464b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 *
4474b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * As a consequence, we don't need to take the spin lock while
4484b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * purging the list here.
4494b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 */
450f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->sock);
451f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->active_req);
4524b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
453f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	while (!list_empty(&nbd->queue_head)) {
454f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		req = list_entry(nbd->queue_head.next, struct request,
4554b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu				 queuelist);
4564b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		list_del_init(&req->queuelist);
4574b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		req->errors++;
4584b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		nbd_end_request(req);
4594b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	}
460fded4e090c60100d709318896c79816d68d5b47dPaul Clements
461fded4e090c60100d709318896c79816d68d5b47dPaul Clements	while (!list_empty(&nbd->waiting_queue)) {
462fded4e090c60100d709318896c79816d68d5b47dPaul Clements		req = list_entry(nbd->waiting_queue.next, struct request,
463fded4e090c60100d709318896c79816d68d5b47dPaul Clements				 queuelist);
464fded4e090c60100d709318896c79816d68d5b47dPaul Clements		list_del_init(&req->queuelist);
465fded4e090c60100d709318896c79816d68d5b47dPaul Clements		req->errors++;
466fded4e090c60100d709318896c79816d68d5b47dPaul Clements		nbd_end_request(req);
467fded4e090c60100d709318896c79816d68d5b47dPaul Clements	}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4707fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
471f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void nbd_handle_req(struct nbd_device *nbd, struct request *req)
47248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{
47333659ebbae262228eef4e0fe990f393d1f0ed941Christoph Hellwig	if (req->cmd_type != REQ_TYPE_FS)
47448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		goto error_out;
47548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
47648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	nbd_cmd(req) = NBD_CMD_READ;
47748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	if (rq_data_dir(req) == WRITE) {
478a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		if ((req->cmd_flags & REQ_DISCARD)) {
479a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM));
480a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			nbd_cmd(req) = NBD_CMD_TRIM;
481a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		} else
482a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			nbd_cmd(req) = NBD_CMD_WRITE;
4832f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements		if (nbd->flags & NBD_FLAG_READ_ONLY) {
484f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			dev_err(disk_to_dev(nbd->disk),
4857f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong				"Write on read-only\n");
48648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			goto error_out;
48748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		}
48848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
48948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
49075f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	if (req->cmd_flags & REQ_FLUSH) {
49175f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		BUG_ON(unlikely(blk_rq_sectors(req)));
49275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		nbd_cmd(req) = NBD_CMD_FLUSH;
49375f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	}
49475f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh
49548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	req->errors = 0;
49648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
497f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_lock(&nbd->tx_lock);
498f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	if (unlikely(!nbd->sock)) {
499f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_unlock(&nbd->tx_lock);
500f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
5017f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Attempted send on closed socket\n");
50215746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek		goto error_out;
50348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
50448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
505f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->active_req = req;
50648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
507f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	if (nbd_send_req(nbd, req) != 0) {
508f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Request send failed\n");
50948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		req->errors++;
51048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		nbd_end_request(req);
51148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	} else {
512f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_lock(&nbd->queue_lock);
51301ff5dbc0925d11c8ad76eed3bdd02d0c7e1e0f5Chetan Loke		list_add_tail(&req->queuelist, &nbd->queue_head);
514f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock(&nbd->queue_lock);
51548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
51648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
517f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->active_req = NULL;
518f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_unlock(&nbd->tx_lock);
519f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	wake_up_all(&nbd->active_wq);
52048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
52148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	return;
52248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
52348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Viviererror_out:
52448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	req->errors++;
52548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	nbd_end_request(req);
52648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier}
52748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
52848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivierstatic int nbd_thread(void *data)
52948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{
530f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	struct nbd_device *nbd = data;
53148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	struct request *req;
53248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5338698a745d800c59cd5a576398bdeccd578ac66f1Dongsheng Yang	set_user_nice(current, MIN_NICE);
534f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
53548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* wait for something to do */
536f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		wait_event_interruptible(nbd->waiting_wq,
53748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier					 kthread_should_stop() ||
538f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao					 !list_empty(&nbd->waiting_queue));
53948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
54048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* extract request */
541f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (list_empty(&nbd->waiting_queue))
54248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			continue;
54348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
544f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_lock_irq(&nbd->queue_lock);
545f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		req = list_entry(nbd->waiting_queue.next, struct request,
54648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier				 queuelist);
54748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		list_del_init(&req->queuelist);
548f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock_irq(&nbd->queue_lock);
54948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
55048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* handle request */
551f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_handle_req(nbd, req);
55248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
55348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	return 0;
55448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier}
55548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We always wait for result of write, for now. It would be nice to make it optional
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in future
559f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao * if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK))
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56315746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machekstatic void do_nbd_request(struct request_queue *q)
564398eb08555b24049e0362fee92920982b283fd96Alex Elder		__releases(q->queue_lock) __acquires(q->queue_lock)
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5689934c8c04561413609d2bc38c6b9f268cba774a4Tejun Heo	while ((req = blk_fetch_request(q)) != NULL) {
569f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		struct nbd_device *nbd;
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_unlock_irq(q->queue_lock);
57248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5734aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe		dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
5744aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe				req->rq_disk->disk_name, req, req->cmd_type);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd = req->rq_disk->private_data;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
578f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		BUG_ON(nbd->magic != NBD_MAGIC);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
580f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (unlikely(!nbd->sock)) {
581f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			dev_err(disk_to_dev(nbd->disk),
5827f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong				"Attempted send on closed socket\n");
5834d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			req->errors++;
5844d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			nbd_end_request(req);
5854d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			spin_lock_irq(q->queue_lock);
5864d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			continue;
5874d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements		}
5884d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements
589f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_lock_irq(&nbd->queue_lock);
590f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		list_add_tail(&req->queuelist, &nbd->waiting_queue);
591f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock_irq(&nbd->queue_lock);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
593f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		wake_up(&nbd->waiting_wq);
5944b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irq(q->queue_lock);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek/* Must be called with tx_lock held */
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
6021a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		       unsigned int cmd, unsigned long arg)
6031a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
6051a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_DISCONNECT: {
6061a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct request sreq;
6071a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
608f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
6093a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		if (!nbd->sock)
6103a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini			return -EINVAL;
6111a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6123a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		mutex_unlock(&nbd->tx_lock);
6133a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		fsync_bdev(bdev);
6143a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		mutex_lock(&nbd->tx_lock);
6154f54eec8311c3325888c29ce8e4496daf4dbe624FUJITA Tomonori		blk_rq_init(NULL, &sreq);
6164aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe		sreq.cmd_type = REQ_TYPE_SPECIAL;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_cmd(&sreq) = NBD_CMD_DISC;
6183a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini
6193a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		/* Check again after getting mutex back.  */
620f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (!nbd->sock)
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6223a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini
623c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements		nbd->disconnect = 1;
624c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements
625f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_send_req(nbd, &sreq);
626c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements		return 0;
6271a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_CLEAR_SOCK: {
630e25115786ee540fc428a14872ebd4f56252aba32Al Viro		struct socket *sock = nbd->sock;
631f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->sock = NULL;
632f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_clear_que(nbd);
633f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		BUG_ON(!list_empty(&nbd->queue_head));
634fded4e090c60100d709318896c79816d68d5b47dPaul Clements		BUG_ON(!list_empty(&nbd->waiting_queue));
6353a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		kill_bdev(bdev);
636e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (sock)
637e25115786ee540fc428a14872ebd4f56252aba32Al Viro			sockfd_put(sock);
6381a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return 0;
6391a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6401a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6411a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_SET_SOCK: {
642e25115786ee540fc428a14872ebd4f56252aba32Al Viro		struct socket *sock;
643e25115786ee540fc428a14872ebd4f56252aba32Al Viro		int err;
644e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (nbd->sock)
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBUSY;
646e25115786ee540fc428a14872ebd4f56252aba32Al Viro		sock = sockfd_lookup(arg, &err);
647e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (sock) {
648e25115786ee540fc428a14872ebd4f56252aba32Al Viro			nbd->sock = sock;
649e25115786ee540fc428a14872ebd4f56252aba32Al Viro			if (max_part > 0)
650e25115786ee540fc428a14872ebd4f56252aba32Al Viro				bdev->bd_invalidated = 1;
651e25115786ee540fc428a14872ebd4f56252aba32Al Viro			nbd->disconnect = 0; /* we're connected now */
652e25115786ee540fc428a14872ebd4f56252aba32Al Viro			return 0;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6541a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return -EINVAL;
6551a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6561a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_BLKSIZE:
658f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->blksize = arg;
659f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize &= ~(nbd->blksize-1);
660f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		bdev->bd_inode->i_size = nbd->bytesize;
661f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_blocksize(bdev, nbd->blksize);
662f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, nbd->bytesize >> 9);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6641a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE:
666f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize = arg & ~(nbd->blksize-1);
667f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		bdev->bd_inode->i_size = nbd->bytesize;
668f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_blocksize(bdev, nbd->blksize);
669f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, nbd->bytesize >> 9);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6727fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	case NBD_SET_TIMEOUT:
673f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->xmit_timeout = arg * HZ;
6747fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		return 0;
6751a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6762f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements	case NBD_SET_FLAGS:
6772f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements		nbd->flags = arg;
6782f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements		return 0;
6792f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE_BLOCKS:
681f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize = ((u64) arg) * nbd->blksize;
682f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		bdev->bd_inode->i_size = nbd->bytesize;
683f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_blocksize(bdev, nbd->blksize);
684f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, nbd->bytesize >> 9);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6861a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6871a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_DO_IT: {
6881a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct task_struct *thread;
689e25115786ee540fc428a14872ebd4f56252aba32Al Viro		struct socket *sock;
6901a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		int error;
6911a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
692f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (nbd->pid)
693c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek			return -EBUSY;
694e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (!nbd->sock)
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6961a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
697f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_unlock(&nbd->tx_lock);
6981a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
699a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini		if (nbd->flags & NBD_FLAG_READ_ONLY)
700a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini			set_device_ro(bdev, true);
701a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		if (nbd->flags & NBD_FLAG_SEND_TRIM)
702a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
703a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements				nbd->disk->queue);
70475f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		if (nbd->flags & NBD_FLAG_SEND_FLUSH)
70575f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh			blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
70675f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		else
70775f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh			blk_queue_flush(nbd->disk->queue, 0);
708a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements
709ffc8b30866879ed9ba62bd0a86fecdbd51cd3d19Kees Cook		thread = kthread_create(nbd_thread, nbd, "%s",
710ffc8b30866879ed9ba62bd0a86fecdbd51cd3d19Kees Cook					nbd->disk->disk_name);
7111a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		if (IS_ERR(thread)) {
712f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			mutex_lock(&nbd->tx_lock);
71348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			return PTR_ERR(thread);
7141a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		}
71548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		wake_up_process(thread);
716f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		error = nbd_do_it(nbd);
71748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		kthread_stop(thread);
7181a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
719f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_lock(&nbd->tx_lock);
72084963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		if (error)
72184963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong			return error;
722f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		sock_shutdown(nbd, 0);
723e25115786ee540fc428a14872ebd4f56252aba32Al Viro		sock = nbd->sock;
724e25115786ee540fc428a14872ebd4f56252aba32Al Viro		nbd->sock = NULL;
725f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_clear_que(nbd);
726f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
7273a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		kill_bdev(bdev);
728a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
729a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini		set_device_ro(bdev, false);
730e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (sock)
731e25115786ee540fc428a14872ebd4f56252aba32Al Viro			sockfd_put(sock);
73275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		nbd->flags = 0;
733f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize = 0;
734a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		bdev->bd_inode->i_size = 0;
735f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, 0);
736d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		if (max_part > 0)
737a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro			ioctl_by_bdev(bdev, BLKRRPART, 0);
738c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements		if (nbd->disconnect) /* user requested, ignore socket errors */
739c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements			return 0;
740f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		return nbd->harderror;
7411a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
7421a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_QUE:
7444b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		/*
7454b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 * This is for compatibility only.  The queue is always cleared
7464b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 * by NBD_DO_IT or NBD_CLEAR_SOCK.
7474b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 */
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7491a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_PRINT_DEBUG:
751f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_info(disk_to_dev(nbd->disk),
7525eedf5415cd57f8db8642a5db4cf8e5507390030WANG Cong			"next = %p, prev = %p, head = %p\n",
753f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			nbd->queue_head.next, nbd->queue_head.prev,
754f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			&nbd->queue_head);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7571a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	return -ENOTTY;
7581a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek}
7591a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7601a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machekstatic int nbd_ioctl(struct block_device *bdev, fmode_t mode,
7611a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		     unsigned int cmd, unsigned long arg)
7621a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{
763f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	struct nbd_device *nbd = bdev->bd_disk->private_data;
7641a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	int error;
7651a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7661a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	if (!capable(CAP_SYS_ADMIN))
7671a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return -EPERM;
7681a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
769f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->magic != NBD_MAGIC);
7701a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	/* Anyone capable of this syscall can do *real bad* things */
7721a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
773f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
7741a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
775f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_lock(&nbd->tx_lock);
776f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	error = __nbd_ioctl(bdev, nbd, cmd, arg);
777f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_unlock(&nbd->tx_lock);
7781a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7791a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	return error;
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
78283d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations nbd_fops =
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner =	THIS_MODULE,
7858a6cfeb6deca3a8fefd639d898b0d163c0b5d368Arnd Bergmann	.ioctl =	nbd_ioctl,
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And here should be modules and kernel interface
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  (Just smiley confuses emacs :-)
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init nbd_init(void)
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -ENOMEM;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
797d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	int part_shift;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7995b7b18ccdeb17dcc4a2ddbf4ce87094c7365f4b9Adrian Bunk	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	if (max_part < 0) {
8027742ce4ab49976851ce7f0185dcbe491935371a2WANG Cong		printk(KERN_ERR "nbd: max_part must be >= 0\n");
803d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		return -EINVAL;
804d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	}
805d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier
806f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
807f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	if (!nbd_dev)
808f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener		return -ENOMEM;
809f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener
810d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	part_shift = 0;
8115988ce239682854d4e632fb58bff000700830394Namhyung Kim	if (max_part > 0) {
812d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		part_shift = fls(max_part);
813d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier
8145988ce239682854d4e632fb58bff000700830394Namhyung Kim		/*
8155988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * Adjust max_part according to part_shift as it is exported
8165988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * to user space so that user can know the max number of
8175988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * partition kernel should be able to manage.
8185988ce239682854d4e632fb58bff000700830394Namhyung Kim		 *
8195988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * Note that -1 is required because partition 0 is reserved
8205988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * for the whole disk.
8215988ce239682854d4e632fb58bff000700830394Namhyung Kim		 */
8225988ce239682854d4e632fb58bff000700830394Namhyung Kim		max_part = (1UL << part_shift) - 1;
8235988ce239682854d4e632fb58bff000700830394Namhyung Kim	}
8245988ce239682854d4e632fb58bff000700830394Namhyung Kim
8253b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim	if ((1UL << part_shift) > DISK_MAX_PARTS)
8263b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim		return -EINVAL;
8273b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim
8283b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim	if (nbds_max > 1UL << (MINORBITS - part_shift))
8293b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim		return -EINVAL;
8303b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim
83140be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
832d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		struct gendisk *disk = alloc_disk(1 << part_shift);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!disk)
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].disk = disk;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The new linux 2.5 block layer implementation requires
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * every gendisk to have its very own request_queue struct.
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * These structs are big so we dynamically allocate them.
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->queue = blk_init_queue(do_nbd_request, &nbd_lock);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!disk->queue) {
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_disk(disk);
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
84631dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		/*
84731dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		 * Tell the block layer that we are not a rotational device
84831dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		 */
84931dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
850b277da0a8a594308e17881f4926879bd5fca2a2dMike Snitzer		queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, disk->queue);
851a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		disk->queue->limits.discard_granularity = 512;
852a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		disk->queue->limits.max_discard_sectors = UINT_MAX;
853a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		disk->queue->limits.discard_zeroes_data = 0;
854078be02b80359a541928c899c2631f39628f56dfMichal Belczyk		blk_queue_max_hw_sectors(disk->queue, 65536);
855078be02b80359a541928c899c2631f39628f56dfMichal Belczyk		disk->queue->limits.max_sectors = 256;
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (register_blkdev(NBD_MAJOR, "nbd")) {
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
86640be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct gendisk *disk = nbd_dev[i].disk;
868f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_dev[i].magic = NBD_MAGIC;
86948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_init(&nbd_dev[i].queue_lock);
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
87282d4dc5adb0055393248ad4ab8de392fac708a12Ingo Molnar		mutex_init(&nbd_dev[i].tx_lock);
8734b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		init_waitqueue_head(&nbd_dev[i].active_wq);
87448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		init_waitqueue_head(&nbd_dev[i].waiting_wq);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].blksize = 1024;
8764b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		nbd_dev[i].bytesize = 0;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->major = NBD_MAJOR;
878d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		disk->first_minor = i << part_shift;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->fops = &nbd_fops;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->private_data = &nbd_dev[i];
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(disk->disk_name, "nbd%d", i);
8824b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		set_capacity(disk, 0);
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		add_disk(disk);
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (i--) {
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		blk_cleanup_queue(nbd_dev[i].disk->queue);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_disk(nbd_dev[i].disk);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
892f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	kfree(nbd_dev);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit nbd_cleanup(void)
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
89940be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct gendisk *disk = nbd_dev[i].disk;
90140be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree		nbd_dev[i].magic = 0;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (disk) {
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			del_gendisk(disk);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			blk_cleanup_queue(disk->queue);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_disk(disk);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unregister_blkdev(NBD_MAJOR, "nbd");
909f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	kfree(nbd_dev);
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(nbd_init);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(nbd_cleanup);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Network Block Device");
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91940be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Breemodule_param(nbds_max, int, 0444);
920d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
921d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Viviermodule_param(max_part, int, 0444);
922d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NDEBUG
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debugflags, int, 0644);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debugflags, "flags for controlling debug output");
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
927