nbd.c revision e25115786ee540fc428a14872ebd4f56252aba32
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
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.magic = htonl(NBD_REQUEST_MAGIC);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.type = htonl(nbd_cmd(req));
24875f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh
24975f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	if (nbd_cmd(req) == NBD_CMD_FLUSH) {
25075f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		/* Other values are reserved for FLUSH requests.  */
25175f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		request.from = 0;
25275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		request.len = 0;
25375f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	} else {
25475f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
25575f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		request.len = htonl(size);
25675f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	}
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(request.handle, &req, sizeof(req));
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25983096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n",
260f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			nbd->disk->disk_name, req,
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nbdcmd_to_ascii(nbd_cmd(req)),
26283096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo			(unsigned long long)blk_rq_pos(req) << 9,
2631011c1b9f2e45ce7c6e38888d2b83936aec38771Tejun Heo			blk_rq_bytes(req));
264f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 1, &request, sizeof(request),
2657fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result <= 0) {
267f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
2687f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Send control failed (result %d)\n", result);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_out;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nbd_cmd(req) == NBD_CMD_WRITE) {
2735705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct req_iterator iter;
2747988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet		struct bio_vec bvec;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we are really probing at internals to determine
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * whether to set MSG_MORE or not...
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2795705f7021748a69d84d6567e68e8851dab551464NeilBrown		rq_for_each_segment(bvec, req, iter) {
2806c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			flags = 0;
2814550dd6c6b062fc5e5b647296d55da22616123c3Kent Overstreet			if (!rq_iter_last(bvec, iter))
2826c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				flags = MSG_MORE;
2836c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
2847988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet					nbd->disk->disk_name, req, bvec.bv_len);
2857988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet			result = sock_send_bvec(nbd, &bvec, flags);
2866c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (result <= 0) {
287f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao				dev_err(disk_to_dev(nbd->disk),
2887f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong					"Send data failed (result %d)\n",
2897f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong					result);
2906c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				goto error_out;
2916c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			}
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror_out:
29715746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek	return -EIO;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
300f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic struct request *nbd_find_request(struct nbd_device *nbd,
3010cbc591bf884a5662b2fbb21b5c09fa1c1c7b579Denis Cheng					struct request *xreq)
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
303d2c9740b499f959ed513375b6e35c2ab161921cbDenis Cheng	struct request *req, *tmp;
3044b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	int err;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
306f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq);
3074b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	if (unlikely(err))
3084b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		goto out;
3094b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
310f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	spin_lock(&nbd->queue_lock);
311f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) {
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (req != xreq)
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&req->queuelist);
315f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock(&nbd->queue_lock);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return req;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
318f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	spin_unlock(&nbd->queue_lock);
3194b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3204b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	err = -ENOENT;
3214b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3224b2f0260c74324abca76ccaa42d426af163125e7Herbert Xuout:
3234b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	return ERR_PTR(err);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
326f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *kaddr = kmap(bvec->bv_page);
330f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MSG_WAITALL);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(bvec->bv_page);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* NULL returned = something went wrong, inform userspace */
337f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic struct request *nbd_read_stat(struct nbd_device *nbd)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nbd_reply reply;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	reply.magic = 0;
344f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result <= 0) {
346f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
3477f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Receive control failed (result %d)\n", result);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto harderror;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
350e4b57e0842621f597d744b193ea325d62724596bMichal Feix
351e4b57e0842621f597d744b193ea325d62724596bMichal Feix	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
352f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)\n",
353e4b57e0842621f597d744b193ea325d62724596bMichal Feix				(unsigned long)ntohl(reply.magic));
354e4b57e0842621f597d744b193ea325d62724596bMichal Feix		result = -EPROTO;
355e4b57e0842621f597d744b193ea325d62724596bMichal Feix		goto harderror;
356e4b57e0842621f597d744b193ea325d62724596bMichal Feix	}
357e4b57e0842621f597d744b193ea325d62724596bMichal Feix
358f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	req = nbd_find_request(nbd, *(struct request **)reply.handle);
359801678c5a3b4c79236970bcca27c733f5559e0d1Hirofumi Nakagawa	if (IS_ERR(req)) {
3604b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		result = PTR_ERR(req);
3614b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		if (result != -ENOENT)
3624b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu			goto harderror;
3634b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
364f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p)\n",
3657f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			reply.handle);
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = -EBADR;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto harderror;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ntohl(reply.error)) {
371f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
3727f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			ntohl(reply.error));
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		req->errors++;
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return req;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_RX, "%s: request %p: got reply\n",
378f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			nbd->disk->disk_name, req);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nbd_cmd(req) == NBD_CMD_READ) {
3805705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct req_iterator iter;
3817988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet		struct bio_vec bvec;
3825705f7021748a69d84d6567e68e8851dab551464NeilBrown
3835705f7021748a69d84d6567e68e8851dab551464NeilBrown		rq_for_each_segment(bvec, req, iter) {
3847988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet			result = sock_recv_bvec(nbd, &bvec);
3856c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (result <= 0) {
386f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao				dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
3877f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong					result);
3886c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				req->errors++;
3896c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				return req;
3906c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			}
3916c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
3927988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet				nbd->disk->disk_name, req, bvec.bv_len);
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return req;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsharderror:
397f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->harderror = result;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t pid_show(struct device *dev,
402edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers			struct device_attribute *attr, char *buf)
4036b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements{
404edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers	struct gendisk *disk = dev_to_disk(dev);
405edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers
406edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers	return sprintf(buf, "%ld\n",
4076b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements		(long) ((struct nbd_device *)disk->private_data)->pid);
4086b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements}
4096b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
410edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute pid_attr = {
41101e8ef11bc1a74e65678ed55795f59266d4add01Parag Warudkar	.attr = { .name = "pid", .mode = S_IRUGO},
4126b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements	.show = pid_show,
4136b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements};
4146b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
415f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int nbd_do_it(struct nbd_device *nbd)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
41884963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	int ret;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
420f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->magic != NBD_MAGIC);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4227f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman	sk_set_memalloc(nbd->sock->sk);
423f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->pid = task_pid_nr(current);
424f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
42584963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	if (ret) {
426f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
427f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->pid = 0;
42884963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		return ret;
42984963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	}
4306b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
431f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	while ((req = nbd_read_stat(nbd)) != NULL)
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_end_request(req);
4336b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
434f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
435f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->pid = 0;
43684963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	return 0;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
439f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void nbd_clear_que(struct nbd_device *nbd)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
443f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->magic != NBD_MAGIC);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4454b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	/*
446f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	 * Because we have set nbd->sock to NULL under the tx_lock, all
4474b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * modifications to the list must have completed by now.  For
4484b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * the same reason, the active_req must be NULL.
4494b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 *
4504b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * As a consequence, we don't need to take the spin lock while
4514b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * purging the list here.
4524b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 */
453f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->sock);
454f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->active_req);
4554b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
456f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	while (!list_empty(&nbd->queue_head)) {
457f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		req = list_entry(nbd->queue_head.next, struct request,
4584b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu				 queuelist);
4594b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		list_del_init(&req->queuelist);
4604b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		req->errors++;
4614b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		nbd_end_request(req);
4624b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	}
463fded4e090c60100d709318896c79816d68d5b47dPaul Clements
464fded4e090c60100d709318896c79816d68d5b47dPaul Clements	while (!list_empty(&nbd->waiting_queue)) {
465fded4e090c60100d709318896c79816d68d5b47dPaul Clements		req = list_entry(nbd->waiting_queue.next, struct request,
466fded4e090c60100d709318896c79816d68d5b47dPaul Clements				 queuelist);
467fded4e090c60100d709318896c79816d68d5b47dPaul Clements		list_del_init(&req->queuelist);
468fded4e090c60100d709318896c79816d68d5b47dPaul Clements		req->errors++;
469fded4e090c60100d709318896c79816d68d5b47dPaul Clements		nbd_end_request(req);
470fded4e090c60100d709318896c79816d68d5b47dPaul Clements	}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4737fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
474f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void nbd_handle_req(struct nbd_device *nbd, struct request *req)
47548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{
47633659ebbae262228eef4e0fe990f393d1f0ed941Christoph Hellwig	if (req->cmd_type != REQ_TYPE_FS)
47748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		goto error_out;
47848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
47948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	nbd_cmd(req) = NBD_CMD_READ;
48048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	if (rq_data_dir(req) == WRITE) {
481a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		if ((req->cmd_flags & REQ_DISCARD)) {
482a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM));
483a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			nbd_cmd(req) = NBD_CMD_TRIM;
484a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		} else
485a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			nbd_cmd(req) = NBD_CMD_WRITE;
4862f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements		if (nbd->flags & NBD_FLAG_READ_ONLY) {
487f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			dev_err(disk_to_dev(nbd->disk),
4887f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong				"Write on read-only\n");
48948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			goto error_out;
49048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		}
49148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
49248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
49375f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	if (req->cmd_flags & REQ_FLUSH) {
49475f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		BUG_ON(unlikely(blk_rq_sectors(req)));
49575f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		nbd_cmd(req) = NBD_CMD_FLUSH;
49675f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh	}
49775f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh
49848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	req->errors = 0;
49948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
500f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_lock(&nbd->tx_lock);
501f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	if (unlikely(!nbd->sock)) {
502f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_unlock(&nbd->tx_lock);
503f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk),
5047f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong			"Attempted send on closed socket\n");
50515746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek		goto error_out;
50648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
50748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
508f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->active_req = req;
50948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
510f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	if (nbd_send_req(nbd, req) != 0) {
511f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_err(disk_to_dev(nbd->disk), "Request send failed\n");
51248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		req->errors++;
51348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		nbd_end_request(req);
51448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	} else {
515f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_lock(&nbd->queue_lock);
51601ff5dbc0925d11c8ad76eed3bdd02d0c7e1e0f5Chetan Loke		list_add_tail(&req->queuelist, &nbd->queue_head);
517f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock(&nbd->queue_lock);
51848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
51948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
520f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	nbd->active_req = NULL;
521f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_unlock(&nbd->tx_lock);
522f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	wake_up_all(&nbd->active_wq);
52348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
52448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	return;
52548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
52648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Viviererror_out:
52748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	req->errors++;
52848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	nbd_end_request(req);
52948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier}
53048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
53148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivierstatic int nbd_thread(void *data)
53248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{
533f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	struct nbd_device *nbd = data;
53448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	struct request *req;
53548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
53648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	set_user_nice(current, -20);
537f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
53848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* wait for something to do */
539f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		wait_event_interruptible(nbd->waiting_wq,
54048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier					 kthread_should_stop() ||
541f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao					 !list_empty(&nbd->waiting_queue));
54248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
54348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* extract request */
544f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (list_empty(&nbd->waiting_queue))
54548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			continue;
54648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
547f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_lock_irq(&nbd->queue_lock);
548f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		req = list_entry(nbd->waiting_queue.next, struct request,
54948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier				 queuelist);
55048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		list_del_init(&req->queuelist);
551f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock_irq(&nbd->queue_lock);
55248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
55348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* handle request */
554f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_handle_req(nbd, req);
55548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
55648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	return 0;
55748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier}
55848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We always wait for result of write, for now. It would be nice to make it optional
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in future
562f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao * if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK))
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56615746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machekstatic void do_nbd_request(struct request_queue *q)
567398eb08555b24049e0362fee92920982b283fd96Alex Elder		__releases(q->queue_lock) __acquires(q->queue_lock)
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5719934c8c04561413609d2bc38c6b9f268cba774a4Tejun Heo	while ((req = blk_fetch_request(q)) != NULL) {
572f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		struct nbd_device *nbd;
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_unlock_irq(q->queue_lock);
57548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5764aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe		dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
5774aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe				req->rq_disk->disk_name, req, req->cmd_type);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
579f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd = req->rq_disk->private_data;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		BUG_ON(nbd->magic != NBD_MAGIC);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
583f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (unlikely(!nbd->sock)) {
584f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			dev_err(disk_to_dev(nbd->disk),
5857f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong				"Attempted send on closed socket\n");
5864d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			req->errors++;
5874d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			nbd_end_request(req);
5884d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			spin_lock_irq(q->queue_lock);
5894d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			continue;
5904d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements		}
5914d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements
592f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_lock_irq(&nbd->queue_lock);
593f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		list_add_tail(&req->queuelist, &nbd->waiting_queue);
594f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		spin_unlock_irq(&nbd->queue_lock);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
596f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		wake_up(&nbd->waiting_wq);
5974b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irq(q->queue_lock);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek/* Must be called with tx_lock held */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
604f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
6051a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		       unsigned int cmd, unsigned long arg)
6061a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
6081a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_DISCONNECT: {
6091a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct request sreq;
6101a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
611f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
6123a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		if (!nbd->sock)
6133a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini			return -EINVAL;
6141a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6153a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		mutex_unlock(&nbd->tx_lock);
6163a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		fsync_bdev(bdev);
6173a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		mutex_lock(&nbd->tx_lock);
6184f54eec8311c3325888c29ce8e4496daf4dbe624FUJITA Tomonori		blk_rq_init(NULL, &sreq);
6194aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe		sreq.cmd_type = REQ_TYPE_SPECIAL;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_cmd(&sreq) = NBD_CMD_DISC;
6213a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini
6223a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		/* Check again after getting mutex back.  */
623f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (!nbd->sock)
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6253a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini
626c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements		nbd->disconnect = 1;
627c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements
628f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_send_req(nbd, &sreq);
629c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements		return 0;
6301a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_CLEAR_SOCK: {
633e25115786ee540fc428a14872ebd4f56252aba32Al Viro		struct socket *sock = nbd->sock;
634f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->sock = NULL;
635f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_clear_que(nbd);
636f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		BUG_ON(!list_empty(&nbd->queue_head));
637fded4e090c60100d709318896c79816d68d5b47dPaul Clements		BUG_ON(!list_empty(&nbd->waiting_queue));
6383a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		kill_bdev(bdev);
639e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (sock)
640e25115786ee540fc428a14872ebd4f56252aba32Al Viro			sockfd_put(sock);
6411a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return 0;
6421a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6431a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6441a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_SET_SOCK: {
645e25115786ee540fc428a14872ebd4f56252aba32Al Viro		struct socket *sock;
646e25115786ee540fc428a14872ebd4f56252aba32Al Viro		int err;
647e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (nbd->sock)
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBUSY;
649e25115786ee540fc428a14872ebd4f56252aba32Al Viro		sock = sockfd_lookup(arg, &err);
650e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (sock) {
651e25115786ee540fc428a14872ebd4f56252aba32Al Viro			nbd->sock = sock;
652e25115786ee540fc428a14872ebd4f56252aba32Al Viro			if (max_part > 0)
653e25115786ee540fc428a14872ebd4f56252aba32Al Viro				bdev->bd_invalidated = 1;
654e25115786ee540fc428a14872ebd4f56252aba32Al Viro			nbd->disconnect = 0; /* we're connected now */
655e25115786ee540fc428a14872ebd4f56252aba32Al Viro			return 0;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6571a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return -EINVAL;
6581a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6591a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_BLKSIZE:
661f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->blksize = arg;
662f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize &= ~(nbd->blksize-1);
663f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		bdev->bd_inode->i_size = nbd->bytesize;
664f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_blocksize(bdev, nbd->blksize);
665f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, nbd->bytesize >> 9);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6671a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE:
669f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize = arg & ~(nbd->blksize-1);
670f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		bdev->bd_inode->i_size = nbd->bytesize;
671f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_blocksize(bdev, nbd->blksize);
672f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, nbd->bytesize >> 9);
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6741a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6757fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	case NBD_SET_TIMEOUT:
676f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->xmit_timeout = arg * HZ;
6777fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		return 0;
6781a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6792f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements	case NBD_SET_FLAGS:
6802f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements		nbd->flags = arg;
6812f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements		return 0;
6822f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE_BLOCKS:
684f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize = ((u64) arg) * nbd->blksize;
685f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		bdev->bd_inode->i_size = nbd->bytesize;
686f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_blocksize(bdev, nbd->blksize);
687f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, nbd->bytesize >> 9);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6891a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6901a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_DO_IT: {
6911a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct task_struct *thread;
692e25115786ee540fc428a14872ebd4f56252aba32Al Viro		struct socket *sock;
6931a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		int error;
6941a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
695f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		if (nbd->pid)
696c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek			return -EBUSY;
697e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (!nbd->sock)
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6991a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
700f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_unlock(&nbd->tx_lock);
7011a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
702a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini		if (nbd->flags & NBD_FLAG_READ_ONLY)
703a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini			set_device_ro(bdev, true);
704a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		if (nbd->flags & NBD_FLAG_SEND_TRIM)
705a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
706a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements				nbd->disk->queue);
70775f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		if (nbd->flags & NBD_FLAG_SEND_FLUSH)
70875f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh			blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
70975f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		else
71075f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh			blk_queue_flush(nbd->disk->queue, 0);
711a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements
712ffc8b30866879ed9ba62bd0a86fecdbd51cd3d19Kees Cook		thread = kthread_create(nbd_thread, nbd, "%s",
713ffc8b30866879ed9ba62bd0a86fecdbd51cd3d19Kees Cook					nbd->disk->disk_name);
7141a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		if (IS_ERR(thread)) {
715f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			mutex_lock(&nbd->tx_lock);
71648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			return PTR_ERR(thread);
7171a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		}
71848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		wake_up_process(thread);
719f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		error = nbd_do_it(nbd);
72048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		kthread_stop(thread);
7211a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
722f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		mutex_lock(&nbd->tx_lock);
72384963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		if (error)
72484963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong			return error;
725f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		sock_shutdown(nbd, 0);
726e25115786ee540fc428a14872ebd4f56252aba32Al Viro		sock = nbd->sock;
727e25115786ee540fc428a14872ebd4f56252aba32Al Viro		nbd->sock = NULL;
728f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_clear_que(nbd);
729f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
7303a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini		kill_bdev(bdev);
731a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
732a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini		set_device_ro(bdev, false);
733e25115786ee540fc428a14872ebd4f56252aba32Al Viro		if (sock)
734e25115786ee540fc428a14872ebd4f56252aba32Al Viro			sockfd_put(sock);
73575f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh		nbd->flags = 0;
736f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->bytesize = 0;
737a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		bdev->bd_inode->i_size = 0;
738f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		set_capacity(nbd->disk, 0);
739d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		if (max_part > 0)
740a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro			ioctl_by_bdev(bdev, BLKRRPART, 0);
741c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements		if (nbd->disconnect) /* user requested, ignore socket errors */
742c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements			return 0;
743f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		return nbd->harderror;
7441a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
7451a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_QUE:
7474b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		/*
7484b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 * This is for compatibility only.  The queue is always cleared
7494b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 * by NBD_DO_IT or NBD_CLEAR_SOCK.
7504b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 */
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7521a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_PRINT_DEBUG:
754f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		dev_info(disk_to_dev(nbd->disk),
7555eedf5415cd57f8db8642a5db4cf8e5507390030WANG Cong			"next = %p, prev = %p, head = %p\n",
756f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			nbd->queue_head.next, nbd->queue_head.prev,
757f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao			&nbd->queue_head);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7601a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	return -ENOTTY;
7611a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek}
7621a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7631a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machekstatic int nbd_ioctl(struct block_device *bdev, fmode_t mode,
7641a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		     unsigned int cmd, unsigned long arg)
7651a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{
766f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	struct nbd_device *nbd = bdev->bd_disk->private_data;
7671a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	int error;
7681a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7691a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	if (!capable(CAP_SYS_ADMIN))
7701a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return -EPERM;
7711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
772f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	BUG_ON(nbd->magic != NBD_MAGIC);
7731a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7741a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	/* Anyone capable of this syscall can do *real bad* things */
7751a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
776f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
7771a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
778f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_lock(&nbd->tx_lock);
779f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	error = __nbd_ioctl(bdev, nbd, cmd, arg);
780f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao	mutex_unlock(&nbd->tx_lock);
7811a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7821a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	return error;
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
78583d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations nbd_fops =
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner =	THIS_MODULE,
7888a6cfeb6deca3a8fefd639d898b0d163c0b5d368Arnd Bergmann	.ioctl =	nbd_ioctl,
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And here should be modules and kernel interface
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  (Just smiley confuses emacs :-)
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init nbd_init(void)
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -ENOMEM;
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
800d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	int part_shift;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8025b7b18ccdeb17dcc4a2ddbf4ce87094c7365f4b9Adrian Bunk	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
804d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	if (max_part < 0) {
8057742ce4ab49976851ce7f0185dcbe491935371a2WANG Cong		printk(KERN_ERR "nbd: max_part must be >= 0\n");
806d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		return -EINVAL;
807d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	}
808d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier
809f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
810f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	if (!nbd_dev)
811f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener		return -ENOMEM;
812f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener
813d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	part_shift = 0;
8145988ce239682854d4e632fb58bff000700830394Namhyung Kim	if (max_part > 0) {
815d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		part_shift = fls(max_part);
816d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier
8175988ce239682854d4e632fb58bff000700830394Namhyung Kim		/*
8185988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * Adjust max_part according to part_shift as it is exported
8195988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * to user space so that user can know the max number of
8205988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * partition kernel should be able to manage.
8215988ce239682854d4e632fb58bff000700830394Namhyung Kim		 *
8225988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * Note that -1 is required because partition 0 is reserved
8235988ce239682854d4e632fb58bff000700830394Namhyung Kim		 * for the whole disk.
8245988ce239682854d4e632fb58bff000700830394Namhyung Kim		 */
8255988ce239682854d4e632fb58bff000700830394Namhyung Kim		max_part = (1UL << part_shift) - 1;
8265988ce239682854d4e632fb58bff000700830394Namhyung Kim	}
8275988ce239682854d4e632fb58bff000700830394Namhyung Kim
8283b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim	if ((1UL << part_shift) > DISK_MAX_PARTS)
8293b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim		return -EINVAL;
8303b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim
8313b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim	if (nbds_max > 1UL << (MINORBITS - part_shift))
8323b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim		return -EINVAL;
8333b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim
83440be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
835d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		struct gendisk *disk = alloc_disk(1 << part_shift);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!disk)
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].disk = disk;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The new linux 2.5 block layer implementation requires
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * every gendisk to have its very own request_queue struct.
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * These structs are big so we dynamically allocate them.
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->queue = blk_init_queue(do_nbd_request, &nbd_lock);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!disk->queue) {
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_disk(disk);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
84931dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		/*
85031dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		 * Tell the block layer that we are not a rotational device
85131dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		 */
85231dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
853a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		disk->queue->limits.discard_granularity = 512;
854a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		disk->queue->limits.max_discard_sectors = UINT_MAX;
855a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements		disk->queue->limits.discard_zeroes_data = 0;
856078be02b80359a541928c899c2631f39628f56dfMichal Belczyk		blk_queue_max_hw_sectors(disk->queue, 65536);
857078be02b80359a541928c899c2631f39628f56dfMichal Belczyk		disk->queue->limits.max_sectors = 256;
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (register_blkdev(NBD_MAJOR, "nbd")) {
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
86840be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct gendisk *disk = nbd_dev[i].disk;
870f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao		nbd_dev[i].magic = NBD_MAGIC;
87148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_init(&nbd_dev[i].queue_lock);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
87482d4dc5adb0055393248ad4ab8de392fac708a12Ingo Molnar		mutex_init(&nbd_dev[i].tx_lock);
8754b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		init_waitqueue_head(&nbd_dev[i].active_wq);
87648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		init_waitqueue_head(&nbd_dev[i].waiting_wq);
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].blksize = 1024;
8784b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		nbd_dev[i].bytesize = 0;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->major = NBD_MAJOR;
880d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		disk->first_minor = i << part_shift;
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->fops = &nbd_fops;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->private_data = &nbd_dev[i];
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(disk->disk_name, "nbd%d", i);
8844b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		set_capacity(disk, 0);
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		add_disk(disk);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (i--) {
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		blk_cleanup_queue(nbd_dev[i].disk->queue);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_disk(nbd_dev[i].disk);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
894f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	kfree(nbd_dev);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit nbd_cleanup(void)
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
90140be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct gendisk *disk = nbd_dev[i].disk;
90340be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree		nbd_dev[i].magic = 0;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (disk) {
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			del_gendisk(disk);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			blk_cleanup_queue(disk->queue);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_disk(disk);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unregister_blkdev(NBD_MAJOR, "nbd");
911f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	kfree(nbd_dev);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(nbd_init);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(nbd_cleanup);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Network Block Device");
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92140be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Breemodule_param(nbds_max, int, 0444);
922d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
923d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Viviermodule_param(max_part, int, 0444);
924d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NDEBUG
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debugflags, int, 0644);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debugflags, "flags for controlling debug output");
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
929