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, ¤t->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