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, ¤t->blocked, &info)); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -EINTR; 209f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao sock_shutdown(nbd, !send); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result <= 0) { 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result == 0) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -EPIPE; /* short read */ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size -= result; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf += result; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (size > 0); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 222be0ef957c9eed4ebae873ee3fbcfb9dfde486decOleg Nesterov sigprocmask(SIG_SETMASK, &oldset, NULL); 2237f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman tsk_restore_flags(current, pflags, PF_MEMALLOC); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 228f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec, 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flags) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *kaddr = kmap(bvec->bv_page); 233f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset, 234f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao bvec->bv_len, flags); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kunmap(bvec->bv_page); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2397fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements/* always call with the tx_lock held */ 240f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int nbd_send_req(struct nbd_device *nbd, struct request *req) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2425705f7021748a69d84d6567e68e8851dab551464NeilBrown int result, flags; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nbd_request request; 2441011c1b9f2e45ce7c6e38888d2b83936aec38771Tejun Heo unsigned long size = blk_rq_bytes(req); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24604cfac4e40b2b5dbaf8c0fc625878388a98bb9c6Hani Benhabiles memset(&request, 0, sizeof(request)); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request.magic = htonl(NBD_REQUEST_MAGIC); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request.type = htonl(nbd_cmd(req)); 24975f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh 25004cfac4e40b2b5dbaf8c0fc625878388a98bb9c6Hani Benhabiles if (nbd_cmd(req) != NBD_CMD_FLUSH && nbd_cmd(req) != NBD_CMD_DISC) { 25175f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); 25275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh request.len = htonl(size); 25375f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh } 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(request.handle, &req, sizeof(req)); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25683096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n", 257f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->disk->disk_name, req, 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nbdcmd_to_ascii(nbd_cmd(req)), 25983096ebf1263b2c1ee5e653ba37d993d02e3eb7bTejun Heo (unsigned long long)blk_rq_pos(req) << 9, 2601011c1b9f2e45ce7c6e38888d2b83936aec38771Tejun Heo blk_rq_bytes(req)); 261f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao result = sock_xmit(nbd, 1, &request, sizeof(request), 2627fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result <= 0) { 264f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), 2657f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong "Send control failed (result %d)\n", result); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error_out; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nbd_cmd(req) == NBD_CMD_WRITE) { 2705705f7021748a69d84d6567e68e8851dab551464NeilBrown struct req_iterator iter; 2717988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet struct bio_vec bvec; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we are really probing at internals to determine 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * whether to set MSG_MORE or not... 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2765705f7021748a69d84d6567e68e8851dab551464NeilBrown rq_for_each_segment(bvec, req, iter) { 2776c92e699b56287da582ccb12a64b959b6d6109baJens Axboe flags = 0; 2784550dd6c6b062fc5e5b647296d55da22616123c3Kent Overstreet if (!rq_iter_last(bvec, iter)) 2796c92e699b56287da582ccb12a64b959b6d6109baJens Axboe flags = MSG_MORE; 2806c92e699b56287da582ccb12a64b959b6d6109baJens Axboe dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", 2817988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet nbd->disk->disk_name, req, bvec.bv_len); 2827988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet result = sock_send_bvec(nbd, &bvec, flags); 2836c92e699b56287da582ccb12a64b959b6d6109baJens Axboe if (result <= 0) { 284f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), 2857f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong "Send data failed (result %d)\n", 2867f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong result); 2876c92e699b56287da582ccb12a64b959b6d6109baJens Axboe goto error_out; 2886c92e699b56287da582ccb12a64b959b6d6109baJens Axboe } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror_out: 29415746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek return -EIO; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 297f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic struct request *nbd_find_request(struct nbd_device *nbd, 2980cbc591bf884a5662b2fbb21b5c09fa1c1c7b579Denis Cheng struct request *xreq) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 300d2c9740b499f959ed513375b6e35c2ab161921cbDenis Cheng struct request *req, *tmp; 3014b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu int err; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 303f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq); 3044b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu if (unlikely(err)) 3054b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu goto out; 3064b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu 307f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_lock(&nbd->queue_lock); 308f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) { 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req != xreq) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del_init(&req->queuelist); 312f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_unlock(&nbd->queue_lock); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return req; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 315f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_unlock(&nbd->queue_lock); 3164b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu 3174b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu err = -ENOENT; 3184b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu 3194b2f0260c74324abca76ccaa42d426af163125e7Herbert Xuout: 3204b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu return ERR_PTR(err); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 323f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec) 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *kaddr = kmap(bvec->bv_page); 327f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len, 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MSG_WAITALL); 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kunmap(bvec->bv_page); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* NULL returned = something went wrong, inform userspace */ 334f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic struct request *nbd_read_stat(struct nbd_device *nbd) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct nbd_reply reply; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct request *req; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reply.magic = 0; 341f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result <= 0) { 343f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), 3447f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong "Receive control failed (result %d)\n", result); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto harderror; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 347e4b57e0842621f597d744b193ea325d62724596bMichal Feix 348e4b57e0842621f597d744b193ea325d62724596bMichal Feix if (ntohl(reply.magic) != NBD_REPLY_MAGIC) { 349f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)\n", 350e4b57e0842621f597d744b193ea325d62724596bMichal Feix (unsigned long)ntohl(reply.magic)); 351e4b57e0842621f597d744b193ea325d62724596bMichal Feix result = -EPROTO; 352e4b57e0842621f597d744b193ea325d62724596bMichal Feix goto harderror; 353e4b57e0842621f597d744b193ea325d62724596bMichal Feix } 354e4b57e0842621f597d744b193ea325d62724596bMichal Feix 355f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao req = nbd_find_request(nbd, *(struct request **)reply.handle); 356801678c5a3b4c79236970bcca27c733f5559e0d1Hirofumi Nakagawa if (IS_ERR(req)) { 3574b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu result = PTR_ERR(req); 3584b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu if (result != -ENOENT) 3594b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu goto harderror; 3604b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu 361f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p)\n", 3627f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong reply.handle); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -EBADR; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto harderror; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ntohl(reply.error)) { 368f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n", 3697f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong ntohl(reply.error)); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->errors++; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return req; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(DBG_RX, "%s: request %p: got reply\n", 375f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->disk->disk_name, req); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nbd_cmd(req) == NBD_CMD_READ) { 3775705f7021748a69d84d6567e68e8851dab551464NeilBrown struct req_iterator iter; 3787988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet struct bio_vec bvec; 3795705f7021748a69d84d6567e68e8851dab551464NeilBrown 3805705f7021748a69d84d6567e68e8851dab551464NeilBrown rq_for_each_segment(bvec, req, iter) { 3817988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet result = sock_recv_bvec(nbd, &bvec); 3826c92e699b56287da582ccb12a64b959b6d6109baJens Axboe if (result <= 0) { 383f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n", 3847f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong result); 3856c92e699b56287da582ccb12a64b959b6d6109baJens Axboe req->errors++; 3866c92e699b56287da582ccb12a64b959b6d6109baJens Axboe return req; 3876c92e699b56287da582ccb12a64b959b6d6109baJens Axboe } 3886c92e699b56287da582ccb12a64b959b6d6109baJens Axboe dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", 3897988613b0e5b2638caf6cd493cc78e9595eba19cKent Overstreet nbd->disk->disk_name, req, bvec.bv_len); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return req; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsharderror: 394f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->harderror = result; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 398edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic ssize_t pid_show(struct device *dev, 399edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct device_attribute *attr, char *buf) 4006b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements{ 401edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers struct gendisk *disk = dev_to_disk(dev); 402edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers 403edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sievers return sprintf(buf, "%ld\n", 4046b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements (long) ((struct nbd_device *)disk->private_data)->pid); 4056b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements} 4066b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements 407edfaa7c36574f1bf09c65ad602412db9da5f96bfKay Sieversstatic struct device_attribute pid_attr = { 40801e8ef11bc1a74e65678ed55795f59266d4add01Parag Warudkar .attr = { .name = "pid", .mode = S_IRUGO}, 4096b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements .show = pid_show, 4106b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements}; 4116b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements 412f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int nbd_do_it(struct nbd_device *nbd) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct request *req; 41584963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong int ret; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 417f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(nbd->magic != NBD_MAGIC); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4197f338fe4540b1d0600b02314c7d885fd358e9ecaMel Gorman sk_set_memalloc(nbd->sock->sk); 420f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->pid = task_pid_nr(current); 421f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); 42284963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong if (ret) { 423f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); 424f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->pid = 0; 42584963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong return ret; 42684963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong } 4276b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements 428f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao while ((req = nbd_read_stat(nbd)) != NULL) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nbd_end_request(req); 4306b39bb6548d60b9a18826134b5ccd5c3cef85fe2Paul Clements 431f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao device_remove_file(disk_to_dev(nbd->disk), &pid_attr); 432f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->pid = 0; 43384963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong return 0; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 436f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void nbd_clear_que(struct nbd_device *nbd) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct request *req; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 440f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(nbd->magic != NBD_MAGIC); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4424b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu /* 443f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao * Because we have set nbd->sock to NULL under the tx_lock, all 4444b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * modifications to the list must have completed by now. For 4454b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * the same reason, the active_req must be NULL. 4464b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * 4474b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * As a consequence, we don't need to take the spin lock while 4484b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * purging the list here. 4494b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu */ 450f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(nbd->sock); 451f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(nbd->active_req); 4524b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu 453f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao while (!list_empty(&nbd->queue_head)) { 454f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao req = list_entry(nbd->queue_head.next, struct request, 4554b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu queuelist); 4564b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu list_del_init(&req->queuelist); 4574b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu req->errors++; 4584b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu nbd_end_request(req); 4594b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu } 460fded4e090c60100d709318896c79816d68d5b47dPaul Clements 461fded4e090c60100d709318896c79816d68d5b47dPaul Clements while (!list_empty(&nbd->waiting_queue)) { 462fded4e090c60100d709318896c79816d68d5b47dPaul Clements req = list_entry(nbd->waiting_queue.next, struct request, 463fded4e090c60100d709318896c79816d68d5b47dPaul Clements queuelist); 464fded4e090c60100d709318896c79816d68d5b47dPaul Clements list_del_init(&req->queuelist); 465fded4e090c60100d709318896c79816d68d5b47dPaul Clements req->errors++; 466fded4e090c60100d709318896c79816d68d5b47dPaul Clements nbd_end_request(req); 467fded4e090c60100d709318896c79816d68d5b47dPaul Clements } 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4707fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements 471f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic void nbd_handle_req(struct nbd_device *nbd, struct request *req) 47248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{ 47333659ebbae262228eef4e0fe990f393d1f0ed941Christoph Hellwig if (req->cmd_type != REQ_TYPE_FS) 47448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier goto error_out; 47548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 47648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier nbd_cmd(req) = NBD_CMD_READ; 47748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier if (rq_data_dir(req) == WRITE) { 478a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements if ((req->cmd_flags & REQ_DISCARD)) { 479a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM)); 480a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements nbd_cmd(req) = NBD_CMD_TRIM; 481a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements } else 482a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements nbd_cmd(req) = NBD_CMD_WRITE; 4832f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements if (nbd->flags & NBD_FLAG_READ_ONLY) { 484f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), 4857f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong "Write on read-only\n"); 48648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier goto error_out; 48748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier } 48848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier } 48948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 49075f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh if (req->cmd_flags & REQ_FLUSH) { 49175f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh BUG_ON(unlikely(blk_rq_sectors(req))); 49275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh nbd_cmd(req) = NBD_CMD_FLUSH; 49375f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh } 49475f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh 49548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier req->errors = 0; 49648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 497f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_lock(&nbd->tx_lock); 498f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao if (unlikely(!nbd->sock)) { 499f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_unlock(&nbd->tx_lock); 500f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), 5017f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong "Attempted send on closed socket\n"); 50215746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machek goto error_out; 50348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier } 50448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 505f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->active_req = req; 50648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 507f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao if (nbd_send_req(nbd, req) != 0) { 508f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), "Request send failed\n"); 50948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier req->errors++; 51048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier nbd_end_request(req); 51148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier } else { 512f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_lock(&nbd->queue_lock); 51301ff5dbc0925d11c8ad76eed3bdd02d0c7e1e0f5Chetan Loke list_add_tail(&req->queuelist, &nbd->queue_head); 514f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_unlock(&nbd->queue_lock); 51548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier } 51648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 517f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->active_req = NULL; 518f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_unlock(&nbd->tx_lock); 519f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao wake_up_all(&nbd->active_wq); 52048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 52148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier return; 52248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 52348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Viviererror_out: 52448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier req->errors++; 52548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier nbd_end_request(req); 52648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier} 52748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 52848cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivierstatic int nbd_thread(void *data) 52948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier{ 530f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao struct nbd_device *nbd = data; 53148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier struct request *req; 53248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 5338698a745d800c59cd5a576398bdeccd578ac66f1Dongsheng Yang set_user_nice(current, MIN_NICE); 534f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) { 53548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier /* wait for something to do */ 536f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao wait_event_interruptible(nbd->waiting_wq, 53748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier kthread_should_stop() || 538f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao !list_empty(&nbd->waiting_queue)); 53948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 54048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier /* extract request */ 541f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao if (list_empty(&nbd->waiting_queue)) 54248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier continue; 54348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 544f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_lock_irq(&nbd->queue_lock); 545f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao req = list_entry(nbd->waiting_queue.next, struct request, 54648cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier queuelist); 54748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier list_del_init(&req->queuelist); 548f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_unlock_irq(&nbd->queue_lock); 54948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 55048cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier /* handle request */ 551f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd_handle_req(nbd, req); 55248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier } 55348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier return 0; 55448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier} 55548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We always wait for result of write, for now. It would be nice to make it optional 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in future 559f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao * if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK)) 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); } 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56315746fcaa3a00753bbab2326088b85b10c1ba36aPavel Machekstatic void do_nbd_request(struct request_queue *q) 564398eb08555b24049e0362fee92920982b283fd96Alex Elder __releases(q->queue_lock) __acquires(q->queue_lock) 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct request *req; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5689934c8c04561413609d2bc38c6b9f268cba774a4Tejun Heo while ((req = blk_fetch_request(q)) != NULL) { 569f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao struct nbd_device *nbd; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57148cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier spin_unlock_irq(q->queue_lock); 57248cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier 5734aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", 5744aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe req->rq_disk->disk_name, req, req->cmd_type); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 576f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd = req->rq_disk->private_data; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 578f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(nbd->magic != NBD_MAGIC); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 580f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao if (unlikely(!nbd->sock)) { 581f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_err(disk_to_dev(nbd->disk), 5827f1b90f99a2d4253f8eb1221d39da072178adbc5WANG Cong "Attempted send on closed socket\n"); 5834d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements req->errors++; 5844d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements nbd_end_request(req); 5854d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements spin_lock_irq(q->queue_lock); 5864d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements continue; 5874d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements } 5884d48a542b42747c36a5937447d9c3de7c897ea50Paul Clements 589f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_lock_irq(&nbd->queue_lock); 590f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao list_add_tail(&req->queuelist, &nbd->waiting_queue); 591f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao spin_unlock_irq(&nbd->queue_lock); 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 593f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao wake_up(&nbd->waiting_wq); 5944b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(q->queue_lock); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5991a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek/* Must be called with tx_lock held */ 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gaostatic int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, 6021a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek unsigned int cmd, unsigned long arg) 6031a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{ 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 6051a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek case NBD_DISCONNECT: { 6061a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek struct request sreq; 6071a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 608f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n"); 6093a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini if (!nbd->sock) 6103a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini return -EINVAL; 6111a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6123a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini mutex_unlock(&nbd->tx_lock); 6133a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini fsync_bdev(bdev); 6143a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini mutex_lock(&nbd->tx_lock); 6154f54eec8311c3325888c29ce8e4496daf4dbe624FUJITA Tomonori blk_rq_init(NULL, &sreq); 6164aff5e2333c9a1609662f2091f55c3f6fffdad36Jens Axboe sreq.cmd_type = REQ_TYPE_SPECIAL; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nbd_cmd(&sreq) = NBD_CMD_DISC; 6183a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini 6193a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini /* Check again after getting mutex back. */ 620f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao if (!nbd->sock) 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6223a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini 623c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements nbd->disconnect = 1; 624c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements 625f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd_send_req(nbd, &sreq); 626c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements return 0; 6271a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek } 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6291a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek case NBD_CLEAR_SOCK: { 630e25115786ee540fc428a14872ebd4f56252aba32Al Viro struct socket *sock = nbd->sock; 631f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->sock = NULL; 632f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd_clear_que(nbd); 633f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(!list_empty(&nbd->queue_head)); 634fded4e090c60100d709318896c79816d68d5b47dPaul Clements BUG_ON(!list_empty(&nbd->waiting_queue)); 6353a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini kill_bdev(bdev); 636e25115786ee540fc428a14872ebd4f56252aba32Al Viro if (sock) 637e25115786ee540fc428a14872ebd4f56252aba32Al Viro sockfd_put(sock); 6381a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek return 0; 6391a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek } 6401a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6411a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek case NBD_SET_SOCK: { 642e25115786ee540fc428a14872ebd4f56252aba32Al Viro struct socket *sock; 643e25115786ee540fc428a14872ebd4f56252aba32Al Viro int err; 644e25115786ee540fc428a14872ebd4f56252aba32Al Viro if (nbd->sock) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 646e25115786ee540fc428a14872ebd4f56252aba32Al Viro sock = sockfd_lookup(arg, &err); 647e25115786ee540fc428a14872ebd4f56252aba32Al Viro if (sock) { 648e25115786ee540fc428a14872ebd4f56252aba32Al Viro nbd->sock = sock; 649e25115786ee540fc428a14872ebd4f56252aba32Al Viro if (max_part > 0) 650e25115786ee540fc428a14872ebd4f56252aba32Al Viro bdev->bd_invalidated = 1; 651e25115786ee540fc428a14872ebd4f56252aba32Al Viro nbd->disconnect = 0; /* we're connected now */ 652e25115786ee540fc428a14872ebd4f56252aba32Al Viro return 0; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6541a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek return -EINVAL; 6551a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek } 6561a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NBD_SET_BLKSIZE: 658f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->blksize = arg; 659f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->bytesize &= ~(nbd->blksize-1); 660f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao bdev->bd_inode->i_size = nbd->bytesize; 661f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_blocksize(bdev, nbd->blksize); 662f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_capacity(nbd->disk, nbd->bytesize >> 9); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6641a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NBD_SET_SIZE: 666f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->bytesize = arg & ~(nbd->blksize-1); 667f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao bdev->bd_inode->i_size = nbd->bytesize; 668f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_blocksize(bdev, nbd->blksize); 669f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_capacity(nbd->disk, nbd->bytesize >> 9); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6727fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements case NBD_SET_TIMEOUT: 673f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->xmit_timeout = arg * HZ; 6747fdfd4065c264bddd2d9277470a6a99d34e01befPaul Clements return 0; 6751a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6762f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements case NBD_SET_FLAGS: 6772f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements nbd->flags = arg; 6782f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements return 0; 6792f012508880f8037590372c24ca6e8b6af8fffb6Paul Clements 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NBD_SET_SIZE_BLOCKS: 681f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->bytesize = ((u64) arg) * nbd->blksize; 682f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao bdev->bd_inode->i_size = nbd->bytesize; 683f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_blocksize(bdev, nbd->blksize); 684f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_capacity(nbd->disk, nbd->bytesize >> 9); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6861a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 6871a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek case NBD_DO_IT: { 6881a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek struct task_struct *thread; 689e25115786ee540fc428a14872ebd4f56252aba32Al Viro struct socket *sock; 6901a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek int error; 6911a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 692f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao if (nbd->pid) 693c91192d66d6cea7878b8542c9d9f1873971aba92Pavel Machek return -EBUSY; 694e25115786ee540fc428a14872ebd4f56252aba32Al Viro if (!nbd->sock) 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6961a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 697f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_unlock(&nbd->tx_lock); 6981a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 699a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini if (nbd->flags & NBD_FLAG_READ_ONLY) 700a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini set_device_ro(bdev, true); 701a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements if (nbd->flags & NBD_FLAG_SEND_TRIM) 702a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, 703a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements nbd->disk->queue); 70475f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh if (nbd->flags & NBD_FLAG_SEND_FLUSH) 70575f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh blk_queue_flush(nbd->disk->queue, REQ_FLUSH); 70675f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh else 70775f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh blk_queue_flush(nbd->disk->queue, 0); 708a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements 709ffc8b30866879ed9ba62bd0a86fecdbd51cd3d19Kees Cook thread = kthread_create(nbd_thread, nbd, "%s", 710ffc8b30866879ed9ba62bd0a86fecdbd51cd3d19Kees Cook nbd->disk->disk_name); 7111a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek if (IS_ERR(thread)) { 712f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_lock(&nbd->tx_lock); 71348cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier return PTR_ERR(thread); 7141a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek } 71548cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier wake_up_process(thread); 716f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao error = nbd_do_it(nbd); 71748cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier kthread_stop(thread); 7181a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 719f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_lock(&nbd->tx_lock); 72084963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong if (error) 72184963048ca8093e0aa71ac90c2a5fe7af5f617c3WANG Cong return error; 722f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao sock_shutdown(nbd, 0); 723e25115786ee540fc428a14872ebd4f56252aba32Al Viro sock = nbd->sock; 724e25115786ee540fc428a14872ebd4f56252aba32Al Viro nbd->sock = NULL; 725f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd_clear_que(nbd); 726f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_warn(disk_to_dev(nbd->disk), "queue cleared\n"); 7273a2d63f87989e01437ba994df5f297528c353d7dPaolo Bonzini kill_bdev(bdev); 728a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); 729a83e814b5bb948850e903585d18b6298b7093cb2Paolo Bonzini set_device_ro(bdev, false); 730e25115786ee540fc428a14872ebd4f56252aba32Al Viro if (sock) 731e25115786ee540fc428a14872ebd4f56252aba32Al Viro sockfd_put(sock); 73275f187aba5e7a3eea259041f85099029774a4c5bAlex Bligh nbd->flags = 0; 733f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->bytesize = 0; 734a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro bdev->bd_inode->i_size = 0; 735f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao set_capacity(nbd->disk, 0); 736d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier if (max_part > 0) 737a8cdc308c0ca3809e37e2be62174906a45b92670Al Viro ioctl_by_bdev(bdev, BLKRRPART, 0); 738c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements if (nbd->disconnect) /* user requested, ignore socket errors */ 739c378f70adbc1bbecd9e6db145019f14b2f688c7cPaul Clements return 0; 740f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao return nbd->harderror; 7411a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek } 7421a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NBD_CLEAR_QUE: 7444b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu /* 7454b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * This is for compatibility only. The queue is always cleared 7464b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu * by NBD_DO_IT or NBD_CLEAR_SOCK. 7474b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu */ 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7491a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NBD_PRINT_DEBUG: 751f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao dev_info(disk_to_dev(nbd->disk), 7525eedf5415cd57f8db8642a5db4cf8e5507390030WANG Cong "next = %p, prev = %p, head = %p\n", 753f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->queue_head.next, nbd->queue_head.prev, 754f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao &nbd->queue_head); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7571a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek return -ENOTTY; 7581a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek} 7591a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 7601a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machekstatic int nbd_ioctl(struct block_device *bdev, fmode_t mode, 7611a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek unsigned int cmd, unsigned long arg) 7621a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek{ 763f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao struct nbd_device *nbd = bdev->bd_disk->private_data; 7641a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek int error; 7651a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 7661a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek if (!capable(CAP_SYS_ADMIN)) 7671a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek return -EPERM; 7681a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 769f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao BUG_ON(nbd->magic != NBD_MAGIC); 7701a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 7711a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek /* Anyone capable of this syscall can do *real bad* things */ 7721a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n", 773f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); 7741a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 775f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_lock(&nbd->tx_lock); 776f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao error = __nbd_ioctl(bdev, nbd, cmd, arg); 777f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao mutex_unlock(&nbd->tx_lock); 7781a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek 7791a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3Pavel Machek return error; 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 78283d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations nbd_fops = 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 7858a6cfeb6deca3a8fefd639d898b0d163c0b5d368Arnd Bergmann .ioctl = nbd_ioctl, 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And here should be modules and kernel interface 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (Just smiley confuses emacs :-) 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init nbd_init(void) 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENOMEM; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 797d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier int part_shift; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7995b7b18ccdeb17dcc4a2ddbf4ce87094c7365f4b9Adrian Bunk BUILD_BUG_ON(sizeof(struct nbd_request) != 28); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier if (max_part < 0) { 8027742ce4ab49976851ce7f0185dcbe491935371a2WANG Cong printk(KERN_ERR "nbd: max_part must be >= 0\n"); 803d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier return -EINVAL; 804d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier } 805d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier 806f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); 807f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener if (!nbd_dev) 808f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener return -ENOMEM; 809f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener 810d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier part_shift = 0; 8115988ce239682854d4e632fb58bff000700830394Namhyung Kim if (max_part > 0) { 812d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier part_shift = fls(max_part); 813d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier 8145988ce239682854d4e632fb58bff000700830394Namhyung Kim /* 8155988ce239682854d4e632fb58bff000700830394Namhyung Kim * Adjust max_part according to part_shift as it is exported 8165988ce239682854d4e632fb58bff000700830394Namhyung Kim * to user space so that user can know the max number of 8175988ce239682854d4e632fb58bff000700830394Namhyung Kim * partition kernel should be able to manage. 8185988ce239682854d4e632fb58bff000700830394Namhyung Kim * 8195988ce239682854d4e632fb58bff000700830394Namhyung Kim * Note that -1 is required because partition 0 is reserved 8205988ce239682854d4e632fb58bff000700830394Namhyung Kim * for the whole disk. 8215988ce239682854d4e632fb58bff000700830394Namhyung Kim */ 8225988ce239682854d4e632fb58bff000700830394Namhyung Kim max_part = (1UL << part_shift) - 1; 8235988ce239682854d4e632fb58bff000700830394Namhyung Kim } 8245988ce239682854d4e632fb58bff000700830394Namhyung Kim 8253b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim if ((1UL << part_shift) > DISK_MAX_PARTS) 8263b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim return -EINVAL; 8273b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim 8283b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim if (nbds_max > 1UL << (MINORBITS - part_shift)) 8293b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim return -EINVAL; 8303b2710824e00d238554c13b5add347e6c701ab1aNamhyung Kim 83140be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree for (i = 0; i < nbds_max; i++) { 832d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier struct gendisk *disk = alloc_disk(1 << part_shift); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!disk) 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nbd_dev[i].disk = disk; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The new linux 2.5 block layer implementation requires 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * every gendisk to have its very own request_queue struct. 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These structs are big so we dynamically allocate them. 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disk->queue = blk_init_queue(do_nbd_request, &nbd_lock); 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!disk->queue) { 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(disk); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 84631dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe /* 84731dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe * Tell the block layer that we are not a rotational device 84831dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe */ 84931dcfab0ae6eb0340d456931df4d478e17efc65dJens Axboe queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue); 850b277da0a8a594308e17881f4926879bd5fca2a2dMike Snitzer queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, disk->queue); 851a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements disk->queue->limits.discard_granularity = 512; 852a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements disk->queue->limits.max_discard_sectors = UINT_MAX; 853a336d29870f8a1f8e5f10d9f1aa95531c4edeabePaul Clements disk->queue->limits.discard_zeroes_data = 0; 854078be02b80359a541928c899c2631f39628f56dfMichal Belczyk blk_queue_max_hw_sectors(disk->queue, 65536); 855078be02b80359a541928c899c2631f39628f56dfMichal Belczyk disk->queue->limits.max_sectors = 256; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (register_blkdev(NBD_MAJOR, "nbd")) { 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EIO; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR); 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags); 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 86640be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree for (i = 0; i < nbds_max; i++) { 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *disk = nbd_dev[i].disk; 868f4507164e7796b66c371ff9a63154f1c884a2433Wanlong Gao nbd_dev[i].magic = NBD_MAGIC; 86948cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier INIT_LIST_HEAD(&nbd_dev[i].waiting_queue); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&nbd_dev[i].queue_lock); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&nbd_dev[i].queue_head); 87282d4dc5adb0055393248ad4ab8de392fac708a12Ingo Molnar mutex_init(&nbd_dev[i].tx_lock); 8734b2f0260c74324abca76ccaa42d426af163125e7Herbert Xu init_waitqueue_head(&nbd_dev[i].active_wq); 87448cf6061b30205b29b306bf9bc22dd6f0b091461Laurent Vivier init_waitqueue_head(&nbd_dev[i].waiting_wq); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nbd_dev[i].blksize = 1024; 8764b86a872561ad052bdc6f092a06807822d26beb1Paul Clements nbd_dev[i].bytesize = 0; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disk->major = NBD_MAJOR; 878d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Vivier disk->first_minor = i << part_shift; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disk->fops = &nbd_fops; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disk->private_data = &nbd_dev[i]; 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(disk->disk_name, "nbd%d", i); 8824b86a872561ad052bdc6f092a06807822d26beb1Paul Clements set_capacity(disk, 0); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_disk(disk); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (i--) { 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blk_cleanup_queue(nbd_dev[i].disk->queue); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(nbd_dev[i].disk); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 892f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener kfree(nbd_dev); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit nbd_cleanup(void) 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 89940be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree for (i = 0; i < nbds_max; i++) { 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gendisk *disk = nbd_dev[i].disk; 90140be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Bree nbd_dev[i].magic = 0; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (disk) { 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_gendisk(disk); 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blk_cleanup_queue(disk->queue); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_disk(disk); 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_blkdev(NBD_MAJOR, "nbd"); 909f3944d61ddc65722539ffd7b6f5b7c7217c136ccSven Wegener kfree(nbd_dev); 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(nbd_init); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(nbd_cleanup); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Network Block Device"); 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91940be0c28b33ff0821594a3fa7126354dfe6eccd1Lars Marowsky-Breemodule_param(nbds_max, int, 0444); 920d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)"); 921d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent Viviermodule_param(max_part, int, 0444); 922d71a6d7332e5881a65249f4fb97b0db3c61dd5ecLaurent VivierMODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)"); 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NDEBUG 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debugflags, int, 0644); 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debugflags, "flags for controlling debug output"); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 927