Blame view
drivers/block/nbd.c
25.6 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> |
b9c495bb6 nbd: Fix device b... |
35 |
#include <linux/types.h> |
30d53d9c1 nbd: Add debugfs ... |
36 |
#include <linux/debugfs.h> |
1da177e4c Linux-2.6.12-rc2 |
37 |
|
1da177e4c Linux-2.6.12-rc2 |
38 39 40 41 |
#include <asm/uaccess.h> #include <asm/types.h> #include <linux/nbd.h> |
13e71d69c nbd: Remove kerne... |
42 |
struct nbd_device { |
22d109c1b nbd: flags is a u... |
43 |
u32 flags; |
13e71d69c nbd: Remove kerne... |
44 45 46 47 48 49 50 51 52 53 54 55 56 |
struct socket * sock; /* If == NULL, device is not ready, yet */ int magic; spinlock_t queue_lock; struct list_head queue_head; /* Requests waiting result */ struct request *active_req; wait_queue_head_t active_wq; struct list_head waiting_queue; /* Requests to be sent */ wait_queue_head_t waiting_wq; struct mutex tx_lock; struct gendisk *disk; int blksize; |
b9c495bb6 nbd: Fix device b... |
57 |
loff_t bytesize; |
13e71d69c nbd: Remove kerne... |
58 |
int xmit_timeout; |
1f7b5cf1b nbd: Timeouts are... |
59 |
bool timedout; |
696697cb5 nbd: Change 'disc... |
60 |
bool disconnect; /* a disconnect has been requested by user */ |
7e2893a16 nbd: Fix timeout ... |
61 62 |
struct timer_list timeout_timer; |
23272a675 nbd: Remove signa... |
63 64 |
/* protects initialization and shutdown of the socket */ spinlock_t sock_lock; |
7e2893a16 nbd: Fix timeout ... |
65 66 |
struct task_struct *task_recv; struct task_struct *task_send; |
30d53d9c1 nbd: Add debugfs ... |
67 68 69 70 |
#if IS_ENABLED(CONFIG_DEBUG_FS) struct dentry *dbg_dir; #endif |
13e71d69c nbd: Remove kerne... |
71 |
}; |
30d53d9c1 nbd: Add debugfs ... |
72 73 74 75 76 |
#if IS_ENABLED(CONFIG_DEBUG_FS) static struct dentry *nbd_dbg_dir; #endif #define nbd_name(nbd) ((nbd)->disk->disk_name) |
f4507164e nbd: rename the n... |
77 |
#define NBD_MAGIC 0x68797548 |
1da177e4c Linux-2.6.12-rc2 |
78 |
|
9c7a41691 [PATCH] drivers/b... |
79 |
static unsigned int nbds_max = 16; |
20a8143ea NBD: remove limit... |
80 |
static struct nbd_device *nbd_dev; |
d71a6d733 NBD: add partitio... |
81 |
static int max_part; |
1da177e4c Linux-2.6.12-rc2 |
82 83 84 85 86 87 88 89 90 91 92 93 |
/* * 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); |
d18509f59 nbd: Restructure ... |
94 |
static inline struct device *nbd_to_dev(struct nbd_device *nbd) |
1da177e4c Linux-2.6.12-rc2 |
95 |
{ |
d18509f59 nbd: Restructure ... |
96 |
return disk_to_dev(nbd->disk); |
1da177e4c Linux-2.6.12-rc2 |
97 |
} |
37091fdd8 nbd: Create size ... |
98 99 100 101 |
static bool nbd_is_connected(struct nbd_device *nbd) { return !!nbd->task_recv; } |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 105 106 107 |
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... |
108 |
case NBD_CMD_FLUSH: return "flush"; |
a336d2987 nbd: handle disca... |
109 |
case NBD_CMD_TRIM: return "trim/discard"; |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 |
} return "invalid"; } |
1da177e4c Linux-2.6.12-rc2 |
113 |
|
37091fdd8 nbd: Create size ... |
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev) { bdev->bd_inode->i_size = 0; set_capacity(nbd->disk, 0); kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); return 0; } static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev) { if (!nbd_is_connected(nbd)) return; bdev->bd_inode->i_size = nbd->bytesize; set_capacity(nbd->disk, nbd->bytesize >> 9); kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); } static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev, int blocksize, int nr_blocks) { int ret; ret = set_blocksize(bdev, blocksize); if (ret) return ret; nbd->blksize = blocksize; nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks; nbd_size_update(nbd, bdev); return 0; } |
d18509f59 nbd: Restructure ... |
149 |
static void nbd_end_request(struct nbd_device *nbd, struct request *req) |
1da177e4c Linux-2.6.12-rc2 |
150 |
{ |
097c94a4e blk_end_request: ... |
151 |
int error = req->errors ? -EIO : 0; |
165125e1e [BLOCK] Get rid o... |
152 |
struct request_queue *q = req->q; |
1da177e4c Linux-2.6.12-rc2 |
153 |
unsigned long flags; |
d18509f59 nbd: Restructure ... |
154 155 156 |
dev_dbg(nbd_to_dev(nbd), "request %p: %s ", req, error ? "failed" : "done"); |
1da177e4c Linux-2.6.12-rc2 |
157 158 |
spin_lock_irqsave(q->queue_lock, flags); |
1011c1b9f block: blk_rq_[cu... |
159 |
__blk_end_request_all(req, error); |
1da177e4c Linux-2.6.12-rc2 |
160 161 |
spin_unlock_irqrestore(q->queue_lock, flags); } |
e018e7570 nbd: Remove fixme... |
162 163 164 |
/* * Forcibly shutdown the socket causing all listeners to error */ |
36e47bee7 nbd: sock_shutdow... |
165 |
static void sock_shutdown(struct nbd_device *nbd) |
7fdfd4065 NBD: allow hung n... |
166 |
{ |
23272a675 nbd: Remove signa... |
167 168 169 170 |
spin_lock_irq(&nbd->sock_lock); if (!nbd->sock) { spin_unlock_irq(&nbd->sock_lock); |
260bbce40 nbd: restructure ... |
171 |
return; |
23272a675 nbd: Remove signa... |
172 |
} |
260bbce40 nbd: restructure ... |
173 174 175 176 |
dev_warn(disk_to_dev(nbd->disk), "shutting down socket "); kernel_sock_shutdown(nbd->sock, SHUT_RDWR); |
23272a675 nbd: Remove signa... |
177 |
sockfd_put(nbd->sock); |
260bbce40 nbd: restructure ... |
178 |
nbd->sock = NULL; |
23272a675 nbd: Remove signa... |
179 180 181 |
spin_unlock_irq(&nbd->sock_lock); del_timer(&nbd->timeout_timer); |
7fdfd4065 NBD: allow hung n... |
182 183 184 185 |
} static void nbd_xmit_timeout(unsigned long arg) { |
7e2893a16 nbd: Fix timeout ... |
186 |
struct nbd_device *nbd = (struct nbd_device *)arg; |
dcc909d90 nbd: Add locking ... |
187 |
unsigned long flags; |
7e2893a16 nbd: Fix timeout ... |
188 189 190 |
if (list_empty(&nbd->queue_head)) return; |
23272a675 nbd: Remove signa... |
191 |
spin_lock_irqsave(&nbd->sock_lock, flags); |
dcc909d90 nbd: Add locking ... |
192 |
|
1f7b5cf1b nbd: Timeouts are... |
193 |
nbd->timedout = true; |
7fdfd4065 NBD: allow hung n... |
194 |
|
23272a675 nbd: Remove signa... |
195 196 |
if (nbd->sock) kernel_sock_shutdown(nbd->sock, SHUT_RDWR); |
7e2893a16 nbd: Fix timeout ... |
197 |
|
23272a675 nbd: Remove signa... |
198 |
spin_unlock_irqrestore(&nbd->sock_lock, flags); |
dcc909d90 nbd: Add locking ... |
199 |
|
23272a675 nbd: Remove signa... |
200 201 |
dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection "); |
7fdfd4065 NBD: allow hung n... |
202 |
} |
1da177e4c Linux-2.6.12-rc2 |
203 204 205 |
/* * Send or receive packet. */ |
f4507164e nbd: rename the n... |
206 |
static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, |
1da177e4c Linux-2.6.12-rc2 |
207 208 |
int msg_flags) { |
f4507164e nbd: rename the n... |
209 |
struct socket *sock = nbd->sock; |
1da177e4c Linux-2.6.12-rc2 |
210 211 212 |
int result; struct msghdr msg; struct kvec iov; |
7f338fe45 nbd: set SOCK_MEM... |
213 |
unsigned long pflags = current->flags; |
1da177e4c Linux-2.6.12-rc2 |
214 |
|
ffc41cf8d nbd: prevent sock... |
215 |
if (unlikely(!sock)) { |
f4507164e nbd: rename the n... |
216 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
217 218 219 |
"Attempted %s on closed socket in sock_xmit ", (send ? "send" : "recv")); |
ffc41cf8d nbd: prevent sock... |
220 221 |
return -EINVAL; } |
7f338fe45 nbd: set SOCK_MEM... |
222 |
current->flags |= PF_MEMALLOC; |
1da177e4c Linux-2.6.12-rc2 |
223 |
do { |
7f338fe45 nbd: set SOCK_MEM... |
224 |
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 228 229 230 |
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 |
231 |
msg.msg_flags = msg_flags | MSG_NOSIGNAL; |
7e2893a16 nbd: Fix timeout ... |
232 |
if (send) |
1da177e4c Linux-2.6.12-rc2 |
233 |
result = kernel_sendmsg(sock, &msg, &iov, 1, size); |
7e2893a16 nbd: Fix timeout ... |
234 |
else |
35fbf5bcf nbd: pass MSG_* f... |
235 236 |
result = kernel_recvmsg(sock, &msg, &iov, 1, size, msg.msg_flags); |
1da177e4c Linux-2.6.12-rc2 |
237 |
|
1da177e4c Linux-2.6.12-rc2 |
238 239 240 241 242 243 244 245 |
if (result <= 0) { if (result == 0) result = -EPIPE; /* short read */ break; } size -= result; buf += result; } while (size > 0); |
7f338fe45 nbd: set SOCK_MEM... |
246 |
tsk_restore_flags(current, pflags, PF_MEMALLOC); |
1da177e4c Linux-2.6.12-rc2 |
247 |
|
7e2893a16 nbd: Fix timeout ... |
248 249 |
if (!send && nbd->xmit_timeout) mod_timer(&nbd->timeout_timer, jiffies + nbd->xmit_timeout); |
1da177e4c Linux-2.6.12-rc2 |
250 251 |
return result; } |
f4507164e nbd: rename the n... |
252 |
static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec, |
1da177e4c Linux-2.6.12-rc2 |
253 254 255 256 |
int flags) { int result; void *kaddr = kmap(bvec->bv_page); |
f4507164e nbd: rename the n... |
257 258 |
result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags); |
1da177e4c Linux-2.6.12-rc2 |
259 260 261 |
kunmap(bvec->bv_page); return result; } |
7fdfd4065 NBD: allow hung n... |
262 |
/* always call with the tx_lock held */ |
f4507164e nbd: rename the n... |
263 |
static int nbd_send_req(struct nbd_device *nbd, struct request *req) |
1da177e4c Linux-2.6.12-rc2 |
264 |
{ |
5705f7021 Introduce rq_for_... |
265 |
int result, flags; |
1da177e4c Linux-2.6.12-rc2 |
266 |
struct nbd_request request; |
1011c1b9f block: blk_rq_[cu... |
267 |
unsigned long size = blk_rq_bytes(req); |
9dc6c806b nbd: stop using r... |
268 269 270 271 |
u32 type; if (req->cmd_type == REQ_TYPE_DRV_PRIV) type = NBD_CMD_DISC; |
c2df40dfb drivers: use req ... |
272 |
else if (req_op(req) == REQ_OP_DISCARD) |
9dc6c806b nbd: stop using r... |
273 |
type = NBD_CMD_TRIM; |
3a5e02ced block, drivers: a... |
274 |
else if (req_op(req) == REQ_OP_FLUSH) |
9dc6c806b nbd: stop using r... |
275 276 277 278 279 |
type = NBD_CMD_FLUSH; else if (rq_data_dir(req) == WRITE) type = NBD_CMD_WRITE; else type = NBD_CMD_READ; |
1da177e4c Linux-2.6.12-rc2 |
280 |
|
04cfac4e4 nbd: zero from an... |
281 |
memset(&request, 0, sizeof(request)); |
1da177e4c Linux-2.6.12-rc2 |
282 |
request.magic = htonl(NBD_REQUEST_MAGIC); |
9dc6c806b nbd: stop using r... |
283 284 |
request.type = htonl(type); if (type != NBD_CMD_FLUSH && type != NBD_CMD_DISC) { |
75f187aba nbd: support FLUS... |
285 286 287 |
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); request.len = htonl(size); } |
1da177e4c Linux-2.6.12-rc2 |
288 |
memcpy(request.handle, &req, sizeof(req)); |
d18509f59 nbd: Restructure ... |
289 290 |
dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB) ", |
9dc6c806b nbd: stop using r... |
291 |
req, nbdcmd_to_ascii(type), |
d18509f59 nbd: Restructure ... |
292 |
(unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req)); |
f4507164e nbd: rename the n... |
293 |
result = sock_xmit(nbd, 1, &request, sizeof(request), |
9dc6c806b nbd: stop using r... |
294 |
(type == NBD_CMD_WRITE) ? MSG_MORE : 0); |
1da177e4c Linux-2.6.12-rc2 |
295 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
296 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
297 298 |
"Send control failed (result %d) ", result); |
dab5313aa nbd: Return error... |
299 |
return -EIO; |
1da177e4c Linux-2.6.12-rc2 |
300 |
} |
9dc6c806b nbd: stop using r... |
301 |
if (type == NBD_CMD_WRITE) { |
5705f7021 Introduce rq_for_... |
302 |
struct req_iterator iter; |
7988613b0 block: Convert bi... |
303 |
struct bio_vec bvec; |
1da177e4c Linux-2.6.12-rc2 |
304 305 306 307 |
/* * we are really probing at internals to determine * whether to set MSG_MORE or not... */ |
5705f7021 Introduce rq_for_... |
308 |
rq_for_each_segment(bvec, req, iter) { |
6c92e699b Fixup rq_for_each... |
309 |
flags = 0; |
4550dd6c6 block: Immutable ... |
310 |
if (!rq_iter_last(bvec, iter)) |
6c92e699b Fixup rq_for_each... |
311 |
flags = MSG_MORE; |
d18509f59 nbd: Restructure ... |
312 313 314 |
dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data ", req, bvec.bv_len); |
7988613b0 block: Convert bi... |
315 |
result = sock_send_bvec(nbd, &bvec, flags); |
6c92e699b Fixup rq_for_each... |
316 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
317 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
318 319 320 |
"Send data failed (result %d) ", result); |
dab5313aa nbd: Return error... |
321 |
return -EIO; |
6c92e699b Fixup rq_for_each... |
322 |
} |
1da177e4c Linux-2.6.12-rc2 |
323 324 |
} } |
1da177e4c Linux-2.6.12-rc2 |
325 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
326 |
} |
f4507164e nbd: rename the n... |
327 |
static struct request *nbd_find_request(struct nbd_device *nbd, |
0cbc591bf nbd: change a par... |
328 |
struct request *xreq) |
1da177e4c Linux-2.6.12-rc2 |
329 |
{ |
d2c9740b4 nbd: use list_for... |
330 |
struct request *req, *tmp; |
4b2f0260c [PATCH] nbd: fix ... |
331 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
332 |
|
f4507164e nbd: rename the n... |
333 |
err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq); |
4b2f0260c [PATCH] nbd: fix ... |
334 |
if (unlikely(err)) |
de9ad6d4e nbd: Return error... |
335 |
return ERR_PTR(err); |
4b2f0260c [PATCH] nbd: fix ... |
336 |
|
f4507164e nbd: rename the n... |
337 338 |
spin_lock(&nbd->queue_lock); list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) { |
1da177e4c Linux-2.6.12-rc2 |
339 340 341 |
if (req != xreq) continue; list_del_init(&req->queuelist); |
f4507164e nbd: rename the n... |
342 |
spin_unlock(&nbd->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
343 344 |
return req; } |
f4507164e nbd: rename the n... |
345 |
spin_unlock(&nbd->queue_lock); |
4b2f0260c [PATCH] nbd: fix ... |
346 |
|
de9ad6d4e nbd: Return error... |
347 |
return ERR_PTR(-ENOENT); |
1da177e4c Linux-2.6.12-rc2 |
348 |
} |
f4507164e nbd: rename the n... |
349 |
static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec) |
1da177e4c Linux-2.6.12-rc2 |
350 351 352 |
{ int result; void *kaddr = kmap(bvec->bv_page); |
f4507164e nbd: rename the n... |
353 |
result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len, |
1da177e4c Linux-2.6.12-rc2 |
354 355 356 357 358 359 |
MSG_WAITALL); kunmap(bvec->bv_page); return result; } /* NULL returned = something went wrong, inform userspace */ |
f4507164e nbd: rename the n... |
360 |
static struct request *nbd_read_stat(struct nbd_device *nbd) |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 364 |
{ int result; struct nbd_reply reply; struct request *req; |
1da177e4c Linux-2.6.12-rc2 |
365 366 |
reply.magic = 0; |
f4507164e nbd: rename the n... |
367 |
result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL); |
1da177e4c Linux-2.6.12-rc2 |
368 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
369 |
dev_err(disk_to_dev(nbd->disk), |
7f1b90f99 nbd: replace prin... |
370 371 |
"Receive control failed (result %d) ", result); |
193918307 nbd: Remove 'hard... |
372 |
return ERR_PTR(result); |
1da177e4c Linux-2.6.12-rc2 |
373 |
} |
e4b57e084 [PATCH] nbd: Chec... |
374 375 |
if (ntohl(reply.magic) != NBD_REPLY_MAGIC) { |
f4507164e nbd: rename the n... |
376 377 |
dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx) ", |
e4b57e084 [PATCH] nbd: Chec... |
378 |
(unsigned long)ntohl(reply.magic)); |
193918307 nbd: Remove 'hard... |
379 |
return ERR_PTR(-EPROTO); |
e4b57e084 [PATCH] nbd: Chec... |
380 |
} |
f4507164e nbd: rename the n... |
381 |
req = nbd_find_request(nbd, *(struct request **)reply.handle); |
801678c5a Remove duplicated... |
382 |
if (IS_ERR(req)) { |
4b2f0260c [PATCH] nbd: fix ... |
383 384 |
result = PTR_ERR(req); if (result != -ENOENT) |
193918307 nbd: Remove 'hard... |
385 |
return ERR_PTR(result); |
4b2f0260c [PATCH] nbd: fix ... |
386 |
|
f4507164e nbd: rename the n... |
387 388 |
dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p) ", |
7f1b90f99 nbd: replace prin... |
389 |
reply.handle); |
193918307 nbd: Remove 'hard... |
390 |
return ERR_PTR(-EBADR); |
1da177e4c Linux-2.6.12-rc2 |
391 |
} |
1da177e4c Linux-2.6.12-rc2 |
392 |
if (ntohl(reply.error)) { |
f4507164e nbd: rename the n... |
393 394 |
dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d) ", |
7f1b90f99 nbd: replace prin... |
395 |
ntohl(reply.error)); |
1da177e4c Linux-2.6.12-rc2 |
396 397 398 |
req->errors++; return req; } |
d18509f59 nbd: Restructure ... |
399 400 |
dev_dbg(nbd_to_dev(nbd), "request %p: got reply ", req); |
9dc6c806b nbd: stop using r... |
401 |
if (rq_data_dir(req) != WRITE) { |
5705f7021 Introduce rq_for_... |
402 |
struct req_iterator iter; |
7988613b0 block: Convert bi... |
403 |
struct bio_vec bvec; |
5705f7021 Introduce rq_for_... |
404 405 |
rq_for_each_segment(bvec, req, iter) { |
7988613b0 block: Convert bi... |
406 |
result = sock_recv_bvec(nbd, &bvec); |
6c92e699b Fixup rq_for_each... |
407 |
if (result <= 0) { |
f4507164e nbd: rename the n... |
408 409 |
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d) ", |
7f1b90f99 nbd: replace prin... |
410 |
result); |
6c92e699b Fixup rq_for_each... |
411 412 413 |
req->errors++; return req; } |
d18509f59 nbd: Restructure ... |
414 415 416 |
dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data ", req, bvec.bv_len); |
1da177e4c Linux-2.6.12-rc2 |
417 418 419 |
} } return req; |
1da177e4c Linux-2.6.12-rc2 |
420 |
} |
edfaa7c36 Driver core: conv... |
421 422 |
static ssize_t pid_show(struct device *dev, struct device_attribute *attr, char *buf) |
6b39bb654 [PATCH] nbd: show... |
423 |
{ |
edfaa7c36 Driver core: conv... |
424 |
struct gendisk *disk = dev_to_disk(dev); |
6521d39a6 nbd: Remove varia... |
425 |
struct nbd_device *nbd = (struct nbd_device *)disk->private_data; |
edfaa7c36 Driver core: conv... |
426 |
|
6521d39a6 nbd: Remove varia... |
427 428 |
return sprintf(buf, "%d ", task_pid_nr(nbd->task_recv)); |
6b39bb654 [PATCH] nbd: show... |
429 |
} |
edfaa7c36 Driver core: conv... |
430 |
static struct device_attribute pid_attr = { |
01e8ef11b x86: sysfs: kill ... |
431 |
.attr = { .name = "pid", .mode = S_IRUGO}, |
6b39bb654 [PATCH] nbd: show... |
432 433 |
.show = pid_show, }; |
37091fdd8 nbd: Create size ... |
434 |
static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev) |
1da177e4c Linux-2.6.12-rc2 |
435 436 |
{ struct request *req; |
84963048c nbd: check the re... |
437 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
438 |
|
f4507164e nbd: rename the n... |
439 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1da177e4c Linux-2.6.12-rc2 |
440 |
|
7f338fe45 nbd: set SOCK_MEM... |
441 |
sk_set_memalloc(nbd->sock->sk); |
6521d39a6 nbd: Remove varia... |
442 443 |
nbd->task_recv = current; |
f4507164e nbd: rename the n... |
444 |
ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); |
84963048c nbd: check the re... |
445 |
if (ret) { |
f4507164e nbd: rename the n... |
446 447 |
dev_err(disk_to_dev(nbd->disk), "device_create_file failed! "); |
dcc909d90 nbd: Add locking ... |
448 |
|
6521d39a6 nbd: Remove varia... |
449 |
nbd->task_recv = NULL; |
dcc909d90 nbd: Add locking ... |
450 |
|
84963048c nbd: check the re... |
451 452 |
return ret; } |
6b39bb654 [PATCH] nbd: show... |
453 |
|
37091fdd8 nbd: Create size ... |
454 |
nbd_size_update(nbd, bdev); |
193918307 nbd: Remove 'hard... |
455 456 457 458 459 460 |
while (1) { req = nbd_read_stat(nbd); if (IS_ERR(req)) { ret = PTR_ERR(req); break; } |
d18509f59 nbd: Restructure ... |
461 |
nbd_end_request(nbd, req); |
193918307 nbd: Remove 'hard... |
462 |
} |
6b39bb654 [PATCH] nbd: show... |
463 |
|
37091fdd8 nbd: Create size ... |
464 |
nbd_size_clear(nbd, bdev); |
6521d39a6 nbd: Remove varia... |
465 |
device_remove_file(disk_to_dev(nbd->disk), &pid_attr); |
7e2893a16 nbd: Fix timeout ... |
466 |
nbd->task_recv = NULL; |
7e2893a16 nbd: Fix timeout ... |
467 |
|
7e2893a16 nbd: Fix timeout ... |
468 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
469 |
} |
f4507164e nbd: rename the n... |
470 |
static void nbd_clear_que(struct nbd_device *nbd) |
1da177e4c Linux-2.6.12-rc2 |
471 472 |
{ struct request *req; |
f4507164e nbd: rename the n... |
473 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1da177e4c Linux-2.6.12-rc2 |
474 |
|
4b2f0260c [PATCH] nbd: fix ... |
475 |
/* |
f4507164e nbd: rename the n... |
476 |
* Because we have set nbd->sock to NULL under the tx_lock, all |
4b2f0260c [PATCH] nbd: fix ... |
477 478 479 480 481 482 |
* 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... |
483 484 |
BUG_ON(nbd->sock); BUG_ON(nbd->active_req); |
4b2f0260c [PATCH] nbd: fix ... |
485 |
|
f4507164e nbd: rename the n... |
486 487 |
while (!list_empty(&nbd->queue_head)) { req = list_entry(nbd->queue_head.next, struct request, |
4b2f0260c [PATCH] nbd: fix ... |
488 489 490 |
queuelist); list_del_init(&req->queuelist); req->errors++; |
d18509f59 nbd: Restructure ... |
491 |
nbd_end_request(nbd, req); |
4b2f0260c [PATCH] nbd: fix ... |
492 |
} |
fded4e090 nbd: clear waitin... |
493 494 495 496 497 498 |
while (!list_empty(&nbd->waiting_queue)) { req = list_entry(nbd->waiting_queue.next, struct request, queuelist); list_del_init(&req->queuelist); req->errors++; |
d18509f59 nbd: Restructure ... |
499 |
nbd_end_request(nbd, req); |
fded4e090 nbd: clear waitin... |
500 |
} |
e78273c80 nbd: Move clear q... |
501 502 |
dev_dbg(disk_to_dev(nbd->disk), "queue cleared "); |
1da177e4c Linux-2.6.12-rc2 |
503 |
} |
7fdfd4065 NBD: allow hung n... |
504 |
|
f4507164e nbd: rename the n... |
505 |
static void nbd_handle_req(struct nbd_device *nbd, struct request *req) |
48cf6061b NBD: allow nbd to... |
506 |
{ |
33659ebba block: remove wra... |
507 |
if (req->cmd_type != REQ_TYPE_FS) |
48cf6061b NBD: allow nbd to... |
508 |
goto error_out; |
9dc6c806b nbd: stop using r... |
509 510 511 512 513 514 |
if (rq_data_dir(req) == WRITE && (nbd->flags & NBD_FLAG_READ_ONLY)) { dev_err(disk_to_dev(nbd->disk), "Write on read-only "); goto error_out; |
75f187aba nbd: support FLUS... |
515 |
} |
48cf6061b NBD: allow nbd to... |
516 |
req->errors = 0; |
f4507164e nbd: rename the n... |
517 518 519 520 |
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... |
521 522 |
"Attempted send on closed socket "); |
15746fcaa nbd: trivial clea... |
523 |
goto error_out; |
48cf6061b NBD: allow nbd to... |
524 |
} |
f4507164e nbd: rename the n... |
525 |
nbd->active_req = req; |
48cf6061b NBD: allow nbd to... |
526 |
|
7e2893a16 nbd: Fix timeout ... |
527 528 |
if (nbd->xmit_timeout && list_empty_careful(&nbd->queue_head)) mod_timer(&nbd->timeout_timer, jiffies + nbd->xmit_timeout); |
f4507164e nbd: rename the n... |
529 530 531 |
if (nbd_send_req(nbd, req) != 0) { dev_err(disk_to_dev(nbd->disk), "Request send failed "); |
48cf6061b NBD: allow nbd to... |
532 |
req->errors++; |
d18509f59 nbd: Restructure ... |
533 |
nbd_end_request(nbd, req); |
48cf6061b NBD: allow nbd to... |
534 |
} else { |
f4507164e nbd: rename the n... |
535 |
spin_lock(&nbd->queue_lock); |
01ff5dbc0 block/nbd: micro-... |
536 |
list_add_tail(&req->queuelist, &nbd->queue_head); |
f4507164e nbd: rename the n... |
537 |
spin_unlock(&nbd->queue_lock); |
48cf6061b NBD: allow nbd to... |
538 |
} |
f4507164e nbd: rename the n... |
539 540 541 |
nbd->active_req = NULL; mutex_unlock(&nbd->tx_lock); wake_up_all(&nbd->active_wq); |
48cf6061b NBD: allow nbd to... |
542 543 544 545 546 |
return; error_out: req->errors++; |
d18509f59 nbd: Restructure ... |
547 |
nbd_end_request(nbd, req); |
48cf6061b NBD: allow nbd to... |
548 |
} |
cad73b270 nbd: Rename funct... |
549 |
static int nbd_thread_send(void *data) |
48cf6061b NBD: allow nbd to... |
550 |
{ |
f4507164e nbd: rename the n... |
551 |
struct nbd_device *nbd = data; |
48cf6061b NBD: allow nbd to... |
552 |
struct request *req; |
7e2893a16 nbd: Fix timeout ... |
553 |
nbd->task_send = current; |
8698a745d sched, treewide: ... |
554 |
set_user_nice(current, MIN_NICE); |
f4507164e nbd: rename the n... |
555 |
while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) { |
48cf6061b NBD: allow nbd to... |
556 |
/* wait for something to do */ |
f4507164e nbd: rename the n... |
557 |
wait_event_interruptible(nbd->waiting_wq, |
48cf6061b NBD: allow nbd to... |
558 |
kthread_should_stop() || |
f4507164e nbd: rename the n... |
559 |
!list_empty(&nbd->waiting_queue)); |
48cf6061b NBD: allow nbd to... |
560 561 |
/* extract request */ |
f4507164e nbd: rename the n... |
562 |
if (list_empty(&nbd->waiting_queue)) |
48cf6061b NBD: allow nbd to... |
563 |
continue; |
f4507164e nbd: rename the n... |
564 565 |
spin_lock_irq(&nbd->queue_lock); req = list_entry(nbd->waiting_queue.next, struct request, |
48cf6061b NBD: allow nbd to... |
566 567 |
queuelist); list_del_init(&req->queuelist); |
f4507164e nbd: rename the n... |
568 |
spin_unlock_irq(&nbd->queue_lock); |
48cf6061b NBD: allow nbd to... |
569 570 |
/* handle request */ |
f4507164e nbd: rename the n... |
571 |
nbd_handle_req(nbd, req); |
48cf6061b NBD: allow nbd to... |
572 |
} |
7e2893a16 nbd: Fix timeout ... |
573 574 |
nbd->task_send = NULL; |
48cf6061b NBD: allow nbd to... |
575 576 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
577 578 579 |
/* * We always wait for result of write, for now. It would be nice to make it optional * in future |
f4507164e nbd: rename the n... |
580 |
* if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK)) |
1da177e4c Linux-2.6.12-rc2 |
581 582 583 |
* { printk( "Warning: Ignoring result! "); nbd_end_request( req ); } */ |
cad73b270 nbd: Rename funct... |
584 |
static void nbd_request_handler(struct request_queue *q) |
398eb0855 nbd: fix sparse w... |
585 |
__releases(q->queue_lock) __acquires(q->queue_lock) |
1da177e4c Linux-2.6.12-rc2 |
586 587 588 |
{ struct request *req; |
9934c8c04 block: implement ... |
589 |
while ((req = blk_fetch_request(q)) != NULL) { |
f4507164e nbd: rename the n... |
590 |
struct nbd_device *nbd; |
1da177e4c Linux-2.6.12-rc2 |
591 |
|
48cf6061b NBD: allow nbd to... |
592 |
spin_unlock_irq(q->queue_lock); |
f4507164e nbd: rename the n... |
593 |
nbd = req->rq_disk->private_data; |
1da177e4c Linux-2.6.12-rc2 |
594 |
|
f4507164e nbd: rename the n... |
595 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1da177e4c Linux-2.6.12-rc2 |
596 |
|
d18509f59 nbd: Restructure ... |
597 598 599 |
dev_dbg(nbd_to_dev(nbd), "request %p: dequeued (flags=%x) ", req, req->cmd_type); |
f4507164e nbd: rename the n... |
600 |
if (unlikely(!nbd->sock)) { |
da6ccaaa7 nbd: ratelimit er... |
601 602 603 |
dev_err_ratelimited(disk_to_dev(nbd->disk), "Attempted send on closed socket "); |
4d48a542b nbd: fix I/O hang... |
604 |
req->errors++; |
d18509f59 nbd: Restructure ... |
605 |
nbd_end_request(nbd, req); |
4d48a542b nbd: fix I/O hang... |
606 607 608 |
spin_lock_irq(q->queue_lock); continue; } |
f4507164e nbd: rename the n... |
609 610 611 |
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 |
612 |
|
f4507164e nbd: rename the n... |
613 |
wake_up(&nbd->waiting_wq); |
4b2f0260c [PATCH] nbd: fix ... |
614 |
|
1da177e4c Linux-2.6.12-rc2 |
615 |
spin_lock_irq(q->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
616 |
} |
1da177e4c Linux-2.6.12-rc2 |
617 |
} |
23272a675 nbd: Remove signa... |
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock) { int ret = 0; spin_lock_irq(&nbd->sock_lock); if (nbd->sock) { ret = -EBUSY; goto out; } nbd->sock = sock; out: spin_unlock_irq(&nbd->sock_lock); return ret; } |
0e4f0f6f6 nbd: Cleanup rese... |
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
/* Reset all properties of an NBD device */ static void nbd_reset(struct nbd_device *nbd) { nbd->disconnect = false; nbd->timedout = false; nbd->blksize = 1024; nbd->bytesize = 0; set_capacity(nbd->disk, 0); nbd->flags = 0; nbd->xmit_timeout = 0; queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); del_timer_sync(&nbd->timeout_timer); } static void nbd_bdev_reset(struct block_device *bdev) { set_device_ro(bdev, false); bdev->bd_inode->i_size = 0; if (max_part > 0) { blkdev_reread_part(bdev); bdev->bd_invalidated = 1; } } |
d02cf5310 nbd: Move flag pa... |
659 660 661 662 663 664 665 |
static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev) { if (nbd->flags & NBD_FLAG_READ_ONLY) set_device_ro(bdev, true); if (nbd->flags & NBD_FLAG_SEND_TRIM) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); if (nbd->flags & NBD_FLAG_SEND_FLUSH) |
aafb1eecb nbd: switch to us... |
666 |
blk_queue_write_cache(nbd->disk->queue, true, false); |
d02cf5310 nbd: Move flag pa... |
667 |
else |
aafb1eecb nbd: switch to us... |
668 |
blk_queue_write_cache(nbd->disk->queue, false, false); |
d02cf5310 nbd: Move flag pa... |
669 |
} |
30d53d9c1 nbd: Add debugfs ... |
670 671 |
static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); |
1a2ad2112 nbd: add locking ... |
672 |
/* Must be called with tx_lock held */ |
1da177e4c Linux-2.6.12-rc2 |
673 |
|
f4507164e nbd: rename the n... |
674 |
static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, |
1a2ad2112 nbd: add locking ... |
675 676 |
unsigned int cmd, unsigned long arg) { |
1da177e4c Linux-2.6.12-rc2 |
677 |
switch (cmd) { |
1a2ad2112 nbd: add locking ... |
678 679 |
case NBD_DISCONNECT: { struct request sreq; |
f4507164e nbd: rename the n... |
680 681 |
dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT "); |
3a2d63f87 nbd: fsync and ki... |
682 683 |
if (!nbd->sock) return -EINVAL; |
1a2ad2112 nbd: add locking ... |
684 |
|
3a2d63f87 nbd: fsync and ki... |
685 686 687 |
mutex_unlock(&nbd->tx_lock); fsync_bdev(bdev); mutex_lock(&nbd->tx_lock); |
4f54eec83 block: use blk_rq... |
688 |
blk_rq_init(NULL, &sreq); |
4f8c9510b block: rename REQ... |
689 |
sreq.cmd_type = REQ_TYPE_DRV_PRIV; |
3a2d63f87 nbd: fsync and ki... |
690 691 |
/* Check again after getting mutex back. */ |
f4507164e nbd: rename the n... |
692 |
if (!nbd->sock) |
1da177e4c Linux-2.6.12-rc2 |
693 |
return -EINVAL; |
3a2d63f87 nbd: fsync and ki... |
694 |
|
696697cb5 nbd: Change 'disc... |
695 |
nbd->disconnect = true; |
c378f70ad nbd: correct disc... |
696 |
|
f4507164e nbd: rename the n... |
697 |
nbd_send_req(nbd, &sreq); |
c378f70ad nbd: correct disc... |
698 |
return 0; |
1a2ad2112 nbd: add locking ... |
699 |
} |
1da177e4c Linux-2.6.12-rc2 |
700 |
|
23272a675 nbd: Remove signa... |
701 702 |
case NBD_CLEAR_SOCK: sock_shutdown(nbd); |
f4507164e nbd: rename the n... |
703 704 |
nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); |
fded4e090 nbd: clear waitin... |
705 |
BUG_ON(!list_empty(&nbd->waiting_queue)); |
3a2d63f87 nbd: fsync and ki... |
706 |
kill_bdev(bdev); |
1a2ad2112 nbd: add locking ... |
707 |
return 0; |
1a2ad2112 nbd: add locking ... |
708 709 |
case NBD_SET_SOCK: { |
e25115786 switch nbd to soc... |
710 |
int err; |
23272a675 nbd: Remove signa... |
711 712 713 714 715 716 717 718 719 720 |
struct socket *sock = sockfd_lookup(arg, &err); if (!sock) return err; err = nbd_set_socket(nbd, sock); if (!err && max_part) bdev->bd_invalidated = 1; return err; |
1a2ad2112 nbd: add locking ... |
721 |
} |
37091fdd8 nbd: Create size ... |
722 |
case NBD_SET_BLKSIZE: { |
5e454c67f nbd: use correct ... |
723 |
loff_t bsize = div_s64(nbd->bytesize, arg); |
37091fdd8 nbd: Create size ... |
724 725 726 |
return nbd_size_set(nbd, bdev, arg, bsize); } |
1a2ad2112 nbd: add locking ... |
727 |
|
1da177e4c Linux-2.6.12-rc2 |
728 |
case NBD_SET_SIZE: |
37091fdd8 nbd: Create size ... |
729 730 731 732 733 |
return nbd_size_set(nbd, bdev, nbd->blksize, arg / nbd->blksize); case NBD_SET_SIZE_BLOCKS: return nbd_size_set(nbd, bdev, nbd->blksize, arg); |
1a2ad2112 nbd: add locking ... |
734 |
|
7fdfd4065 NBD: allow hung n... |
735 |
case NBD_SET_TIMEOUT: |
f4507164e nbd: rename the n... |
736 |
nbd->xmit_timeout = arg * HZ; |
7e2893a16 nbd: Fix timeout ... |
737 738 739 740 741 |
if (arg) mod_timer(&nbd->timeout_timer, jiffies + nbd->xmit_timeout); else del_timer_sync(&nbd->timeout_timer); |
7fdfd4065 NBD: allow hung n... |
742 |
return 0; |
1a2ad2112 nbd: add locking ... |
743 |
|
2f0125088 nbd: add set flag... |
744 745 746 |
case NBD_SET_FLAGS: nbd->flags = arg; return 0; |
1a2ad2112 nbd: add locking ... |
747 748 |
case NBD_DO_IT: { struct task_struct *thread; |
1a2ad2112 nbd: add locking ... |
749 |
int error; |
6521d39a6 nbd: Remove varia... |
750 |
if (nbd->task_recv) |
c91192d66 nbd: do not allow... |
751 |
return -EBUSY; |
e25115786 switch nbd to soc... |
752 |
if (!nbd->sock) |
1da177e4c Linux-2.6.12-rc2 |
753 |
return -EINVAL; |
1a2ad2112 nbd: add locking ... |
754 |
|
f4507164e nbd: rename the n... |
755 |
mutex_unlock(&nbd->tx_lock); |
1a2ad2112 nbd: add locking ... |
756 |
|
d02cf5310 nbd: Move flag pa... |
757 |
nbd_parse_flags(nbd, bdev); |
a336d2987 nbd: handle disca... |
758 |
|
cad73b270 nbd: Rename funct... |
759 |
thread = kthread_run(nbd_thread_send, nbd, "%s", |
30d53d9c1 nbd: Add debugfs ... |
760 |
nbd_name(nbd)); |
1a2ad2112 nbd: add locking ... |
761 |
if (IS_ERR(thread)) { |
f4507164e nbd: rename the n... |
762 |
mutex_lock(&nbd->tx_lock); |
48cf6061b NBD: allow nbd to... |
763 |
return PTR_ERR(thread); |
1a2ad2112 nbd: add locking ... |
764 |
} |
d06df60b9 nbd: Replace kthr... |
765 |
|
30d53d9c1 nbd: Add debugfs ... |
766 |
nbd_dev_dbg_init(nbd); |
37091fdd8 nbd: Create size ... |
767 |
error = nbd_thread_recv(nbd, bdev); |
30d53d9c1 nbd: Add debugfs ... |
768 |
nbd_dev_dbg_close(nbd); |
48cf6061b NBD: allow nbd to... |
769 |
kthread_stop(thread); |
1a2ad2112 nbd: add locking ... |
770 |
|
f4507164e nbd: rename the n... |
771 |
mutex_lock(&nbd->tx_lock); |
193918307 nbd: Remove 'hard... |
772 |
|
36e47bee7 nbd: sock_shutdow... |
773 |
sock_shutdown(nbd); |
f4507164e nbd: rename the n... |
774 |
nbd_clear_que(nbd); |
3a2d63f87 nbd: fsync and ki... |
775 |
kill_bdev(bdev); |
0e4f0f6f6 nbd: Cleanup rese... |
776 |
nbd_bdev_reset(bdev); |
c378f70ad nbd: correct disc... |
777 |
if (nbd->disconnect) /* user requested, ignore socket errors */ |
1f7b5cf1b nbd: Timeouts are... |
778 779 780 |
error = 0; if (nbd->timedout) error = -ETIMEDOUT; |
0e4f0f6f6 nbd: Cleanup rese... |
781 |
nbd_reset(nbd); |
193918307 nbd: Remove 'hard... |
782 |
return error; |
1a2ad2112 nbd: add locking ... |
783 |
} |
1da177e4c Linux-2.6.12-rc2 |
784 |
case NBD_CLEAR_QUE: |
4b2f0260c [PATCH] nbd: fix ... |
785 786 787 788 |
/* * This is for compatibility only. The queue is always cleared * by NBD_DO_IT or NBD_CLEAR_SOCK. */ |
1da177e4c Linux-2.6.12-rc2 |
789 |
return 0; |
1a2ad2112 nbd: add locking ... |
790 |
|
1da177e4c Linux-2.6.12-rc2 |
791 |
case NBD_PRINT_DEBUG: |
f4507164e nbd: rename the n... |
792 |
dev_info(disk_to_dev(nbd->disk), |
5eedf5415 nbd: replace some... |
793 794 |
"next = %p, prev = %p, head = %p ", |
f4507164e nbd: rename the n... |
795 796 |
nbd->queue_head.next, nbd->queue_head.prev, &nbd->queue_head); |
1da177e4c Linux-2.6.12-rc2 |
797 798 |
return 0; } |
1a2ad2112 nbd: add locking ... |
799 800 801 802 803 804 |
return -ENOTTY; } static int nbd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { |
f4507164e nbd: rename the n... |
805 |
struct nbd_device *nbd = bdev->bd_disk->private_data; |
1a2ad2112 nbd: add locking ... |
806 807 808 809 |
int error; if (!capable(CAP_SYS_ADMIN)) return -EPERM; |
f4507164e nbd: rename the n... |
810 |
BUG_ON(nbd->magic != NBD_MAGIC); |
1a2ad2112 nbd: add locking ... |
811 |
|
f4507164e nbd: rename the n... |
812 813 814 |
mutex_lock(&nbd->tx_lock); error = __nbd_ioctl(bdev, nbd, cmd, arg); mutex_unlock(&nbd->tx_lock); |
1a2ad2112 nbd: add locking ... |
815 816 |
return error; |
1da177e4c Linux-2.6.12-rc2 |
817 |
} |
83d5cde47 const: make block... |
818 |
static const struct block_device_operations nbd_fops = |
1da177e4c Linux-2.6.12-rc2 |
819 820 |
{ .owner = THIS_MODULE, |
8a6cfeb6d block: push down ... |
821 |
.ioctl = nbd_ioctl, |
263a3df18 nbd: use ->compat... |
822 |
.compat_ioctl = nbd_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
823 |
}; |
30d53d9c1 nbd: Add debugfs ... |
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 |
#if IS_ENABLED(CONFIG_DEBUG_FS) static int nbd_dbg_tasks_show(struct seq_file *s, void *unused) { struct nbd_device *nbd = s->private; if (nbd->task_recv) seq_printf(s, "recv: %d ", task_pid_nr(nbd->task_recv)); if (nbd->task_send) seq_printf(s, "send: %d ", task_pid_nr(nbd->task_send)); return 0; } static int nbd_dbg_tasks_open(struct inode *inode, struct file *file) { return single_open(file, nbd_dbg_tasks_show, inode->i_private); } static const struct file_operations nbd_dbg_tasks_ops = { .open = nbd_dbg_tasks_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int nbd_dbg_flags_show(struct seq_file *s, void *unused) { struct nbd_device *nbd = s->private; u32 flags = nbd->flags; seq_printf(s, "Hex: 0x%08x ", flags); seq_puts(s, "Known flags: "); if (flags & NBD_FLAG_HAS_FLAGS) seq_puts(s, "NBD_FLAG_HAS_FLAGS "); if (flags & NBD_FLAG_READ_ONLY) seq_puts(s, "NBD_FLAG_READ_ONLY "); if (flags & NBD_FLAG_SEND_FLUSH) seq_puts(s, "NBD_FLAG_SEND_FLUSH "); if (flags & NBD_FLAG_SEND_TRIM) seq_puts(s, "NBD_FLAG_SEND_TRIM "); return 0; } static int nbd_dbg_flags_open(struct inode *inode, struct file *file) { return single_open(file, nbd_dbg_flags_show, inode->i_private); } static const struct file_operations nbd_dbg_flags_ops = { .open = nbd_dbg_flags_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int nbd_dev_dbg_init(struct nbd_device *nbd) { struct dentry *dir; |
27ea43fe2 nbd: Fix debugfs ... |
895 896 897 |
if (!nbd_dbg_dir) return -EIO; |
30d53d9c1 nbd: Add debugfs ... |
898 899 |
dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir); |
27ea43fe2 nbd: Fix debugfs ... |
900 901 902 903 904 |
if (!dir) { dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s' ", nbd_name(nbd)); return -EIO; |
30d53d9c1 nbd: Add debugfs ... |
905 906 |
} nbd->dbg_dir = dir; |
27ea43fe2 nbd: Fix debugfs ... |
907 908 909 910 |
debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops); debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize); debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout); debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize); |
d366a0ff1 nbd: pass the nbd... |
911 |
debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops); |
30d53d9c1 nbd: Add debugfs ... |
912 913 914 915 916 917 918 919 920 921 922 923 924 925 |
return 0; } static void nbd_dev_dbg_close(struct nbd_device *nbd) { debugfs_remove_recursive(nbd->dbg_dir); } static int nbd_dbg_init(void) { struct dentry *dbg_dir; dbg_dir = debugfs_create_dir("nbd", NULL); |
27ea43fe2 nbd: Fix debugfs ... |
926 927 |
if (!dbg_dir) return -EIO; |
30d53d9c1 nbd: Add debugfs ... |
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
nbd_dbg_dir = dbg_dir; return 0; } static void nbd_dbg_close(void) { debugfs_remove_recursive(nbd_dbg_dir); } #else /* IS_ENABLED(CONFIG_DEBUG_FS) */ static int nbd_dev_dbg_init(struct nbd_device *nbd) { return 0; } static void nbd_dev_dbg_close(struct nbd_device *nbd) { } static int nbd_dbg_init(void) { return 0; } static void nbd_dbg_close(void) { } #endif |
1da177e4c Linux-2.6.12-rc2 |
960 961 962 963 964 965 966 967 968 |
/* * 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... |
969 |
int part_shift; |
1da177e4c Linux-2.6.12-rc2 |
970 |
|
5b7b18ccd [PATCH] drivers/b... |
971 |
BUILD_BUG_ON(sizeof(struct nbd_request) != 28); |
1da177e4c Linux-2.6.12-rc2 |
972 |
|
d71a6d733 NBD: add partitio... |
973 |
if (max_part < 0) { |
7742ce4ab nbd: lower the lo... |
974 975 |
printk(KERN_ERR "nbd: max_part must be >= 0 "); |
d71a6d733 NBD: add partitio... |
976 977 978 979 |
return -EINVAL; } part_shift = 0; |
5988ce239 nbd: adjust 'max_... |
980 |
if (max_part > 0) { |
d71a6d733 NBD: add partitio... |
981 |
part_shift = fls(max_part); |
5988ce239 nbd: adjust 'max_... |
982 983 984 985 986 987 988 989 990 991 |
/* * 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... |
992 993 994 995 996 |
if ((1UL << part_shift) > DISK_MAX_PARTS) return -EINVAL; if (nbds_max > 1UL << (MINORBITS - part_shift)) return -EINVAL; |
ff6b8090e nbd: fix possible... |
997 998 999 |
nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); if (!nbd_dev) return -ENOMEM; |
40be0c28b [PATCH] nbd: Don'... |
1000 |
for (i = 0; i < nbds_max; i++) { |
d71a6d733 NBD: add partitio... |
1001 |
struct gendisk *disk = alloc_disk(1 << part_shift); |
1da177e4c Linux-2.6.12-rc2 |
1002 1003 1004 1005 1006 1007 1008 1009 |
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. */ |
cad73b270 nbd: Rename funct... |
1010 |
disk->queue = blk_init_queue(nbd_request_handler, &nbd_lock); |
1da177e4c Linux-2.6.12-rc2 |
1011 1012 1013 1014 |
if (!disk->queue) { put_disk(disk); goto out; } |
31dcfab0a nbd: tell the blo... |
1015 1016 1017 1018 |
/* * Tell the block layer that we are not a rotational device */ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue); |
b277da0a8 block: disable en... |
1019 |
queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, disk->queue); |
a336d2987 nbd: handle disca... |
1020 |
disk->queue->limits.discard_granularity = 512; |
2bb4cd5cc block: have drive... |
1021 |
blk_queue_max_discard_sectors(disk->queue, UINT_MAX); |
a336d2987 nbd: handle disca... |
1022 |
disk->queue->limits.discard_zeroes_data = 0; |
078be02b8 nbd: increase def... |
1023 1024 |
blk_queue_max_hw_sectors(disk->queue, 65536); disk->queue->limits.max_sectors = 256; |
1da177e4c Linux-2.6.12-rc2 |
1025 1026 1027 1028 1029 1030 1031 1032 1033 |
} if (register_blkdev(NBD_MAJOR, "nbd")) { err = -EIO; goto out; } printk(KERN_INFO "nbd: registered device at major %d ", NBD_MAJOR); |
1da177e4c Linux-2.6.12-rc2 |
1034 |
|
30d53d9c1 nbd: Add debugfs ... |
1035 |
nbd_dbg_init(); |
40be0c28b [PATCH] nbd: Don'... |
1036 |
for (i = 0; i < nbds_max; i++) { |
1da177e4c Linux-2.6.12-rc2 |
1037 |
struct gendisk *disk = nbd_dev[i].disk; |
f4507164e nbd: rename the n... |
1038 |
nbd_dev[i].magic = NBD_MAGIC; |
48cf6061b NBD: allow nbd to... |
1039 |
INIT_LIST_HEAD(&nbd_dev[i].waiting_queue); |
1da177e4c Linux-2.6.12-rc2 |
1040 |
spin_lock_init(&nbd_dev[i].queue_lock); |
23272a675 nbd: Remove signa... |
1041 |
spin_lock_init(&nbd_dev[i].sock_lock); |
1da177e4c Linux-2.6.12-rc2 |
1042 |
INIT_LIST_HEAD(&nbd_dev[i].queue_head); |
82d4dc5ad [PATCH] sem2mutex... |
1043 |
mutex_init(&nbd_dev[i].tx_lock); |
7e2893a16 nbd: Fix timeout ... |
1044 1045 1046 |
init_timer(&nbd_dev[i].timeout_timer); nbd_dev[i].timeout_timer.function = nbd_xmit_timeout; nbd_dev[i].timeout_timer.data = (unsigned long)&nbd_dev[i]; |
4b2f0260c [PATCH] nbd: fix ... |
1047 |
init_waitqueue_head(&nbd_dev[i].active_wq); |
48cf6061b NBD: allow nbd to... |
1048 |
init_waitqueue_head(&nbd_dev[i].waiting_wq); |
1da177e4c Linux-2.6.12-rc2 |
1049 |
disk->major = NBD_MAJOR; |
d71a6d733 NBD: add partitio... |
1050 |
disk->first_minor = i << part_shift; |
1da177e4c Linux-2.6.12-rc2 |
1051 1052 |
disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; |
1da177e4c Linux-2.6.12-rc2 |
1053 |
sprintf(disk->disk_name, "nbd%d", i); |
0e4f0f6f6 nbd: Cleanup rese... |
1054 |
nbd_reset(&nbd_dev[i]); |
1da177e4c Linux-2.6.12-rc2 |
1055 1056 1057 1058 1059 1060 1061 1062 1063 |
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... |
1064 |
kfree(nbd_dev); |
1da177e4c Linux-2.6.12-rc2 |
1065 1066 1067 1068 1069 1070 |
return err; } static void __exit nbd_cleanup(void) { int i; |
30d53d9c1 nbd: Add debugfs ... |
1071 1072 |
nbd_dbg_close(); |
40be0c28b [PATCH] nbd: Don'... |
1073 |
for (i = 0; i < nbds_max; i++) { |
1da177e4c Linux-2.6.12-rc2 |
1074 |
struct gendisk *disk = nbd_dev[i].disk; |
40be0c28b [PATCH] nbd: Don'... |
1075 |
nbd_dev[i].magic = 0; |
1da177e4c Linux-2.6.12-rc2 |
1076 1077 1078 1079 1080 1081 |
if (disk) { del_gendisk(disk); blk_cleanup_queue(disk->queue); put_disk(disk); } } |
1da177e4c Linux-2.6.12-rc2 |
1082 |
unregister_blkdev(NBD_MAJOR, "nbd"); |
f3944d61d nbd: fix memory l... |
1083 |
kfree(nbd_dev); |
1da177e4c Linux-2.6.12-rc2 |
1084 1085 1086 1087 1088 1089 1090 1091 1092 |
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'... |
1093 |
module_param(nbds_max, int, 0444); |
d71a6d733 NBD: add partitio... |
1094 1095 1096 |
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)"); |