nbd.c revision 15746fcaa3a00753bbab2326088b85b10c1ba36a
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 *
715746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek * Copyright 1997-2000, 2008 Pavel Machek <pavel@suse.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>
274b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <linux/compiler.h>
284b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <linux/err.h>
294b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <linux/kernel.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sock.h>
3191cf45f02af5c871251165d000c3f42a2a0b0552Trond Myklebust#include <linux/net.h>
3248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier#include <linux/kthread.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
354b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu#include <asm/system.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/types.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/nbd.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LO_MAGIC 0x68797548
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NDEBUG
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(flags, fmt...)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* NDEBUG */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(flags, fmt...) do { \
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (debugflags & (flags)) printk(KERN_DEBUG fmt); \
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} while (0)
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_IOCTL       0x0004
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_INIT        0x0010
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_EXIT        0x0020
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_BLKDEV      0x0100
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_RX          0x0200
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_TX          0x0400
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int debugflags;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NDEBUG */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
579c7a41691f37a1538a88e5eb9b0b73df1f834542Ingo van Lilstatic unsigned int nbds_max = 16;
5820a8143eaa3300a58326156eaf43e03db0fd2cb6Paul Clementsstatic struct nbd_device *nbd_dev;
59d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivierstatic int max_part;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use just one lock (or at most 1 per NIC). Two arguments for this:
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Each NIC is essentially a synchronization point for all servers
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    accessed through that NIC so there's no need to have more locks
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    than NICs anyway.
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. More locks lead to more "Dirty cache line bouncing" which will slow
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    down each lock to the point where they're actually slower than just
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    a single lock.
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this!
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(nbd_lock);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NDEBUG
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *ioctl_cmd_to_ascii(int cmd)
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SOCK: return "set-sock";
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_BLKSIZE: return "set-blksize";
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE: return "set-size";
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_DO_IT: return "do-it";
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_SOCK: return "clear-sock";
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_QUE: return "clear-que";
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_PRINT_DEBUG: return "print-debug";
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE_BLOCKS: return "set-size-blocks";
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_DISCONNECT: return "disconnect";
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BLKROSET: return "set-read-only";
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BLKFLSBUF: return "flush-buffer-cache";
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return "unknown";
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *nbdcmd_to_ascii(int cmd)
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  NBD_CMD_READ: return "read";
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CMD_WRITE: return "write";
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  NBD_CMD_DISC: return "disconnect";
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return "invalid";
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NDEBUG */
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void nbd_end_request(struct request *req)
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
105097c94a4e8bde978c8d12683d9a34048e9139e4bKiyoshi Ueda	int error = req->errors ? -EIO : 0;
106165125e1e480f9510a5ffcfbfee4e3ee38c05f23Jens Axboe	struct request_queue *q = req->q;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
110097c94a4e8bde978c8d12683d9a34048e9139e4bKiyoshi Ueda			req, error ? "failed" : "done");
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(q->queue_lock, flags);
113097c94a4e8bde978c8d12683d9a34048e9139e4bKiyoshi Ueda	__blk_end_request(req, error, req->nr_sectors << 9);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(q->queue_lock, flags);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1177fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clementsstatic void sock_shutdown(struct nbd_device *lo, int lock)
1187fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements{
1197fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	/* Forcibly shutdown the socket causing all listeners
1207fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * to error
1217fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 *
1227fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * FIXME: This code is duplicated from sys_shutdown, but
1237fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * there should be a more generic interface rather than
1247fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	 * calling socket ops directly here */
1257fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	if (lock)
1267fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		mutex_lock(&lo->tx_lock);
1277fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	if (lo->sock) {
1287fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		printk(KERN_WARNING "%s: shutting down socket\n",
1297fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			lo->disk->disk_name);
13091cf45f02af5c871251165d000c3f42a2a0b0552Trond Myklebust		kernel_sock_shutdown(lo->sock, SHUT_RDWR);
1317fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		lo->sock = NULL;
1327fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	}
1337fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	if (lock)
1347fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		mutex_unlock(&lo->tx_lock);
1357fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements}
1367fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1377fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clementsstatic void nbd_xmit_timeout(unsigned long arg)
1387fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements{
1397fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	struct task_struct *task = (struct task_struct *)arg;
1407fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1417fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d)\n",
1427fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		task->comm, task->pid);
1437fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	force_sig(SIGKILL, task);
1447fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements}
1457fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Send or receive packet.
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1497fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clementsstatic int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int msg_flags)
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1527fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	struct socket *sock = lo->sock;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct msghdr msg;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct kvec iov;
156be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	sigset_t blocked, oldset;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer	if (unlikely(!sock)) {
159ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer		printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n",
160ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer		       lo->disk->disk_name, (send ? "send" : "recv"));
161ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer		return -EINVAL;
162ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer	}
163ffc41cf8dbb1b895a87daf47d0e5bf6dfbfcab4cMike Snitzer
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow interception of SIGKILL only
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Don't allow other signals to interrupt the transmission */
166be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	siginitsetinv(&blocked, sigmask(SIGKILL));
167be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	sigprocmask(SIG_SETMASK, &blocked, &oldset);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sock->sk->sk_allocation = GFP_NOIO;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov.iov_base = buf;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iov.iov_len = size;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_name = NULL;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_namelen = 0;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_control = NULL;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_controllen = 0;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msg.msg_flags = msg_flags | MSG_NOSIGNAL;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1797fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		if (send) {
1807fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			struct timer_list ti;
1817fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
1827fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			if (lo->xmit_timeout) {
1837fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				init_timer(&ti);
1847fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				ti.function = nbd_xmit_timeout;
1857fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				ti.data = (unsigned long)current;
1867fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				ti.expires = jiffies + lo->xmit_timeout;
1877fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				add_timer(&ti);
1887fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = kernel_sendmsg(sock, &msg, &iov, 1, size);
1907fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			if (lo->xmit_timeout)
1917fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements				del_timer_sync(&ti);
1927fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		} else
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = kernel_recvmsg(sock, &msg, &iov, 1, size, 0);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (signal_pending(current)) {
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			siginfo_t info;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
198ba25f9dcc4ea6e30839fcab5a5516f2176d5bfedPavel Emelyanov				task_pid_nr(current), current->comm,
199be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov				dequeue_signal_lock(current, &current->blocked, &info));
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			result = -EINTR;
2017fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			sock_shutdown(lo, !send);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (result <= 0) {
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (result == 0)
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				result = -EPIPE; /* short read */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size -= result;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buf += result;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (size > 0);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
214be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov	sigprocmask(SIG_SETMASK, &oldset, NULL);
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2197fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clementsstatic inline int sock_send_bvec(struct nbd_device *lo, struct bio_vec *bvec,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int flags)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *kaddr = kmap(bvec->bv_page);
2247fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	result = sock_xmit(lo, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(bvec->bv_page);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2297fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements/* always call with the tx_lock held */
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int nbd_send_req(struct nbd_device *lo, struct request *req)
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2325705f7021748a69d84d6567e68e8851dab551464NeilBrown	int result, flags;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nbd_request request;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long size = req->nr_sectors << 9;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.magic = htonl(NBD_REQUEST_MAGIC);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.type = htonl(nbd_cmd(req));
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.from = cpu_to_be64((u64) req->sector << 9);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request.len = htonl(size);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(request.handle, &req, sizeof(req));
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lo->disk->disk_name, req,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nbdcmd_to_ascii(nbd_cmd(req)),
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long long)req->sector << 9,
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			req->nr_sectors << 9);
2477fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	result = sock_xmit(lo, 1, &request, sizeof(request),
2487fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result <= 0) {
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s: Send control failed (result %d)\n",
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lo->disk->disk_name, result);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_out;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nbd_cmd(req) == NBD_CMD_WRITE) {
2565705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct req_iterator iter;
2575705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct bio_vec *bvec;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we are really probing at internals to determine
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * whether to set MSG_MORE or not...
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2625705f7021748a69d84d6567e68e8851dab551464NeilBrown		rq_for_each_segment(bvec, req, iter) {
2636c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			flags = 0;
2646c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (!rq_iter_last(req, iter))
2656c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				flags = MSG_MORE;
2666c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
2676c92e699b56287da582ccb12a64b959b6d6109baJens Axboe					lo->disk->disk_name, req, bvec->bv_len);
2687fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			result = sock_send_bvec(lo, bvec, flags);
2696c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (result <= 0) {
2706c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				printk(KERN_ERR "%s: Send data failed (result %d)\n",
2716c92e699b56287da582ccb12a64b959b6d6109baJens Axboe						lo->disk->disk_name, result);
2726c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				goto error_out;
2736c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			}
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror_out:
27915746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek	return -EIO;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2820cbc591bf884a5662b2fbb21b5c09fa1c1c7b579Denis Chengstatic struct request *nbd_find_request(struct nbd_device *lo,
2830cbc591bf884a5662b2fbb21b5c09fa1c1c7b579Denis Cheng					struct request *xreq)
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
285d2c9740b499f959ed513375b6e35c2ab161921cbDenis Cheng	struct request *req, *tmp;
2864b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	int err;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2884b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
2894b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	if (unlikely(err))
2904b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		goto out;
2914b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&lo->queue_lock);
293d2c9740b499f959ed513375b6e35c2ab161921cbDenis Cheng	list_for_each_entry_safe(req, tmp, &lo->queue_head, queuelist) {
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (req != xreq)
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del_init(&req->queuelist);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&lo->queue_lock);
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return req;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&lo->queue_lock);
3014b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3024b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	err = -ENOENT;
3034b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3044b2f0260c74324abca76ccaa42d426af163125e7Herbert Xuout:
3054b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	return ERR_PTR(err);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3087fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clementsstatic inline int sock_recv_bvec(struct nbd_device *lo, struct bio_vec *bvec)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *kaddr = kmap(bvec->bv_page);
3127fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	result = sock_xmit(lo, 0, kaddr + bvec->bv_offset, bvec->bv_len,
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MSG_WAITALL);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(bvec->bv_page);
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return result;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* NULL returned = something went wrong, inform userspace */
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct request *nbd_read_stat(struct nbd_device *lo)
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int result;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct nbd_reply reply;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	reply.magic = 0;
3267fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result <= 0) {
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s: Receive control failed (result %d)\n",
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lo->disk->disk_name, result);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto harderror;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
332e4b57e0842621f597d744b193ea325d62724596bMichal Feix
333e4b57e0842621f597d744b193ea325d62724596bMichal Feix	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
334e4b57e0842621f597d744b193ea325d62724596bMichal Feix		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
335e4b57e0842621f597d744b193ea325d62724596bMichal Feix				lo->disk->disk_name,
336e4b57e0842621f597d744b193ea325d62724596bMichal Feix				(unsigned long)ntohl(reply.magic));
337e4b57e0842621f597d744b193ea325d62724596bMichal Feix		result = -EPROTO;
338e4b57e0842621f597d744b193ea325d62724596bMichal Feix		goto harderror;
339e4b57e0842621f597d744b193ea325d62724596bMichal Feix	}
340e4b57e0842621f597d744b193ea325d62724596bMichal Feix
3410cbc591bf884a5662b2fbb21b5c09fa1c1c7b579Denis Cheng	req = nbd_find_request(lo, *(struct request **)reply.handle);
342801678c5a3b4c79236970bcca27c733f5559e0d1Hirofumi Nakagawa	if (IS_ERR(req)) {
3434b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		result = PTR_ERR(req);
3444b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		if (result != -ENOENT)
3454b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu			goto harderror;
3464b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s: Unexpected reply (%p)\n",
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lo->disk->disk_name, reply.handle);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = -EBADR;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto harderror;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ntohl(reply.error)) {
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s: Other side returned error (%d)\n",
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lo->disk->disk_name, ntohl(reply.error));
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		req->errors++;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return req;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_RX, "%s: request %p: got reply\n",
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lo->disk->disk_name, req);
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nbd_cmd(req) == NBD_CMD_READ) {
3635705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct req_iterator iter;
3645705f7021748a69d84d6567e68e8851dab551464NeilBrown		struct bio_vec *bvec;
3655705f7021748a69d84d6567e68e8851dab551464NeilBrown
3665705f7021748a69d84d6567e68e8851dab551464NeilBrown		rq_for_each_segment(bvec, req, iter) {
3677fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements			result = sock_recv_bvec(lo, bvec);
3686c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			if (result <= 0) {
3696c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				printk(KERN_ERR "%s: Receive data failed (result %d)\n",
3706c92e699b56287da582ccb12a64b959b6d6109baJens Axboe						lo->disk->disk_name, result);
3716c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				req->errors++;
3726c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				return req;
3736c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			}
3746c92e699b56287da582ccb12a64b959b6d6109baJens Axboe			dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
3756c92e699b56287da582ccb12a64b959b6d6109baJens Axboe				lo->disk->disk_name, req, bvec->bv_len);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return req;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsharderror:
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lo->harderror = result;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
384edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t pid_show(struct device *dev,
385edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers			struct device_attribute *attr, char *buf)
3866b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements{
387edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers	struct gendisk *disk = dev_to_disk(dev);
388edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers
389edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers	return sprintf(buf, "%ld\n",
3906b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements		(long) ((struct nbd_device *)disk->private_data)->pid);
3916b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements}
3926b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
393edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute pid_attr = {
39401e8ef11bc1a74e65678ed55795f59266d4add01Parag Warudkar	.attr = { .name = "pid", .mode = S_IRUGO},
3956b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements	.show = pid_show,
3966b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements};
3976b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
39884963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Congstatic int nbd_do_it(struct nbd_device *lo)
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
40184963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	int ret;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(lo->magic != LO_MAGIC);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4056b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements	lo->pid = current->pid;
406ed9e1982347b36573cd622ee5f4e2a7ccd79b3fdTejun Heo	ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
40784963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	if (ret) {
40884963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		printk(KERN_ERR "nbd: sysfs_create_file failed!");
409c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek		lo->pid = 0;
41084963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		return ret;
41184963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	}
4126b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((req = nbd_read_stat(lo)) != NULL)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_end_request(req);
4156b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements
416ed9e1982347b36573cd622ee5f4e2a7ccd79b3fdTejun Heo	sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
417c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek	lo->pid = 0;
41884963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong	return 0;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void nbd_clear_que(struct nbd_device *lo)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(lo->magic != LO_MAGIC);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4274b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	/*
4284b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * Because we have set lo->sock to NULL under the tx_lock, all
4294b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * modifications to the list must have completed by now.  For
4304b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * the same reason, the active_req must be NULL.
4314b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 *
4324b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * As a consequence, we don't need to take the spin lock while
4334b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 * purging the list here.
4344b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	 */
4354b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	BUG_ON(lo->sock);
4364b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	BUG_ON(lo->active_req);
4374b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
4384b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	while (!list_empty(&lo->queue_head)) {
4394b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		req = list_entry(lo->queue_head.next, struct request,
4404b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu				 queuelist);
4414b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		list_del_init(&req->queuelist);
4424b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		req->errors++;
4434b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		nbd_end_request(req);
4444b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu	}
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4477fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements
44848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivierstatic void nbd_handle_req(struct nbd_device *lo, struct request *req)
44948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{
45048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	if (!blk_fs_request(req))
45148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		goto error_out;
45248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
45348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	nbd_cmd(req) = NBD_CMD_READ;
45448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	if (rq_data_dir(req) == WRITE) {
45548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		nbd_cmd(req) = NBD_CMD_WRITE;
45648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		if (lo->flags & NBD_READ_ONLY) {
45748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			printk(KERN_ERR "%s: Write on read-only\n",
45848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier					lo->disk->disk_name);
45948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			goto error_out;
46048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		}
46148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
46248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
46348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	req->errors = 0;
46448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
46548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	mutex_lock(&lo->tx_lock);
46648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	if (unlikely(!lo->sock)) {
46748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		mutex_unlock(&lo->tx_lock);
46848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		printk(KERN_ERR "%s: Attempted send on closed socket\n",
46948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		       lo->disk->disk_name);
47015746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek		goto error_out;
47148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
47248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
47348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	lo->active_req = req;
47448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
47548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	if (nbd_send_req(lo, req) != 0) {
47648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		printk(KERN_ERR "%s: Request send failed\n",
47748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier				lo->disk->disk_name);
47848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		req->errors++;
47948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		nbd_end_request(req);
48048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	} else {
48148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_lock(&lo->queue_lock);
48248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		list_add(&req->queuelist, &lo->queue_head);
48348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_unlock(&lo->queue_lock);
48448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
48548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
48648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	lo->active_req = NULL;
48748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	mutex_unlock(&lo->tx_lock);
48848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	wake_up_all(&lo->active_wq);
48948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
49048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	return;
49148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
49248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Viviererror_out:
49348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	req->errors++;
49448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	nbd_end_request(req);
49548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier}
49648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
49748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivierstatic int nbd_thread(void *data)
49848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{
49948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	struct nbd_device *lo = data;
50048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	struct request *req;
50148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
50248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	set_user_nice(current, -20);
50348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	while (!kthread_should_stop() || !list_empty(&lo->waiting_queue)) {
50448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* wait for something to do */
50548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		wait_event_interruptible(lo->waiting_wq,
50648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier					 kthread_should_stop() ||
50748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier					 !list_empty(&lo->waiting_queue));
50848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
50948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* extract request */
51048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		if (list_empty(&lo->waiting_queue))
51148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			continue;
51248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
51348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_lock_irq(&lo->queue_lock);
51448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		req = list_entry(lo->waiting_queue.next, struct request,
51548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier				 queuelist);
51648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		list_del_init(&req->queuelist);
51748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_unlock_irq(&lo->queue_lock);
51848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
51948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		/* handle request */
52048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		nbd_handle_req(lo, req);
52148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	}
52248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier	return 0;
52348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier}
52448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We always wait for result of write, for now. It would be nice to make it optional
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in future
528e654bc4393e85e326993256d80b9710a4d6411ffBoaz Harrosh * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53215746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machekstatic void do_nbd_request(struct request_queue *q)
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct request *req;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((req = elv_next_request(q)) != NULL) {
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct nbd_device *lo;
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		blkdev_dequeue_request(req);
54048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
54148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_unlock_irq(q->queue_lock);
54248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier
5434aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe		dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
5444aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe				req->rq_disk->disk_name, req, req->cmd_type);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo = req->rq_disk->private_data;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(lo->magic != LO_MAGIC);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5504d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements		if (unlikely(!lo->sock)) {
5514d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			printk(KERN_ERR "%s: Attempted send on closed socket\n",
5524d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements				lo->disk->disk_name);
5534d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			req->errors++;
5544d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			nbd_end_request(req);
5554d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			spin_lock_irq(q->queue_lock);
5564d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements			continue;
5574d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements		}
5584d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements
55948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_lock_irq(&lo->queue_lock);
56048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		list_add_tail(&req->queuelist, &lo->waiting_queue);
56148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		spin_unlock_irq(&lo->queue_lock);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		wake_up(&lo->waiting_wq);
5644b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irq(q->queue_lock);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5691a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek/* Must be called with tx_lock held */
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machekstatic int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
5721a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		       unsigned int cmd, unsigned long arg)
5731a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
5751a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_DISCONNECT: {
5761a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct request sreq;
5771a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
5791a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
5804f54eec8311c3325888c29ce8e4496daf4dbe624FUJITA Tomonori		blk_rq_init(NULL, &sreq);
5814aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe		sreq.cmd_type = REQ_TYPE_SPECIAL;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_cmd(&sreq) = NBD_CMD_DISC;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Set these to sane values in case server implementation
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * fails to check the request type first and also to keep
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * debugging output cleaner.
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sreq.sector = 0;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sreq.nr_sectors = 0;
5901a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		if (!lo->sock)
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
5921a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		nbd_send_req(lo, &sreq);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return 0;
5941a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5961a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_CLEAR_SOCK: {
5971a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct file *file;
5981a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->sock = NULL;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		file = lo->file;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->file = NULL;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_clear_que(lo);
6034b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		BUG_ON(!list_empty(&lo->queue_head));
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (file)
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			fput(file);
6061a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return 0;
6071a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6081a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6091a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_SET_SOCK: {
6101a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct file *file;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lo->file)
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBUSY;
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		file = fget(arg);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (file) {
615a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro			struct inode *inode = file->f_path.dentry->d_inode;
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (S_ISSOCK(inode->i_mode)) {
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lo->file = file;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lo->sock = SOCKET_I(inode);
619d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier				if (max_part > 0)
620d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier					bdev->bd_invalidated = 1;
6211a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek				return 0;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				fput(file);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6261a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return -EINVAL;
6271a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6281a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_BLKSIZE:
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->blksize = arg;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->bytesize &= ~(lo->blksize-1);
632a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		bdev->bd_inode->i_size = lo->bytesize;
633a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		set_blocksize(bdev, lo->blksize);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_capacity(lo->disk, lo->bytesize >> 9);
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6361a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE:
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->bytesize = arg & ~(lo->blksize-1);
639a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		bdev->bd_inode->i_size = lo->bytesize;
640a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		set_blocksize(bdev, lo->blksize);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_capacity(lo->disk, lo->bytesize >> 9);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6431a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6447fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements	case NBD_SET_TIMEOUT:
6457fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		lo->xmit_timeout = arg * HZ;
6467fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements		return 0;
6471a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_SET_SIZE_BLOCKS:
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->bytesize = ((u64) arg) * lo->blksize;
650a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		bdev->bd_inode->i_size = lo->bytesize;
651a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		set_blocksize(bdev, lo->blksize);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_capacity(lo->disk, lo->bytesize >> 9);
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6541a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6551a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	case NBD_DO_IT: {
6561a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct task_struct *thread;
6571a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		struct file *file;
6581a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		int error;
6591a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
660c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek		if (lo->pid)
661c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek			return -EBUSY;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!lo->file)
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6641a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6651a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		mutex_unlock(&lo->tx_lock);
6661a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
66748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
6681a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		if (IS_ERR(thread)) {
6691a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek			mutex_lock(&lo->tx_lock);
67048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier			return PTR_ERR(thread);
6711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		}
67248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		wake_up_process(thread);
67384963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		error = nbd_do_it(lo);
67448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		kthread_stop(thread);
6751a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6761a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		mutex_lock(&lo->tx_lock);
67784963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong		if (error)
67884963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong			return error;
6791a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		sock_shutdown(lo, 0);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		file = lo->file;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lo->file = NULL;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_clear_que(lo);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (file)
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			fput(file);
6864b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		lo->bytesize = 0;
687a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro		bdev->bd_inode->i_size = 0;
6884b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		set_capacity(lo->disk, 0);
689d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		if (max_part > 0)
690a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro			ioctl_by_bdev(bdev, BLKRRPART, 0);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return lo->harderror;
6921a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	}
6931a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_CLEAR_QUE:
6954b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		/*
6964b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 * This is for compatibility only.  The queue is always cleared
6974b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 * by NBD_DO_IT or NBD_CLEAR_SOCK.
6984b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		 */
6994b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7011a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case NBD_PRINT_DEBUG:
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
704a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro			bdev->bd_disk->disk_name,
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lo->queue_head.next, lo->queue_head.prev,
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&lo->queue_head);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7091a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	return -ENOTTY;
7101a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek}
7111a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7121a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machekstatic int nbd_ioctl(struct block_device *bdev, fmode_t mode,
7131a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		     unsigned int cmd, unsigned long arg)
7141a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{
7151a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	struct nbd_device *lo = bdev->bd_disk->private_data;
7161a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	int error;
7171a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7181a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	if (!capable(CAP_SYS_ADMIN))
7191a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek		return -EPERM;
7201a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7211a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	BUG_ON(lo->magic != LO_MAGIC);
7221a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7231a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	/* Anyone capable of this syscall can do *real bad* things */
7241a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
7251a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
7261a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7271a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	mutex_lock(&lo->tx_lock);
7281a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	error = __nbd_ioctl(bdev, lo, cmd, arg);
7291a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	mutex_unlock(&lo->tx_lock);
7301a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek
7311a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek	return error;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct block_device_operations nbd_fops =
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner =	THIS_MODULE,
737a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro	.locked_ioctl =	nbd_ioctl,
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And here should be modules and kernel interface
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  (Just smiley confuses emacs :-)
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init nbd_init(void)
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -ENOMEM;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
749d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	int part_shift;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7515b7b18ccdeb17dcc4a2ddbf4ce87094c7365f4b9Adrian Bunk	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
753d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	if (max_part < 0) {
754d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		printk(KERN_CRIT "nbd: max_part must be >= 0\n");
755d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		return -EINVAL;
756d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	}
757d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier
758f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
759f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	if (!nbd_dev)
760f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener		return -ENOMEM;
761f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener
762d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	part_shift = 0;
763d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier	if (max_part > 0)
764d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		part_shift = fls(max_part);
765d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier
76640be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
767d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		struct gendisk *disk = alloc_disk(1 << part_shift);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!disk)
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].disk = disk;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The new linux 2.5 block layer implementation requires
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * every gendisk to have its very own request_queue struct.
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * These structs are big so we dynamically allocate them.
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->queue = blk_init_queue(do_nbd_request, &nbd_lock);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!disk->queue) {
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_disk(disk);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
78131dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		/*
78231dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		 * Tell the block layer that we are not a rotational device
78331dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		 */
78431dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (register_blkdev(NBD_MAJOR, "nbd")) {
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
79540be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct gendisk *disk = nbd_dev[i].disk;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].file = NULL;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].magic = LO_MAGIC;
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].flags = 0;
80048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_init(&nbd_dev[i].queue_lock);
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
80382d4dc5adb0055393248ad4ab8de392fac708a12Ingo Molnar		mutex_init(&nbd_dev[i].tx_lock);
8044b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu		init_waitqueue_head(&nbd_dev[i].active_wq);
80548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier		init_waitqueue_head(&nbd_dev[i].waiting_wq);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nbd_dev[i].blksize = 1024;
8074b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		nbd_dev[i].bytesize = 0;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->major = NBD_MAJOR;
809d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier		disk->first_minor = i << part_shift;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->fops = &nbd_fops;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disk->private_data = &nbd_dev[i];
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(disk->disk_name, "nbd%d", i);
8134b86a872561ad052bdc6f092a06807822d26beb1Paul Clements		set_capacity(disk, 0);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		add_disk(disk);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (i--) {
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		blk_cleanup_queue(nbd_dev[i].disk->queue);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_disk(nbd_dev[i].disk);
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
823f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	kfree(nbd_dev);
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit nbd_cleanup(void)
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
83040be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree	for (i = 0; i < nbds_max; i++) {
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct gendisk *disk = nbd_dev[i].disk;
83240be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree		nbd_dev[i].magic = 0;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (disk) {
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			del_gendisk(disk);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			blk_cleanup_queue(disk->queue);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			put_disk(disk);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unregister_blkdev(NBD_MAJOR, "nbd");
840f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener	kfree(nbd_dev);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(nbd_init);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(nbd_cleanup);
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Network Block Device");
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
85040be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Breemodule_param(nbds_max, int, 0444);
851d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
852d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Viviermodule_param(max_part, int, 0444);
853d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NDEBUG
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debugflags, int, 0644);
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debugflags, "flags for controlling debug output");
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
858