Blame view
drivers/block/nbd.c
22.5 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * Network block device - make block devices work over TCP * * Note that you can not swap over this thing, yet. Seems to work but * deadlocks sometimes - you can not swap over TCP in general. * |
a2531293d update email address |
7 |
* Copyright 1997-2000, 2008 Pavel Machek <pavel@ucw.cz> |
1da177e4c Linux-2.6.12-rc2 |
8 9 |
* Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com> * |
dbf492d6c [PATCH] nbd: kill... |
10 |
* This file is released under GPLv2 or later. |
1da177e4c Linux-2.6.12-rc2 |
11 |
* |
dbf492d6c [PATCH] nbd: kill... |
12 |
* (part of code stolen from loop.c) |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
*/ #include <linux/major.h> #include <linux/blkdev.h> #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/fs.h> #include <linux/bio.h> #include <linux/stat.h> #include <linux/errno.h> #include <linux/file.h> #include <linux/ioctl.h> |
2a48fc0ab block: autoconver... |
27 |
#include <linux/mutex.h> |
4b2f0260c [PATCH] nbd: fix ... |
28 29 30 |
#include <linux/compiler.h> #include <linux/err.h> #include <linux/kernel.h> |
5a0e3ad6a include cleanup: ... |
31 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
#include <net/sock.h> |
91cf45f02 [NET]: Add the he... |
33 |
#include <linux/net.h> |
48cf6061b NBD: allow nbd to... |
34 |
#include <linux/kthread.h> |
1da177e4c Linux-2.6.12-rc2 |
35 |
|
1da177e4c Linux-2.6.12-rc2 |
36 37 38 39 |
#include <asm/uaccess.h> #include <asm/types.h> #include <linux/nbd.h> |
f4507164e nbd: rename the n... |
40 |
#define NBD_MAGIC 0x68797548 |
1da177e4c Linux-2.6.12-rc2 |
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#ifdef NDEBUG #define dprintk(flags, fmt...) #else /* NDEBUG */ #define dprintk(flags, fmt...) do { \ if (debugflags & (flags)) printk(KERN_DEBUG fmt); \ } while (0) #define DBG_IOCTL 0x0004 #define DBG_INIT 0x0010 #define DBG_EXIT 0x0020 #define DBG_BLKDEV 0x0100 #define DBG_RX 0x0200 #define DBG_TX 0x0400 static unsigned int debugflags; #endif /* NDEBUG */ |
9c7a41691 [PATCH] drivers/b... |
56 |
static unsigned int nbds_max = 16; |
20a8143ea NBD: remove limit... |
57 |
static struct nbd_device *nbd_dev; |
d71a6d733 NBD: add partitio... |
58 |
static int max_part; |
1da177e4c Linux-2.6.12-rc2 |
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
/* * Use just one lock (or at most 1 per NIC). Two arguments for this: * 1. Each NIC is essentially a synchronization point for all servers * accessed through that NIC so there's no need to have more locks * than NICs anyway. * 2. More locks lead to more "Dirty cache line bouncing" which will slow * down each lock to the point where they're actually slower than just * a single lock. * Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this! */ static DEFINE_SPINLOCK(nbd_lock); #ifndef NDEBUG static const char *ioctl_cmd_to_ascii(int cmd) { switch (cmd) { case NBD_SET_SOCK: return "set-sock"; case NBD_SET_BLKSIZE: return "set-blksize"; case NBD_SET_SIZE: return "set-size"; |
2f0125088 nbd: add set flag... |
79 80 |
case NBD_SET_TIMEOUT: return "set-timeout"; case NBD_SET_FLAGS: return "set-flags"; |
1da177e4c Linux-2.6.12-rc2 |
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
case NBD_DO_IT: return "do-it"; case NBD_CLEAR_SOCK: return "clear-sock"; case NBD_CLEAR_QUE: return "clear-que"; case NBD_PRINT_DEBUG: return "print-debug"; case NBD_SET_SIZE_BLOCKS: return "set-size-blocks"; case NBD_DISCONNECT: return "disconnect"; case BLKROSET: return "set-read-only"; case BLKFLSBUF: return "flush-buffer-cache"; } return "unknown"; } static const char *nbdcmd_to_ascii(int cmd) { switch (cmd) { case NBD_CMD_READ: return "read"; case NBD_CMD_WRITE: return "write"; case NBD_CMD_DISC: return "disconnect"; |
75f187aba nbd: support FLUS... |
99 |
case NBD_CMD_FLUSH: return "flush"; |
a336d2987 nbd: handle disca... |
100 |
case NBD_CMD_TRIM: return "trim/discard"; |
1da177e4c Linux-2.6.12-rc2 |
101 102 103 104 105 106 107 |
} return "invalid"; } #endif /* NDEBUG */ static void nbd_end_request(struct request *req) { |
097c94a4e blk_end_request: ... |
108 |
int error = req->errors ? -EIO : 0; |
165125e1e [BLOCK] Get rid o... |
109 |
struct request_queue *q = req->q; |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 113 |
unsigned long flags; dprintk(DBG_BLKDEV, "%s: request %p: %s ", req->rq_disk->disk_name, |
097c94a4e blk_end_request: ... |
114 |
req, error ? "failed" : "done"); |
1da177e4c Linux-2.6.12-rc2 |
115 116 |
spin_lock_irqsave(q->queue_lock, flags); |
1011c1b9f block: blk_rq_[cu... |
117 |
__blk_end_request_all(req, error); |
1da177e4c Linux-2.6.12-rc2 |
118 119 |
spin_unlock_irqrestore(q->queue_lock, flags); } |
f4507164e nbd: rename the n... |
120 |
static void sock_shutdown(struct nbd_device *nbd, int lock) |
7fdfd4065 NBD: allow hung n... |
121 122 123 124 125 126 127 128 |
{ /* Forcibly shutdown the socket causing all listeners * to error * * FIXME: This code is duplicated from sys_shutdown, but * there should be a more generic interface rather than * calling socket ops directly here */ if (lock) |
f4507164e nbd: rename the n... |
129 130 131 132 133 134 |
mutex_lock(&nbd->tx_lock); if (nbd->sock) { dev_warn(disk_to_dev(nbd->disk), "shutting down socket "); kernel_sock_shutdown(nbd->sock, SHUT_RDWR); nbd->sock = NULL; |
7fdfd4065 NBD: allow hung n... |
135 136 |
} if (lock) |
f4507164e nbd: rename the n... |
137 |
mutex_unlock(&nbd->tx_lock); |
7fdfd4065 NBD: allow hung n... |
138 139 140 141 142 143 144 145 146 147 148 |
} static void nbd_xmit_timeout(unsigned long arg) { struct task_struct *task = (struct task_struct *)arg; printk(KERN_WARNING "nbd: killing hung xmit (%s, pid: %d) ", task->comm, task->pid); force_sig(SIGKILL, task); } |
1da177e4c Linux-2.6.12-rc2 |
149 150 151 |
/* * Send or receive packet. */ |
f4507164e nbd: rename the n... |
152 |
static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, |
1da177e4c Linux-2.6.12-rc2 |
153 154 |
int msg_flags) { |
f4507164e nbd: rename the n... |
155 |
struct socket *sock = nbd->sock; |
1da177e4c Linux-2.6.12-rc2 |
156 157 158 |
int result; struct msghdr msg; struct kvec iov; |
be0ef957c nbd.c: sock_xmit:... |
159 |
sigset_t blocked, oldset; |
7f338fe45 nbd: set SOCK_MEM... |
160 |
unsigned long pflags = current->flags; |
1da177e4c Linux-2.6.12-rc2 |
161 |
|
ffc41cf8d nbd: prevent sock... |
162 |
if (unlikely(!sock)) { |
f4507164e nbd: rename the n... |
163 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
164 165 166 |
"Attempted %s on closed socket in sock_xmit ", (send ? "send" : "recv")); |
ffc41cf8d nbd: prevent sock... |
167 168 |
return -EINVAL; } |
1da177e4c Linux-2.6.12-rc2 |
169 170 |
/* Allow interception of SIGKILL only * Don't allow other signals to interrupt the transmission */ |
be0ef957c nbd.c: sock_xmit:... |
171 172 |
siginitsetinv(&blocked, sigmask(SIGKILL)); sigprocmask(SIG_SETMASK, &blocked, &oldset); |
1da177e4c Linux-2.6.12-rc2 |
173 |
|
7f338fe45 nbd: set SOCK_MEM... |
174 |
current->flags |= PF_MEMALLOC; |
1da177e4c Linux-2.6.12-rc2 |
175 |
do { |
7f338fe45 nbd: set SOCK_MEM... |
176 |
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; |
1da177e4c Linux-2.6.12-rc2 |
177 178 179 180 181 182 |
iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; |
1da177e4c Linux-2.6.12-rc2 |
183 |
msg.msg_flags = msg_flags | MSG_NOSIGNAL; |
7fdfd4065 NBD: allow hung n... |
184 185 |
if (send) { struct timer_list ti; |
f4507164e nbd: rename the n... |
186 |
if (nbd->xmit_timeout) { |
7fdfd4065 NBD: allow hung n... |
187 188 189 |
init_timer(&ti); ti.function = nbd_xmit_timeout; ti.data = (unsigned long)current; |
f4507164e nbd: rename the n... |
190 |
ti.expires = jiffies + nbd->xmit_timeout; |
7fdfd4065 NBD: allow hung n... |
191 192 |
add_timer(&ti); } |
1da177e4c Linux-2.6.12-rc2 |
193 |
result = kernel_sendmsg(sock, &msg, &iov, 1, size); |
f4507164e nbd: rename the n... |
194 |
if (nbd->xmit_timeout) |
7fdfd4065 NBD: allow hung n... |
195 196 |
del_timer_sync(&ti); } else |
35fbf5bcf nbd: pass MSG_* f... |
197 198 |
result = kernel_recvmsg(sock, &msg, &iov, 1, size, msg.msg_flags); |
1da177e4c Linux-2.6.12-rc2 |
199 200 201 |
if (signal_pending(current)) { siginfo_t info; |
1da177e4c Linux-2.6.12-rc2 |
202 203 |
printk(KERN_WARNING "nbd (pid %d: %s) got signal %d ", |
ba25f9dcc Use helpers to ob... |
204 |
task_pid_nr(current), current->comm, |
be0ef957c nbd.c: sock_xmit:... |
205 |
dequeue_signal_lock(current, ¤t->blocked, &info)); |
1da177e4c Linux-2.6.12-rc2 |
206 |
result = -EINTR; |
f4507164e nbd: rename the n... |
207 |
sock_shutdown(nbd, !send); |
1da177e4c Linux-2.6.12-rc2 |
208 209 210 211 212 213 214 215 216 217 218 |
break; } if (result <= 0) { if (result == 0) result = -EPIPE; /* short read */ break; } size -= result; buf += result; } while (size > 0); |
be0ef957c nbd.c: sock_xmit:... |
219 |
sigprocmask(SIG_SETMASK, &oldset, NULL); |
7f338fe45 nbd: set SOCK_MEM... |
220 |
tsk_restore_flags(current, pflags, PF_MEMALLOC); |
1da177e4c Linux-2.6.12-rc2 |
221 222 223 |
return result; } |
f4507164e nbd: rename the n... |
224 |
static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec, |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 228 |
int flags) { int result; void *kaddr = kmap(bvec->bv_page); |
f4507164e nbd: rename the n... |
229 230 |
result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags); |
1da177e4c Linux-2.6.12-rc2 |
231 232 233 |
kunmap(bvec->bv_page); return result; } |
7fdfd4065 NBD: allow hung n... |
234 |
/* always call with the tx_lock held */ |
f4507164e nbd: rename the n... |
235 |
static int nbd_send_req(struct nbd_device *nbd, struct request *req) |
1da177e4c Linux-2.6.12-rc2 |
236 |
{ |
5705f7021 Introduce rq_for_... |
237 |
int result, flags; |
1da177e4c Linux-2.6.12-rc2 |
238 |
struct nbd_request request; |
1011c1b9f block: blk_rq_[cu... |
239 |
unsigned long size = blk_rq_bytes(req); |
1da177e4c Linux-2.6.12-rc2 |
240 241 242 |
request.magic = htonl(NBD_REQUEST_MAGIC); request.type = htonl(nbd_cmd(req)); |
75f187aba nbd: support FLUS... |
243 244 245 246 247 248 249 250 251 |
if (nbd_cmd(req) == NBD_CMD_FLUSH) { /* Other values are reserved for FLUSH requests. */ request.from = 0; request.len = 0; } else { request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); request.len = htonl(size); } |
1da177e4c Linux-2.6.12-rc2 |
252 |
memcpy(request.handle, &req, sizeof(req)); |
83096ebf1 block: convert to... |
253 254 |
dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB) ", |
f4507164e nbd: rename the n... |
255 |
nbd->disk->disk_name, req, |
1da177e4c Linux-2.6.12-rc2 |
256 |
nbdcmd_to_ascii(nbd_cmd(req)), |
83096ebf1 block: convert to... |
257 |
(unsigned long long)blk_rq_pos(req) << 9, |
1011c1b9f block: blk_rq_[cu... |
258 |
blk_rq_bytes(req)); |
f4507164e nbd: rename the n... |
259 |
result = sock_xmit(nbd, 1, &request, sizeof(request), |
7fdfd4065 NBD: allow hung n... |
260 |
(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0); |
1da177e4c Linux-2.6.12-rc2 |
261 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
262 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
263 264 |
"Send control failed (result %d) ", result); |
1da177e4c Linux-2.6.12-rc2 |
265 266 267 268 |
goto error_out; } if (nbd_cmd(req) == NBD_CMD_WRITE) { |
5705f7021 Introduce rq_for_... |
269 270 |
struct req_iterator iter; struct bio_vec *bvec; |
1da177e4c Linux-2.6.12-rc2 |
271 272 273 274 |
/* * we are really probing at internals to determine * whether to set MSG_MORE or not... */ |
5705f7021 Introduce rq_for_... |
275 |
rq_for_each_segment(bvec, req, iter) { |
6c92e699b Fixup rq_for_each... |
276 277 278 279 280 |
flags = 0; if (!rq_iter_last(req, iter)) flags = MSG_MORE; dprintk(DBG_TX, "%s: request %p: sending %d bytes data ", |
f4507164e nbd: rename the n... |
281 282 |
nbd->disk->disk_name, req, bvec->bv_len); result = sock_send_bvec(nbd, bvec, flags); |
6c92e699b Fixup rq_for_each... |
283 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
284 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
285 286 287 |
"Send data failed (result %d) ", result); |
6c92e699b Fixup rq_for_each... |
288 289 |
goto error_out; } |
1da177e4c Linux-2.6.12-rc2 |
290 291 |
} } |
1da177e4c Linux-2.6.12-rc2 |
292 293 294 |
return 0; error_out: |
15746fcaa nbd: trivial clea... |
295 |
return -EIO; |
1da177e4c Linux-2.6.12-rc2 |
296 |
} |
f4507164e nbd: rename the n... |
297 |
static struct request *nbd_find_request(struct nbd_device *nbd, |
0cbc591bf nbd: change a par... |
298 |
struct request *xreq) |
1da177e4c Linux-2.6.12-rc2 |
299 |
{ |
d2c9740b4 nbd: use list_for... |
300 |
struct request *req, *tmp; |
4b2f0260c [PATCH] nbd: fix ... |
301 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
302 |
|
f4507164e nbd: rename the n... |
303 |
err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq); |
4b2f0260c [PATCH] nbd: fix ... |
304 305 |
if (unlikely(err)) goto out; |
f4507164e nbd: rename the n... |
306 307 |
spin_lock(&nbd->queue_lock); list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) { |
1da177e4c Linux-2.6.12-rc2 |
308 309 310 |
if (req != xreq) continue; list_del_init(&req->queuelist); |
f4507164e nbd: rename the n... |
311 |
spin_unlock(&nbd->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
312 313 |
return req; } |
f4507164e nbd: rename the n... |
314 |
spin_unlock(&nbd->queue_lock); |
4b2f0260c [PATCH] nbd: fix ... |
315 316 317 318 319 |
err = -ENOENT; out: return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
320 |
} |
f4507164e nbd: rename the n... |
321 |
static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec) |
1da177e4c Linux-2.6.12-rc2 |
322 323 324 |
{ int result; void *kaddr = kmap(bvec->bv_page); |
f4507164e nbd: rename the n... |
325 |
result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len, |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 329 330 331 |
MSG_WAITALL); kunmap(bvec->bv_page); return result; } /* NULL returned = something went wrong, inform userspace */ |
f4507164e nbd: rename the n... |
332 |
static struct request *nbd_read_stat(struct nbd_device *nbd) |
1da177e4c Linux-2.6.12-rc2 |
333 334 335 336 |
{ int result; struct nbd_reply reply; struct request *req; |
1da177e4c Linux-2.6.12-rc2 |
337 338 |
reply.magic = 0; |
f4507164e nbd: rename the n... |
339 |
result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL); |
1da177e4c Linux-2.6.12-rc2 |
340 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
341 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
342 343 |
"Receive control failed (result %d) ", result); |
1da177e4c Linux-2.6.12-rc2 |
344 345 |
goto harderror; } |
e4b57e084 [PATCH] nbd: Chec... |
346 347 |
if (ntohl(reply.magic) != NBD_REPLY_MAGIC) { |
f4507164e nbd: rename the n... |
348 349 |
dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx) ", |
e4b57e084 [PATCH] nbd: Chec... |
350 351 352 353 |
(unsigned long)ntohl(reply.magic)); result = -EPROTO; goto harderror; } |
f4507164e nbd: rename the n... |
354 |
req = nbd_find_request(nbd, *(struct request **)reply.handle); |
801678c5a Remove duplicated... |
355 |
if (IS_ERR(req)) { |
4b2f0260c [PATCH] nbd: fix ... |
356 357 358 |
result = PTR_ERR(req); if (result != -ENOENT) goto harderror; |
f4507164e nbd: rename the n... |
359 360 |
dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p) ", |
7f1b90f99 nbd: replace prin... |
361 |
reply.handle); |
1da177e4c Linux-2.6.12-rc2 |
362 363 364 |
result = -EBADR; goto harderror; } |
1da177e4c Linux-2.6.12-rc2 |
365 |
if (ntohl(reply.error)) { |
f4507164e nbd: rename the n... |
366 367 |
dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d) ", |
7f1b90f99 nbd: replace prin... |
368 |
ntohl(reply.error)); |
1da177e4c Linux-2.6.12-rc2 |
369 370 371 372 373 374 |
req->errors++; return req; } dprintk(DBG_RX, "%s: request %p: got reply ", |
f4507164e nbd: rename the n... |
375 |
nbd->disk->disk_name, req); |
1da177e4c Linux-2.6.12-rc2 |
376 |
if (nbd_cmd(req) == NBD_CMD_READ) { |
5705f7021 Introduce rq_for_... |
377 378 379 380 |
struct req_iterator iter; struct bio_vec *bvec; rq_for_each_segment(bvec, req, iter) { |
f4507164e nbd: rename the n... |
381 |
result = sock_recv_bvec(nbd, bvec); |
6c92e699b Fixup rq_for_each... |
382 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
383 384 |
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d) ", |
7f1b90f99 nbd: replace prin... |
385 |
result); |
6c92e699b Fixup rq_for_each... |
386 387 388 389 390 |
req->errors++; return req; } dprintk(DBG_RX, "%s: request %p: got %d bytes data ", |
f4507164e nbd: rename the n... |
391 |
nbd->disk->disk_name, req, bvec->bv_len); |
1da177e4c Linux-2.6.12-rc2 |
392 393 394 395 |
} } return req; harderror: |
f4507164e nbd: rename the n... |
396 |
nbd->harderror = result; |
1da177e4c Linux-2.6.12-rc2 |
397 398 |
return NULL; } |
edfaa7c36 Driver core: conv... |
399 400 |
static ssize_t pid_show(struct device *dev, struct device_attribute *attr, char *buf) |
6b39bb654 [PATCH] nbd: show... |
401 |
{ |
edfaa7c36 Driver core: conv... |
402 403 404 405 |
struct gendisk *disk = dev_to_disk(dev); return sprintf(buf, "%ld ", |
6b39bb654 [PATCH] nbd: show... |
406 407 |
(long) ((struct nbd_device *)disk->private_data)->pid); } |
edfaa7c36 Driver core: conv... |
408 |
static struct device_attribute pid_attr = { |
01e8ef11b x86: sysfs: kill ... |
409 |
.attr = { .name = "pid", .mode = S_IRUGO}, |
6b39bb654 [PATCH] nbd: show... |
410 411 |
.show = pid_show, }; |
f4507164e nbd: rename the n... |
412 |
static int nbd_do_it(struct nbd_device *nbd) |
1da177e4c Linux-2.6.12-rc2 |
413 414 |
{ struct request *req; |
84963048c nbd: check the re... |
415 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
416 |
|
f4507164e nbd: rename the n... |
417 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1da177e4c Linux-2.6.12-rc2 |
418 |
|
7f338fe45 nbd: set SOCK_MEM... |
419 |
sk_set_memalloc(nbd->sock->sk); |
f4507164e nbd: rename the n... |
420 421 |
nbd->pid = task_pid_nr(current); ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); |
84963048c nbd: check the re... |
422 |
if (ret) { |
f4507164e nbd: rename the n... |
423 424 425 |
dev_err(disk_to_dev(nbd->disk), "device_create_file failed! "); nbd->pid = 0; |
84963048c nbd: check the re... |
426 427 |
return ret; } |
6b39bb654 [PATCH] nbd: show... |
428 |
|
f4507164e nbd: rename the n... |
429 |
while ((req = nbd_read_stat(nbd)) != NULL) |
1da177e4c Linux-2.6.12-rc2 |
430 |
nbd_end_request(req); |
6b39bb654 [PATCH] nbd: show... |
431 |
|
f4507164e nbd: rename the n... |
432 433 |
device_remove_file(disk_to_dev(nbd->disk), &pid_attr); nbd->pid = 0; |
84963048c nbd: check the re... |
434 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
435 |
} |
f4507164e nbd: rename the n... |
436 |
static void nbd_clear_que(struct nbd_device *nbd) |
1da177e4c Linux-2.6.12-rc2 |
437 438 |
{ struct request *req; |
f4507164e nbd: rename the n... |
439 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1da177e4c Linux-2.6.12-rc2 |
440 |
|
4b2f0260c [PATCH] nbd: fix ... |
441 |
/* |
f4507164e nbd: rename the n... |
442 |
* Because we have set nbd->sock to NULL under the tx_lock, all |
4b2f0260c [PATCH] nbd: fix ... |
443 444 445 446 447 448 |
* modifications to the list must have completed by now. For * the same reason, the active_req must be NULL. * * As a consequence, we don't need to take the spin lock while * purging the list here. */ |
f4507164e nbd: rename the n... |
449 450 |
BUG_ON(nbd->sock); BUG_ON(nbd->active_req); |
4b2f0260c [PATCH] nbd: fix ... |
451 |
|
f4507164e nbd: rename the n... |
452 453 |
while (!list_empty(&nbd->queue_head)) { req = list_entry(nbd->queue_head.next, struct request, |
4b2f0260c [PATCH] nbd: fix ... |
454 455 456 457 458 |
queuelist); list_del_init(&req->queuelist); req->errors++; nbd_end_request(req); } |
fded4e090 nbd: clear waitin... |
459 460 461 462 463 464 465 466 |
while (!list_empty(&nbd->waiting_queue)) { req = list_entry(nbd->waiting_queue.next, struct request, queuelist); list_del_init(&req->queuelist); req->errors++; nbd_end_request(req); } |
1da177e4c Linux-2.6.12-rc2 |
467 |
} |
7fdfd4065 NBD: allow hung n... |
468 |
|
f4507164e nbd: rename the n... |
469 |
static void nbd_handle_req(struct nbd_device *nbd, struct request *req) |
48cf6061b NBD: allow nbd to... |
470 |
{ |
33659ebba block: remove wra... |
471 |
if (req->cmd_type != REQ_TYPE_FS) |
48cf6061b NBD: allow nbd to... |
472 473 474 475 |
goto error_out; nbd_cmd(req) = NBD_CMD_READ; if (rq_data_dir(req) == WRITE) { |
a336d2987 nbd: handle disca... |
476 477 478 479 480 |
if ((req->cmd_flags & REQ_DISCARD)) { WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM)); nbd_cmd(req) = NBD_CMD_TRIM; } else nbd_cmd(req) = NBD_CMD_WRITE; |
2f0125088 nbd: add set flag... |
481 |
if (nbd->flags & NBD_FLAG_READ_ONLY) { |
f4507164e nbd: rename the n... |
482 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
483 484 |
"Write on read-only "); |
48cf6061b NBD: allow nbd to... |
485 486 487 |
goto error_out; } } |
75f187aba nbd: support FLUS... |
488 489 490 491 |
if (req->cmd_flags & REQ_FLUSH) { BUG_ON(unlikely(blk_rq_sectors(req))); nbd_cmd(req) = NBD_CMD_FLUSH; } |
48cf6061b NBD: allow nbd to... |
492 |
req->errors = 0; |
f4507164e nbd: rename the n... |
493 494 495 496 |
mutex_lock(&nbd->tx_lock); if (unlikely(!nbd->sock)) { mutex_unlock(&nbd->tx_lock); dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
497 498 |
"Attempted send on closed socket "); |
15746fcaa nbd: trivial clea... |
499 |
goto error_out; |
48cf6061b NBD: allow nbd to... |
500 |
} |
f4507164e nbd: rename the n... |
501 |
nbd->active_req = req; |
48cf6061b NBD: allow nbd to... |
502 |
|
f4507164e nbd: rename the n... |
503 504 505 |
if (nbd_send_req(nbd, req) != 0) { dev_err(disk_to_dev(nbd->disk), "Request send failed "); |
48cf6061b NBD: allow nbd to... |
506 507 508 |
req->errors++; nbd_end_request(req); } else { |
f4507164e nbd: rename the n... |
509 |
spin_lock(&nbd->queue_lock); |
01ff5dbc0 block/nbd: micro-... |
510 |
list_add_tail(&req->queuelist, &nbd->queue_head); |
f4507164e nbd: rename the n... |
511 |
spin_unlock(&nbd->queue_lock); |
48cf6061b NBD: allow nbd to... |
512 |
} |
f4507164e nbd: rename the n... |
513 514 515 |
nbd->active_req = NULL; mutex_unlock(&nbd->tx_lock); wake_up_all(&nbd->active_wq); |
48cf6061b NBD: allow nbd to... |
516 517 518 519 520 521 522 523 524 525 |
return; error_out: req->errors++; nbd_end_request(req); } static int nbd_thread(void *data) { |
f4507164e nbd: rename the n... |
526 |
struct nbd_device *nbd = data; |
48cf6061b NBD: allow nbd to... |
527 528 529 |
struct request *req; set_user_nice(current, -20); |
f4507164e nbd: rename the n... |
530 |
while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) { |
48cf6061b NBD: allow nbd to... |
531 |
/* wait for something to do */ |
f4507164e nbd: rename the n... |
532 |
wait_event_interruptible(nbd->waiting_wq, |
48cf6061b NBD: allow nbd to... |
533 |
kthread_should_stop() || |
f4507164e nbd: rename the n... |
534 |
!list_empty(&nbd->waiting_queue)); |
48cf6061b NBD: allow nbd to... |
535 536 |
/* extract request */ |
f4507164e nbd: rename the n... |
537 |
if (list_empty(&nbd->waiting_queue)) |
48cf6061b NBD: allow nbd to... |
538 |
continue; |
f4507164e nbd: rename the n... |
539 540 |
spin_lock_irq(&nbd->queue_lock); req = list_entry(nbd->waiting_queue.next, struct request, |
48cf6061b NBD: allow nbd to... |
541 542 |
queuelist); list_del_init(&req->queuelist); |
f4507164e nbd: rename the n... |
543 |
spin_unlock_irq(&nbd->queue_lock); |
48cf6061b NBD: allow nbd to... |
544 545 |
/* handle request */ |
f4507164e nbd: rename the n... |
546 |
nbd_handle_req(nbd, req); |
48cf6061b NBD: allow nbd to... |
547 548 549 |
} return 0; } |
1da177e4c Linux-2.6.12-rc2 |
550 551 552 |
/* * We always wait for result of write, for now. It would be nice to make it optional * in future |
f4507164e nbd: rename the n... |
553 |
* if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK)) |
1da177e4c Linux-2.6.12-rc2 |
554 555 556 |
* { printk( "Warning: Ignoring result! "); nbd_end_request( req ); } */ |
15746fcaa nbd: trivial clea... |
557 |
static void do_nbd_request(struct request_queue *q) |
398eb0855 nbd: fix sparse w... |
558 |
__releases(q->queue_lock) __acquires(q->queue_lock) |
1da177e4c Linux-2.6.12-rc2 |
559 560 561 |
{ struct request *req; |
9934c8c04 block: implement ... |
562 |
while ((req = blk_fetch_request(q)) != NULL) { |
f4507164e nbd: rename the n... |
563 |
struct nbd_device *nbd; |
1da177e4c Linux-2.6.12-rc2 |
564 |
|
48cf6061b NBD: allow nbd to... |
565 |
spin_unlock_irq(q->queue_lock); |
4aff5e233 [PATCH] Split str... |
566 567 568 |
dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x) ", req->rq_disk->disk_name, req, req->cmd_type); |
1da177e4c Linux-2.6.12-rc2 |
569 |
|
f4507164e nbd: rename the n... |
570 |
nbd = req->rq_disk->private_data; |
1da177e4c Linux-2.6.12-rc2 |
571 |
|
f4507164e nbd: rename the n... |
572 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1da177e4c Linux-2.6.12-rc2 |
573 |
|
f4507164e nbd: rename the n... |
574 575 |
if (unlikely(!nbd->sock)) { dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
576 577 |
"Attempted send on closed socket "); |
4d48a542b nbd: fix I/O hang... |
578 579 580 581 582 |
req->errors++; nbd_end_request(req); spin_lock_irq(q->queue_lock); continue; } |
f4507164e nbd: rename the n... |
583 584 585 |
spin_lock_irq(&nbd->queue_lock); list_add_tail(&req->queuelist, &nbd->waiting_queue); spin_unlock_irq(&nbd->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
586 |
|
f4507164e nbd: rename the n... |
587 |
wake_up(&nbd->waiting_wq); |
4b2f0260c [PATCH] nbd: fix ... |
588 |
|
1da177e4c Linux-2.6.12-rc2 |
589 |
spin_lock_irq(q->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
590 |
} |
1da177e4c Linux-2.6.12-rc2 |
591 |
} |
1a2ad2112 nbd: add locking ... |
592 |
/* Must be called with tx_lock held */ |
1da177e4c Linux-2.6.12-rc2 |
593 |
|
f4507164e nbd: rename the n... |
594 |
static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, |
1a2ad2112 nbd: add locking ... |
595 596 |
unsigned int cmd, unsigned long arg) { |
1da177e4c Linux-2.6.12-rc2 |
597 |
switch (cmd) { |
1a2ad2112 nbd: add locking ... |
598 599 |
case NBD_DISCONNECT: { struct request sreq; |
f4507164e nbd: rename the n... |
600 601 |
dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT "); |
3a2d63f87 nbd: fsync and ki... |
602 603 |
if (!nbd->sock) return -EINVAL; |
1a2ad2112 nbd: add locking ... |
604 |
|
3a2d63f87 nbd: fsync and ki... |
605 606 607 |
mutex_unlock(&nbd->tx_lock); fsync_bdev(bdev); mutex_lock(&nbd->tx_lock); |
4f54eec83 block: use blk_rq... |
608 |
blk_rq_init(NULL, &sreq); |
4aff5e233 [PATCH] Split str... |
609 |
sreq.cmd_type = REQ_TYPE_SPECIAL; |
1da177e4c Linux-2.6.12-rc2 |
610 |
nbd_cmd(&sreq) = NBD_CMD_DISC; |
3a2d63f87 nbd: fsync and ki... |
611 612 |
/* Check again after getting mutex back. */ |
f4507164e nbd: rename the n... |
613 |
if (!nbd->sock) |
1da177e4c Linux-2.6.12-rc2 |
614 |
return -EINVAL; |
3a2d63f87 nbd: fsync and ki... |
615 |
|
c378f70ad nbd: correct disc... |
616 |
nbd->disconnect = 1; |
f4507164e nbd: rename the n... |
617 |
nbd_send_req(nbd, &sreq); |
c378f70ad nbd: correct disc... |
618 |
return 0; |
1a2ad2112 nbd: add locking ... |
619 |
} |
1da177e4c Linux-2.6.12-rc2 |
620 |
|
1a2ad2112 nbd: add locking ... |
621 622 |
case NBD_CLEAR_SOCK: { struct file *file; |
f4507164e nbd: rename the n... |
623 624 625 626 627 |
nbd->sock = NULL; file = nbd->file; nbd->file = NULL; nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); |
fded4e090 nbd: clear waitin... |
628 |
BUG_ON(!list_empty(&nbd->waiting_queue)); |
3a2d63f87 nbd: fsync and ki... |
629 |
kill_bdev(bdev); |
1da177e4c Linux-2.6.12-rc2 |
630 631 |
if (file) fput(file); |
1a2ad2112 nbd: add locking ... |
632 633 634 635 636 |
return 0; } case NBD_SET_SOCK: { struct file *file; |
f4507164e nbd: rename the n... |
637 |
if (nbd->file) |
1da177e4c Linux-2.6.12-rc2 |
638 |
return -EBUSY; |
1da177e4c Linux-2.6.12-rc2 |
639 640 |
file = fget(arg); if (file) { |
496ad9aa8 new helper: file_... |
641 |
struct inode *inode = file_inode(file); |
1da177e4c Linux-2.6.12-rc2 |
642 |
if (S_ISSOCK(inode->i_mode)) { |
f4507164e nbd: rename the n... |
643 644 |
nbd->file = file; nbd->sock = SOCKET_I(inode); |
d71a6d733 NBD: add partitio... |
645 646 |
if (max_part > 0) bdev->bd_invalidated = 1; |
c378f70ad nbd: correct disc... |
647 |
nbd->disconnect = 0; /* we're connected now */ |
1a2ad2112 nbd: add locking ... |
648 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
649 650 651 652 |
} else { fput(file); } } |
1a2ad2112 nbd: add locking ... |
653 654 |
return -EINVAL; } |
1da177e4c Linux-2.6.12-rc2 |
655 |
case NBD_SET_BLKSIZE: |
f4507164e nbd: rename the n... |
656 657 658 659 660 |
nbd->blksize = arg; nbd->bytesize &= ~(nbd->blksize-1); bdev->bd_inode->i_size = nbd->bytesize; set_blocksize(bdev, nbd->blksize); set_capacity(nbd->disk, nbd->bytesize >> 9); |
1da177e4c Linux-2.6.12-rc2 |
661 |
return 0; |
1a2ad2112 nbd: add locking ... |
662 |
|
1da177e4c Linux-2.6.12-rc2 |
663 |
case NBD_SET_SIZE: |
f4507164e nbd: rename the n... |
664 665 666 667 |
nbd->bytesize = arg & ~(nbd->blksize-1); bdev->bd_inode->i_size = nbd->bytesize; set_blocksize(bdev, nbd->blksize); set_capacity(nbd->disk, nbd->bytesize >> 9); |
1da177e4c Linux-2.6.12-rc2 |
668 |
return 0; |
1a2ad2112 nbd: add locking ... |
669 |
|
7fdfd4065 NBD: allow hung n... |
670 |
case NBD_SET_TIMEOUT: |
f4507164e nbd: rename the n... |
671 |
nbd->xmit_timeout = arg * HZ; |
7fdfd4065 NBD: allow hung n... |
672 |
return 0; |
1a2ad2112 nbd: add locking ... |
673 |
|
2f0125088 nbd: add set flag... |
674 675 676 |
case NBD_SET_FLAGS: nbd->flags = arg; return 0; |
1da177e4c Linux-2.6.12-rc2 |
677 |
case NBD_SET_SIZE_BLOCKS: |
f4507164e nbd: rename the n... |
678 679 680 681 |
nbd->bytesize = ((u64) arg) * nbd->blksize; bdev->bd_inode->i_size = nbd->bytesize; set_blocksize(bdev, nbd->blksize); set_capacity(nbd->disk, nbd->bytesize >> 9); |
1da177e4c Linux-2.6.12-rc2 |
682 |
return 0; |
1a2ad2112 nbd: add locking ... |
683 684 685 686 687 |
case NBD_DO_IT: { struct task_struct *thread; struct file *file; int error; |
f4507164e nbd: rename the n... |
688 |
if (nbd->pid) |
c91192d66 nbd: do not allow... |
689 |
return -EBUSY; |
f4507164e nbd: rename the n... |
690 |
if (!nbd->file) |
1da177e4c Linux-2.6.12-rc2 |
691 |
return -EINVAL; |
1a2ad2112 nbd: add locking ... |
692 |
|
f4507164e nbd: rename the n... |
693 |
mutex_unlock(&nbd->tx_lock); |
1a2ad2112 nbd: add locking ... |
694 |
|
a83e814b5 nbd: show read-on... |
695 696 |
if (nbd->flags & NBD_FLAG_READ_ONLY) set_device_ro(bdev, true); |
a336d2987 nbd: handle disca... |
697 698 699 |
if (nbd->flags & NBD_FLAG_SEND_TRIM) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); |
75f187aba nbd: support FLUS... |
700 701 702 703 |
if (nbd->flags & NBD_FLAG_SEND_FLUSH) blk_queue_flush(nbd->disk->queue, REQ_FLUSH); else blk_queue_flush(nbd->disk->queue, 0); |
a336d2987 nbd: handle disca... |
704 |
|
ffc8b3086 block: do not pas... |
705 706 |
thread = kthread_create(nbd_thread, nbd, "%s", nbd->disk->disk_name); |
1a2ad2112 nbd: add locking ... |
707 |
if (IS_ERR(thread)) { |
f4507164e nbd: rename the n... |
708 |
mutex_lock(&nbd->tx_lock); |
48cf6061b NBD: allow nbd to... |
709 |
return PTR_ERR(thread); |
1a2ad2112 nbd: add locking ... |
710 |
} |
48cf6061b NBD: allow nbd to... |
711 |
wake_up_process(thread); |
f4507164e nbd: rename the n... |
712 |
error = nbd_do_it(nbd); |
48cf6061b NBD: allow nbd to... |
713 |
kthread_stop(thread); |
1a2ad2112 nbd: add locking ... |
714 |
|
f4507164e nbd: rename the n... |
715 |
mutex_lock(&nbd->tx_lock); |
84963048c nbd: check the re... |
716 717 |
if (error) return error; |
f4507164e nbd: rename the n... |
718 719 720 721 722 723 |
sock_shutdown(nbd, 0); file = nbd->file; nbd->file = NULL; nbd_clear_que(nbd); dev_warn(disk_to_dev(nbd->disk), "queue cleared "); |
3a2d63f87 nbd: fsync and ki... |
724 |
kill_bdev(bdev); |
a336d2987 nbd: handle disca... |
725 |
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); |
a83e814b5 nbd: show read-on... |
726 |
set_device_ro(bdev, false); |
1da177e4c Linux-2.6.12-rc2 |
727 728 |
if (file) fput(file); |
75f187aba nbd: support FLUS... |
729 |
nbd->flags = 0; |
f4507164e nbd: rename the n... |
730 |
nbd->bytesize = 0; |
a8cdc308c [PATCH] switch nbd |
731 |
bdev->bd_inode->i_size = 0; |
f4507164e nbd: rename the n... |
732 |
set_capacity(nbd->disk, 0); |
d71a6d733 NBD: add partitio... |
733 |
if (max_part > 0) |
a8cdc308c [PATCH] switch nbd |
734 |
ioctl_by_bdev(bdev, BLKRRPART, 0); |
c378f70ad nbd: correct disc... |
735 736 |
if (nbd->disconnect) /* user requested, ignore socket errors */ return 0; |
f4507164e nbd: rename the n... |
737 |
return nbd->harderror; |
1a2ad2112 nbd: add locking ... |
738 |
} |
1da177e4c Linux-2.6.12-rc2 |
739 |
case NBD_CLEAR_QUE: |
4b2f0260c [PATCH] nbd: fix ... |
740 741 742 743 |
/* * This is for compatibility only. The queue is always cleared * by NBD_DO_IT or NBD_CLEAR_SOCK. */ |
1da177e4c Linux-2.6.12-rc2 |
744 |
return 0; |
1a2ad2112 nbd: add locking ... |
745 |
|
1da177e4c Linux-2.6.12-rc2 |
746 |
case NBD_PRINT_DEBUG: |
f4507164e nbd: rename the n... |
747 |
dev_info(disk_to_dev(nbd->disk), |
5eedf5415 nbd: replace some... |
748 749 |
"next = %p, prev = %p, head = %p ", |
f4507164e nbd: rename the n... |
750 751 |
nbd->queue_head.next, nbd->queue_head.prev, &nbd->queue_head); |
1da177e4c Linux-2.6.12-rc2 |
752 753 |
return 0; } |
1a2ad2112 nbd: add locking ... |
754 755 756 757 758 759 |
return -ENOTTY; } static int nbd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { |
f4507164e nbd: rename the n... |
760 |
struct nbd_device *nbd = bdev->bd_disk->private_data; |
1a2ad2112 nbd: add locking ... |
761 762 763 764 |
int error; if (!capable(CAP_SYS_ADMIN)) return -EPERM; |
f4507164e nbd: rename the n... |
765 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1a2ad2112 nbd: add locking ... |
766 767 768 769 |
/* Anyone capable of this syscall can do *real bad* things */ dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu ", |
f4507164e nbd: rename the n... |
770 |
nbd->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); |
1a2ad2112 nbd: add locking ... |
771 |
|
f4507164e nbd: rename the n... |
772 773 774 |
mutex_lock(&nbd->tx_lock); error = __nbd_ioctl(bdev, nbd, cmd, arg); mutex_unlock(&nbd->tx_lock); |
1a2ad2112 nbd: add locking ... |
775 776 |
return error; |
1da177e4c Linux-2.6.12-rc2 |
777 |
} |
83d5cde47 const: make block... |
778 |
static const struct block_device_operations nbd_fops = |
1da177e4c Linux-2.6.12-rc2 |
779 780 |
{ .owner = THIS_MODULE, |
8a6cfeb6d block: push down ... |
781 |
.ioctl = nbd_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
782 783 784 785 786 787 788 789 790 791 792 |
}; /* * And here should be modules and kernel interface * (Just smiley confuses emacs :-) */ static int __init nbd_init(void) { int err = -ENOMEM; int i; |
d71a6d733 NBD: add partitio... |
793 |
int part_shift; |
1da177e4c Linux-2.6.12-rc2 |
794 |
|
5b7b18ccd [PATCH] drivers/b... |
795 |
BUILD_BUG_ON(sizeof(struct nbd_request) != 28); |
1da177e4c Linux-2.6.12-rc2 |
796 |
|
d71a6d733 NBD: add partitio... |
797 |
if (max_part < 0) { |
7742ce4ab nbd: lower the lo... |
798 799 |
printk(KERN_ERR "nbd: max_part must be >= 0 "); |
d71a6d733 NBD: add partitio... |
800 801 |
return -EINVAL; } |
f3944d61d nbd: fix memory l... |
802 803 804 |
nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); if (!nbd_dev) return -ENOMEM; |
d71a6d733 NBD: add partitio... |
805 |
part_shift = 0; |
5988ce239 nbd: adjust 'max_... |
806 |
if (max_part > 0) { |
d71a6d733 NBD: add partitio... |
807 |
part_shift = fls(max_part); |
5988ce239 nbd: adjust 'max_... |
808 809 810 811 812 813 814 815 816 817 |
/* * Adjust max_part according to part_shift as it is exported * to user space so that user can know the max number of * partition kernel should be able to manage. * * Note that -1 is required because partition 0 is reserved * for the whole disk. */ max_part = (1UL << part_shift) - 1; } |
3b2710824 nbd: limit module... |
818 819 820 821 822 |
if ((1UL << part_shift) > DISK_MAX_PARTS) return -EINVAL; if (nbds_max > 1UL << (MINORBITS - part_shift)) return -EINVAL; |
40be0c28b [PATCH] nbd: Don'... |
823 |
for (i = 0; i < nbds_max; i++) { |
d71a6d733 NBD: add partitio... |
824 |
struct gendisk *disk = alloc_disk(1 << part_shift); |
1da177e4c Linux-2.6.12-rc2 |
825 826 827 828 829 830 831 832 833 834 835 836 837 |
if (!disk) goto out; nbd_dev[i].disk = disk; /* * The new linux 2.5 block layer implementation requires * every gendisk to have its very own request_queue struct. * These structs are big so we dynamically allocate them. */ disk->queue = blk_init_queue(do_nbd_request, &nbd_lock); if (!disk->queue) { put_disk(disk); goto out; } |
31dcfab0a nbd: tell the blo... |
838 839 840 841 |
/* * Tell the block layer that we are not a rotational device */ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue); |
a336d2987 nbd: handle disca... |
842 843 844 |
disk->queue->limits.discard_granularity = 512; disk->queue->limits.max_discard_sectors = UINT_MAX; disk->queue->limits.discard_zeroes_data = 0; |
078be02b8 nbd: increase def... |
845 846 |
blk_queue_max_hw_sectors(disk->queue, 65536); disk->queue->limits.max_sectors = 256; |
1da177e4c Linux-2.6.12-rc2 |
847 848 849 850 851 852 853 854 855 856 857 |
} if (register_blkdev(NBD_MAJOR, "nbd")) { err = -EIO; goto out; } printk(KERN_INFO "nbd: registered device at major %d ", NBD_MAJOR); dprintk(DBG_INIT, "nbd: debugflags=0x%x ", debugflags); |
40be0c28b [PATCH] nbd: Don'... |
858 |
for (i = 0; i < nbds_max; i++) { |
1da177e4c Linux-2.6.12-rc2 |
859 860 |
struct gendisk *disk = nbd_dev[i].disk; nbd_dev[i].file = NULL; |
f4507164e nbd: rename the n... |
861 |
nbd_dev[i].magic = NBD_MAGIC; |
1da177e4c Linux-2.6.12-rc2 |
862 |
nbd_dev[i].flags = 0; |
48cf6061b NBD: allow nbd to... |
863 |
INIT_LIST_HEAD(&nbd_dev[i].waiting_queue); |
1da177e4c Linux-2.6.12-rc2 |
864 865 |
spin_lock_init(&nbd_dev[i].queue_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); |
82d4dc5ad [PATCH] sem2mutex... |
866 |
mutex_init(&nbd_dev[i].tx_lock); |
4b2f0260c [PATCH] nbd: fix ... |
867 |
init_waitqueue_head(&nbd_dev[i].active_wq); |
48cf6061b NBD: allow nbd to... |
868 |
init_waitqueue_head(&nbd_dev[i].waiting_wq); |
1da177e4c Linux-2.6.12-rc2 |
869 |
nbd_dev[i].blksize = 1024; |
4b86a8725 NBD: set uninitia... |
870 |
nbd_dev[i].bytesize = 0; |
1da177e4c Linux-2.6.12-rc2 |
871 |
disk->major = NBD_MAJOR; |
d71a6d733 NBD: add partitio... |
872 |
disk->first_minor = i << part_shift; |
1da177e4c Linux-2.6.12-rc2 |
873 874 |
disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; |
1da177e4c Linux-2.6.12-rc2 |
875 |
sprintf(disk->disk_name, "nbd%d", i); |
4b86a8725 NBD: set uninitia... |
876 |
set_capacity(disk, 0); |
1da177e4c Linux-2.6.12-rc2 |
877 878 879 880 881 882 883 884 885 |
add_disk(disk); } return 0; out: while (i--) { blk_cleanup_queue(nbd_dev[i].disk->queue); put_disk(nbd_dev[i].disk); } |
f3944d61d nbd: fix memory l... |
886 |
kfree(nbd_dev); |
1da177e4c Linux-2.6.12-rc2 |
887 888 889 890 891 892 |
return err; } static void __exit nbd_cleanup(void) { int i; |
40be0c28b [PATCH] nbd: Don'... |
893 |
for (i = 0; i < nbds_max; i++) { |
1da177e4c Linux-2.6.12-rc2 |
894 |
struct gendisk *disk = nbd_dev[i].disk; |
40be0c28b [PATCH] nbd: Don'... |
895 |
nbd_dev[i].magic = 0; |
1da177e4c Linux-2.6.12-rc2 |
896 897 898 899 900 901 |
if (disk) { del_gendisk(disk); blk_cleanup_queue(disk->queue); put_disk(disk); } } |
1da177e4c Linux-2.6.12-rc2 |
902 |
unregister_blkdev(NBD_MAJOR, "nbd"); |
f3944d61d nbd: fix memory l... |
903 |
kfree(nbd_dev); |
1da177e4c Linux-2.6.12-rc2 |
904 905 906 907 908 909 910 911 912 |
printk(KERN_INFO "nbd: unregistered device at major %d ", NBD_MAJOR); } module_init(nbd_init); module_exit(nbd_cleanup); MODULE_DESCRIPTION("Network Block Device"); MODULE_LICENSE("GPL"); |
40be0c28b [PATCH] nbd: Don'... |
913 |
module_param(nbds_max, int, 0444); |
d71a6d733 NBD: add partitio... |
914 915 916 |
MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)"); module_param(max_part, int, 0444); MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)"); |
1da177e4c Linux-2.6.12-rc2 |
917 918 919 920 |
#ifndef NDEBUG module_param(debugflags, int, 0644); MODULE_PARM_DESC(debugflags, "flags for controlling debug output"); #endif |