Blame view

drivers/block/nbd.c 25.6 KB
1da177e4c   Linus Torvalds   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   Pavel Machek   update email address
7
   * Copyright 1997-2000, 2008 Pavel Machek <pavel@ucw.cz>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
   * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
   *
dbf492d6c   Pavel Machek   [PATCH] nbd: kill...
10
   * This file is released under GPLv2 or later.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
   *
dbf492d6c   Pavel Machek   [PATCH] nbd: kill...
12
   * (part of code stolen from loop.c)
1da177e4c   Linus Torvalds   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   Arnd Bergmann   block: autoconver...
27
  #include <linux/mutex.h>
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
28
29
30
  #include <linux/compiler.h>
  #include <linux/err.h>
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  #include <net/sock.h>
91cf45f02   Trond Myklebust   [NET]: Add the he...
33
  #include <linux/net.h>
48cf6061b   Laurent Vivier   NBD: allow nbd to...
34
  #include <linux/kthread.h>
b9c495bb6   Markus Pargmann   nbd: Fix device b...
35
  #include <linux/types.h>
30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
36
  #include <linux/debugfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
  #include <asm/uaccess.h>
  #include <asm/types.h>
  
  #include <linux/nbd.h>
13e71d69c   Markus Pargmann   nbd: Remove kerne...
42
  struct nbd_device {
22d109c1b   Markus Pargmann   nbd: flags is a u...
43
  	u32 flags;
13e71d69c   Markus Pargmann   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   Markus Pargmann   nbd: Fix device b...
57
  	loff_t bytesize;
13e71d69c   Markus Pargmann   nbd: Remove kerne...
58
  	int xmit_timeout;
1f7b5cf1b   Markus Pargmann   nbd: Timeouts are...
59
  	bool timedout;
696697cb5   Markus Pargmann   nbd: Change 'disc...
60
  	bool disconnect; /* a disconnect has been requested by user */
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
61
62
  
  	struct timer_list timeout_timer;
23272a675   Markus Pargmann   nbd: Remove signa...
63
64
  	/* protects initialization and shutdown of the socket */
  	spinlock_t sock_lock;
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
65
66
  	struct task_struct *task_recv;
  	struct task_struct *task_send;
30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
67
68
69
70
  
  #if IS_ENABLED(CONFIG_DEBUG_FS)
  	struct dentry *dbg_dir;
  #endif
13e71d69c   Markus Pargmann   nbd: Remove kerne...
71
  };
30d53d9c1   Markus Pargmann   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   Wanlong Gao   nbd: rename the n...
77
  #define NBD_MAGIC 0x68797548
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

9c7a41691   Ingo van Lil   [PATCH] drivers/b...
79
  static unsigned int nbds_max = 16;
20a8143ea   Paul Clements   NBD: remove limit...
80
  static struct nbd_device *nbd_dev;
d71a6d733   Laurent Vivier   NBD: add partitio...
81
  static int max_part;
1da177e4c   Linus Torvalds   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   Markus Pargmann   nbd: Restructure ...
94
  static inline struct device *nbd_to_dev(struct nbd_device *nbd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  {
d18509f59   Markus Pargmann   nbd: Restructure ...
96
  	return disk_to_dev(nbd->disk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  }
37091fdd8   Markus Pargmann   nbd: Create size ...
98
99
100
101
  static bool nbd_is_connected(struct nbd_device *nbd)
  {
  	return !!nbd->task_recv;
  }
1da177e4c   Linus Torvalds   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   Alex Bligh   nbd: support FLUS...
108
  	case NBD_CMD_FLUSH: return "flush";
a336d2987   Paul Clements   nbd: handle disca...
109
  	case  NBD_CMD_TRIM: return "trim/discard";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
  	}
  	return "invalid";
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

37091fdd8   Markus Pargmann   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   Markus Pargmann   nbd: Restructure ...
149
  static void nbd_end_request(struct nbd_device *nbd, struct request *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  {
097c94a4e   Kiyoshi Ueda   blk_end_request: ...
151
  	int error = req->errors ? -EIO : 0;
165125e1e   Jens Axboe   [BLOCK] Get rid o...
152
  	struct request_queue *q = req->q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  	unsigned long flags;
d18509f59   Markus Pargmann   nbd: Restructure ...
154
155
156
  	dev_dbg(nbd_to_dev(nbd), "request %p: %s
  ", req,
  		error ? "failed" : "done");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
  
  	spin_lock_irqsave(q->queue_lock, flags);
1011c1b9f   Tejun Heo   block: blk_rq_[cu...
159
  	__blk_end_request_all(req, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  	spin_unlock_irqrestore(q->queue_lock, flags);
  }
e018e7570   Markus Pargmann   nbd: Remove fixme...
162
163
164
  /*
   * Forcibly shutdown the socket causing all listeners to error
   */
36e47bee7   Markus Pargmann   nbd: sock_shutdow...
165
  static void sock_shutdown(struct nbd_device *nbd)
7fdfd4065   Paul Clements   NBD: allow hung n...
166
  {
23272a675   Markus Pargmann   nbd: Remove signa...
167
168
169
170
  	spin_lock_irq(&nbd->sock_lock);
  
  	if (!nbd->sock) {
  		spin_unlock_irq(&nbd->sock_lock);
260bbce40   Markus Pargmann   nbd: restructure ...
171
  		return;
23272a675   Markus Pargmann   nbd: Remove signa...
172
  	}
260bbce40   Markus Pargmann   nbd: restructure ...
173
174
175
176
  
  	dev_warn(disk_to_dev(nbd->disk), "shutting down socket
  ");
  	kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
23272a675   Markus Pargmann   nbd: Remove signa...
177
  	sockfd_put(nbd->sock);
260bbce40   Markus Pargmann   nbd: restructure ...
178
  	nbd->sock = NULL;
23272a675   Markus Pargmann   nbd: Remove signa...
179
180
181
  	spin_unlock_irq(&nbd->sock_lock);
  
  	del_timer(&nbd->timeout_timer);
7fdfd4065   Paul Clements   NBD: allow hung n...
182
183
184
185
  }
  
  static void nbd_xmit_timeout(unsigned long arg)
  {
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
186
  	struct nbd_device *nbd = (struct nbd_device *)arg;
dcc909d90   Markus Pargmann   nbd: Add locking ...
187
  	unsigned long flags;
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
188
189
190
  
  	if (list_empty(&nbd->queue_head))
  		return;
23272a675   Markus Pargmann   nbd: Remove signa...
191
  	spin_lock_irqsave(&nbd->sock_lock, flags);
dcc909d90   Markus Pargmann   nbd: Add locking ...
192

1f7b5cf1b   Markus Pargmann   nbd: Timeouts are...
193
  	nbd->timedout = true;
7fdfd4065   Paul Clements   NBD: allow hung n...
194

23272a675   Markus Pargmann   nbd: Remove signa...
195
196
  	if (nbd->sock)
  		kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
197

23272a675   Markus Pargmann   nbd: Remove signa...
198
  	spin_unlock_irqrestore(&nbd->sock_lock, flags);
dcc909d90   Markus Pargmann   nbd: Add locking ...
199

23272a675   Markus Pargmann   nbd: Remove signa...
200
201
  	dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection
  ");
7fdfd4065   Paul Clements   NBD: allow hung n...
202
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
205
  /*
   *  Send or receive packet.
   */
f4507164e   Wanlong Gao   nbd: rename the n...
206
  static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
  		int msg_flags)
  {
f4507164e   Wanlong Gao   nbd: rename the n...
209
  	struct socket *sock = nbd->sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
  	int result;
  	struct msghdr msg;
  	struct kvec iov;
7f338fe45   Mel Gorman   nbd: set SOCK_MEM...
213
  	unsigned long pflags = current->flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

ffc41cf8d   Mike Snitzer   nbd: prevent sock...
215
  	if (unlikely(!sock)) {
f4507164e   Wanlong Gao   nbd: rename the n...
216
  		dev_err(disk_to_dev(nbd->disk),
7f1b90f99   WANG Cong   nbd: replace prin...
217
218
219
  			"Attempted %s on closed socket in sock_xmit
  ",
  			(send ? "send" : "recv"));
ffc41cf8d   Mike Snitzer   nbd: prevent sock...
220
221
  		return -EINVAL;
  	}
7f338fe45   Mel Gorman   nbd: set SOCK_MEM...
222
  	current->flags |= PF_MEMALLOC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  	do {
7f338fe45   Mel Gorman   nbd: set SOCK_MEM...
224
  		sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
231
  		msg.msg_flags = msg_flags | MSG_NOSIGNAL;
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
232
  		if (send)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  			result = kernel_sendmsg(sock, &msg, &iov, 1, size);
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
234
  		else
35fbf5bcf   Namhyung Kim   nbd: pass MSG_* f...
235
236
  			result = kernel_recvmsg(sock, &msg, &iov, 1, size,
  						msg.msg_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

1da177e4c   Linus Torvalds   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   Mel Gorman   nbd: set SOCK_MEM...
246
  	tsk_restore_flags(current, pflags, PF_MEMALLOC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247

7e2893a16   Markus Pargmann   nbd: Fix timeout ...
248
249
  	if (!send && nbd->xmit_timeout)
  		mod_timer(&nbd->timeout_timer, jiffies + nbd->xmit_timeout);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  	return result;
  }
f4507164e   Wanlong Gao   nbd: rename the n...
252
  static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
  		int flags)
  {
  	int result;
  	void *kaddr = kmap(bvec->bv_page);
f4507164e   Wanlong Gao   nbd: rename the n...
257
258
  	result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset,
  			   bvec->bv_len, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
  	kunmap(bvec->bv_page);
  	return result;
  }
7fdfd4065   Paul Clements   NBD: allow hung n...
262
  /* always call with the tx_lock held */
f4507164e   Wanlong Gao   nbd: rename the n...
263
  static int nbd_send_req(struct nbd_device *nbd, struct request *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  {
5705f7021   NeilBrown   Introduce rq_for_...
265
  	int result, flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  	struct nbd_request request;
1011c1b9f   Tejun Heo   block: blk_rq_[cu...
267
  	unsigned long size = blk_rq_bytes(req);
9dc6c806b   Christoph Hellwig   nbd: stop using r...
268
269
270
271
  	u32 type;
  
  	if (req->cmd_type == REQ_TYPE_DRV_PRIV)
  		type = NBD_CMD_DISC;
c2df40dfb   Mike Christie   drivers: use req ...
272
  	else if (req_op(req) == REQ_OP_DISCARD)
9dc6c806b   Christoph Hellwig   nbd: stop using r...
273
  		type = NBD_CMD_TRIM;
3a5e02ced   Mike Christie   block, drivers: a...
274
  	else if (req_op(req) == REQ_OP_FLUSH)
9dc6c806b   Christoph Hellwig   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   Linus Torvalds   Linux-2.6.12-rc2
280

04cfac4e4   Hani Benhabiles   nbd: zero from an...
281
  	memset(&request, 0, sizeof(request));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  	request.magic = htonl(NBD_REQUEST_MAGIC);
9dc6c806b   Christoph Hellwig   nbd: stop using r...
283
284
  	request.type = htonl(type);
  	if (type != NBD_CMD_FLUSH && type != NBD_CMD_DISC) {
75f187aba   Alex Bligh   nbd: support FLUS...
285
286
287
  		request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
  		request.len = htonl(size);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  	memcpy(request.handle, &req, sizeof(req));
d18509f59   Markus Pargmann   nbd: Restructure ...
289
290
  	dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)
  ",
9dc6c806b   Christoph Hellwig   nbd: stop using r...
291
  		req, nbdcmd_to_ascii(type),
d18509f59   Markus Pargmann   nbd: Restructure ...
292
  		(unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req));
f4507164e   Wanlong Gao   nbd: rename the n...
293
  	result = sock_xmit(nbd, 1, &request, sizeof(request),
9dc6c806b   Christoph Hellwig   nbd: stop using r...
294
  			(type == NBD_CMD_WRITE) ? MSG_MORE : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  	if (result <= 0) {
f4507164e   Wanlong Gao   nbd: rename the n...
296
  		dev_err(disk_to_dev(nbd->disk),
7f1b90f99   WANG Cong   nbd: replace prin...
297
298
  			"Send control failed (result %d)
  ", result);
dab5313aa   Markus Pargmann   nbd: Return error...
299
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  	}
9dc6c806b   Christoph Hellwig   nbd: stop using r...
301
  	if (type == NBD_CMD_WRITE) {
5705f7021   NeilBrown   Introduce rq_for_...
302
  		struct req_iterator iter;
7988613b0   Kent Overstreet   block: Convert bi...
303
  		struct bio_vec bvec;
1da177e4c   Linus Torvalds   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   NeilBrown   Introduce rq_for_...
308
  		rq_for_each_segment(bvec, req, iter) {
6c92e699b   Jens Axboe   Fixup rq_for_each...
309
  			flags = 0;
4550dd6c6   Kent Overstreet   block: Immutable ...
310
  			if (!rq_iter_last(bvec, iter))
6c92e699b   Jens Axboe   Fixup rq_for_each...
311
  				flags = MSG_MORE;
d18509f59   Markus Pargmann   nbd: Restructure ...
312
313
314
  			dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data
  ",
  				req, bvec.bv_len);
7988613b0   Kent Overstreet   block: Convert bi...
315
  			result = sock_send_bvec(nbd, &bvec, flags);
6c92e699b   Jens Axboe   Fixup rq_for_each...
316
  			if (result <= 0) {
f4507164e   Wanlong Gao   nbd: rename the n...
317
  				dev_err(disk_to_dev(nbd->disk),
7f1b90f99   WANG Cong   nbd: replace prin...
318
319
320
  					"Send data failed (result %d)
  ",
  					result);
dab5313aa   Markus Pargmann   nbd: Return error...
321
  				return -EIO;
6c92e699b   Jens Axboe   Fixup rq_for_each...
322
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  }
f4507164e   Wanlong Gao   nbd: rename the n...
327
  static struct request *nbd_find_request(struct nbd_device *nbd,
0cbc591bf   Denis Cheng   nbd: change a par...
328
  					struct request *xreq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
  {
d2c9740b4   Denis Cheng   nbd: use list_for...
330
  	struct request *req, *tmp;
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
331
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332

f4507164e   Wanlong Gao   nbd: rename the n...
333
  	err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
334
  	if (unlikely(err))
de9ad6d4e   Markus Pargmann   nbd: Return error...
335
  		return ERR_PTR(err);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
336

f4507164e   Wanlong Gao   nbd: rename the n...
337
338
  	spin_lock(&nbd->queue_lock);
  	list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
  		if (req != xreq)
  			continue;
  		list_del_init(&req->queuelist);
f4507164e   Wanlong Gao   nbd: rename the n...
342
  		spin_unlock(&nbd->queue_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
  		return req;
  	}
f4507164e   Wanlong Gao   nbd: rename the n...
345
  	spin_unlock(&nbd->queue_lock);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
346

de9ad6d4e   Markus Pargmann   nbd: Return error...
347
  	return ERR_PTR(-ENOENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  }
f4507164e   Wanlong Gao   nbd: rename the n...
349
  static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
  {
  	int result;
  	void *kaddr = kmap(bvec->bv_page);
f4507164e   Wanlong Gao   nbd: rename the n...
353
  	result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
1da177e4c   Linus Torvalds   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   Wanlong Gao   nbd: rename the n...
360
  static struct request *nbd_read_stat(struct nbd_device *nbd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
364
  {
  	int result;
  	struct nbd_reply reply;
  	struct request *req;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
  
  	reply.magic = 0;
f4507164e   Wanlong Gao   nbd: rename the n...
367
  	result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  	if (result <= 0) {
f4507164e   Wanlong Gao   nbd: rename the n...
369
  		dev_err(disk_to_dev(nbd->disk),
7f1b90f99   WANG Cong   nbd: replace prin...
370
371
  			"Receive control failed (result %d)
  ", result);
193918307   Markus Pargmann   nbd: Remove 'hard...
372
  		return ERR_PTR(result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	}
e4b57e084   Michal Feix   [PATCH] nbd: Chec...
374
375
  
  	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
f4507164e   Wanlong Gao   nbd: rename the n...
376
377
  		dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)
  ",
e4b57e084   Michal Feix   [PATCH] nbd: Chec...
378
  				(unsigned long)ntohl(reply.magic));
193918307   Markus Pargmann   nbd: Remove 'hard...
379
  		return ERR_PTR(-EPROTO);
e4b57e084   Michal Feix   [PATCH] nbd: Chec...
380
  	}
f4507164e   Wanlong Gao   nbd: rename the n...
381
  	req = nbd_find_request(nbd, *(struct request **)reply.handle);
801678c5a   Hirofumi Nakagawa   Remove duplicated...
382
  	if (IS_ERR(req)) {
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
383
384
  		result = PTR_ERR(req);
  		if (result != -ENOENT)
193918307   Markus Pargmann   nbd: Remove 'hard...
385
  			return ERR_PTR(result);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
386

f4507164e   Wanlong Gao   nbd: rename the n...
387
388
  		dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p)
  ",
7f1b90f99   WANG Cong   nbd: replace prin...
389
  			reply.handle);
193918307   Markus Pargmann   nbd: Remove 'hard...
390
  		return ERR_PTR(-EBADR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
  	if (ntohl(reply.error)) {
f4507164e   Wanlong Gao   nbd: rename the n...
393
394
  		dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)
  ",
7f1b90f99   WANG Cong   nbd: replace prin...
395
  			ntohl(reply.error));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
  		req->errors++;
  		return req;
  	}
d18509f59   Markus Pargmann   nbd: Restructure ...
399
400
  	dev_dbg(nbd_to_dev(nbd), "request %p: got reply
  ", req);
9dc6c806b   Christoph Hellwig   nbd: stop using r...
401
  	if (rq_data_dir(req) != WRITE) {
5705f7021   NeilBrown   Introduce rq_for_...
402
  		struct req_iterator iter;
7988613b0   Kent Overstreet   block: Convert bi...
403
  		struct bio_vec bvec;
5705f7021   NeilBrown   Introduce rq_for_...
404
405
  
  		rq_for_each_segment(bvec, req, iter) {
7988613b0   Kent Overstreet   block: Convert bi...
406
  			result = sock_recv_bvec(nbd, &bvec);
6c92e699b   Jens Axboe   Fixup rq_for_each...
407
  			if (result <= 0) {
f4507164e   Wanlong Gao   nbd: rename the n...
408
409
  				dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)
  ",
7f1b90f99   WANG Cong   nbd: replace prin...
410
  					result);
6c92e699b   Jens Axboe   Fixup rq_for_each...
411
412
413
  				req->errors++;
  				return req;
  			}
d18509f59   Markus Pargmann   nbd: Restructure ...
414
415
416
  			dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data
  ",
  				req, bvec.bv_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
  		}
  	}
  	return req;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  }
edfaa7c36   Kay Sievers   Driver core: conv...
421
422
  static ssize_t pid_show(struct device *dev,
  			struct device_attribute *attr, char *buf)
6b39bb654   Paul Clements   [PATCH] nbd: show...
423
  {
edfaa7c36   Kay Sievers   Driver core: conv...
424
  	struct gendisk *disk = dev_to_disk(dev);
6521d39a6   Markus Pargmann   nbd: Remove varia...
425
  	struct nbd_device *nbd = (struct nbd_device *)disk->private_data;
edfaa7c36   Kay Sievers   Driver core: conv...
426

6521d39a6   Markus Pargmann   nbd: Remove varia...
427
428
  	return sprintf(buf, "%d
  ", task_pid_nr(nbd->task_recv));
6b39bb654   Paul Clements   [PATCH] nbd: show...
429
  }
edfaa7c36   Kay Sievers   Driver core: conv...
430
  static struct device_attribute pid_attr = {
01e8ef11b   Parag Warudkar   x86: sysfs: kill ...
431
  	.attr = { .name = "pid", .mode = S_IRUGO},
6b39bb654   Paul Clements   [PATCH] nbd: show...
432
433
  	.show = pid_show,
  };
37091fdd8   Markus Pargmann   nbd: Create size ...
434
  static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
  {
  	struct request *req;
84963048c   WANG Cong   nbd: check the re...
437
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438

f4507164e   Wanlong Gao   nbd: rename the n...
439
  	BUG_ON(nbd->magic != NBD_MAGIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440

7f338fe45   Mel Gorman   nbd: set SOCK_MEM...
441
  	sk_set_memalloc(nbd->sock->sk);
6521d39a6   Markus Pargmann   nbd: Remove varia...
442
443
  
  	nbd->task_recv = current;
f4507164e   Wanlong Gao   nbd: rename the n...
444
  	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
84963048c   WANG Cong   nbd: check the re...
445
  	if (ret) {
f4507164e   Wanlong Gao   nbd: rename the n...
446
447
  		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!
  ");
dcc909d90   Markus Pargmann   nbd: Add locking ...
448

6521d39a6   Markus Pargmann   nbd: Remove varia...
449
  		nbd->task_recv = NULL;
dcc909d90   Markus Pargmann   nbd: Add locking ...
450

84963048c   WANG Cong   nbd: check the re...
451
452
  		return ret;
  	}
6b39bb654   Paul Clements   [PATCH] nbd: show...
453

37091fdd8   Markus Pargmann   nbd: Create size ...
454
  	nbd_size_update(nbd, bdev);
193918307   Markus Pargmann   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   Markus Pargmann   nbd: Restructure ...
461
  		nbd_end_request(nbd, req);
193918307   Markus Pargmann   nbd: Remove 'hard...
462
  	}
6b39bb654   Paul Clements   [PATCH] nbd: show...
463

37091fdd8   Markus Pargmann   nbd: Create size ...
464
  	nbd_size_clear(nbd, bdev);
6521d39a6   Markus Pargmann   nbd: Remove varia...
465
  	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
466
  	nbd->task_recv = NULL;
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
467

7e2893a16   Markus Pargmann   nbd: Fix timeout ...
468
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  }
f4507164e   Wanlong Gao   nbd: rename the n...
470
  static void nbd_clear_que(struct nbd_device *nbd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
  {
  	struct request *req;
f4507164e   Wanlong Gao   nbd: rename the n...
473
  	BUG_ON(nbd->magic != NBD_MAGIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474

4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
475
  	/*
f4507164e   Wanlong Gao   nbd: rename the n...
476
  	 * Because we have set nbd->sock to NULL under the tx_lock, all
4b2f0260c   Herbert Xu   [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   Wanlong Gao   nbd: rename the n...
483
484
  	BUG_ON(nbd->sock);
  	BUG_ON(nbd->active_req);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
485

f4507164e   Wanlong Gao   nbd: rename the n...
486
487
  	while (!list_empty(&nbd->queue_head)) {
  		req = list_entry(nbd->queue_head.next, struct request,
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
488
489
490
  				 queuelist);
  		list_del_init(&req->queuelist);
  		req->errors++;
d18509f59   Markus Pargmann   nbd: Restructure ...
491
  		nbd_end_request(nbd, req);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
492
  	}
fded4e090   Paul Clements   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   Markus Pargmann   nbd: Restructure ...
499
  		nbd_end_request(nbd, req);
fded4e090   Paul Clements   nbd: clear waitin...
500
  	}
e78273c80   Markus Pargmann   nbd: Move clear q...
501
502
  	dev_dbg(disk_to_dev(nbd->disk), "queue cleared
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
  }
7fdfd4065   Paul Clements   NBD: allow hung n...
504

f4507164e   Wanlong Gao   nbd: rename the n...
505
  static void nbd_handle_req(struct nbd_device *nbd, struct request *req)
48cf6061b   Laurent Vivier   NBD: allow nbd to...
506
  {
33659ebba   Christoph Hellwig   block: remove wra...
507
  	if (req->cmd_type != REQ_TYPE_FS)
48cf6061b   Laurent Vivier   NBD: allow nbd to...
508
  		goto error_out;
9dc6c806b   Christoph Hellwig   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   Alex Bligh   nbd: support FLUS...
515
  	}
48cf6061b   Laurent Vivier   NBD: allow nbd to...
516
  	req->errors = 0;
f4507164e   Wanlong Gao   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   WANG Cong   nbd: replace prin...
521
522
  			"Attempted send on closed socket
  ");
15746fcaa   Pavel Machek   nbd: trivial clea...
523
  		goto error_out;
48cf6061b   Laurent Vivier   NBD: allow nbd to...
524
  	}
f4507164e   Wanlong Gao   nbd: rename the n...
525
  	nbd->active_req = req;
48cf6061b   Laurent Vivier   NBD: allow nbd to...
526

7e2893a16   Markus Pargmann   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   Wanlong Gao   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   Laurent Vivier   NBD: allow nbd to...
532
  		req->errors++;
d18509f59   Markus Pargmann   nbd: Restructure ...
533
  		nbd_end_request(nbd, req);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
534
  	} else {
f4507164e   Wanlong Gao   nbd: rename the n...
535
  		spin_lock(&nbd->queue_lock);
01ff5dbc0   Chetan Loke   block/nbd: micro-...
536
  		list_add_tail(&req->queuelist, &nbd->queue_head);
f4507164e   Wanlong Gao   nbd: rename the n...
537
  		spin_unlock(&nbd->queue_lock);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
538
  	}
f4507164e   Wanlong Gao   nbd: rename the n...
539
540
541
  	nbd->active_req = NULL;
  	mutex_unlock(&nbd->tx_lock);
  	wake_up_all(&nbd->active_wq);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
542
543
544
545
546
  
  	return;
  
  error_out:
  	req->errors++;
d18509f59   Markus Pargmann   nbd: Restructure ...
547
  	nbd_end_request(nbd, req);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
548
  }
cad73b270   Markus Pargmann   nbd: Rename funct...
549
  static int nbd_thread_send(void *data)
48cf6061b   Laurent Vivier   NBD: allow nbd to...
550
  {
f4507164e   Wanlong Gao   nbd: rename the n...
551
  	struct nbd_device *nbd = data;
48cf6061b   Laurent Vivier   NBD: allow nbd to...
552
  	struct request *req;
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
553
  	nbd->task_send = current;
8698a745d   Dongsheng Yang   sched, treewide: ...
554
  	set_user_nice(current, MIN_NICE);
f4507164e   Wanlong Gao   nbd: rename the n...
555
  	while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
48cf6061b   Laurent Vivier   NBD: allow nbd to...
556
  		/* wait for something to do */
f4507164e   Wanlong Gao   nbd: rename the n...
557
  		wait_event_interruptible(nbd->waiting_wq,
48cf6061b   Laurent Vivier   NBD: allow nbd to...
558
  					 kthread_should_stop() ||
f4507164e   Wanlong Gao   nbd: rename the n...
559
  					 !list_empty(&nbd->waiting_queue));
48cf6061b   Laurent Vivier   NBD: allow nbd to...
560
561
  
  		/* extract request */
f4507164e   Wanlong Gao   nbd: rename the n...
562
  		if (list_empty(&nbd->waiting_queue))
48cf6061b   Laurent Vivier   NBD: allow nbd to...
563
  			continue;
f4507164e   Wanlong Gao   nbd: rename the n...
564
565
  		spin_lock_irq(&nbd->queue_lock);
  		req = list_entry(nbd->waiting_queue.next, struct request,
48cf6061b   Laurent Vivier   NBD: allow nbd to...
566
567
  				 queuelist);
  		list_del_init(&req->queuelist);
f4507164e   Wanlong Gao   nbd: rename the n...
568
  		spin_unlock_irq(&nbd->queue_lock);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
569
570
  
  		/* handle request */
f4507164e   Wanlong Gao   nbd: rename the n...
571
  		nbd_handle_req(nbd, req);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
572
  	}
7e2893a16   Markus Pargmann   nbd: Fix timeout ...
573
574
  
  	nbd->task_send = NULL;
48cf6061b   Laurent Vivier   NBD: allow nbd to...
575
576
  	return 0;
  }
1da177e4c   Linus Torvalds   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   Wanlong Gao   nbd: rename the n...
580
   * if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
   *   { printk( "Warning: Ignoring result!
  "); nbd_end_request( req ); }
   */
cad73b270   Markus Pargmann   nbd: Rename funct...
584
  static void nbd_request_handler(struct request_queue *q)
398eb0855   Alex Elder   nbd: fix sparse w...
585
  		__releases(q->queue_lock) __acquires(q->queue_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
  {
  	struct request *req;
  	
9934c8c04   Tejun Heo   block: implement ...
589
  	while ((req = blk_fetch_request(q)) != NULL) {
f4507164e   Wanlong Gao   nbd: rename the n...
590
  		struct nbd_device *nbd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591

48cf6061b   Laurent Vivier   NBD: allow nbd to...
592
  		spin_unlock_irq(q->queue_lock);
f4507164e   Wanlong Gao   nbd: rename the n...
593
  		nbd = req->rq_disk->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

f4507164e   Wanlong Gao   nbd: rename the n...
595
  		BUG_ON(nbd->magic != NBD_MAGIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596

d18509f59   Markus Pargmann   nbd: Restructure ...
597
598
599
  		dev_dbg(nbd_to_dev(nbd), "request %p: dequeued (flags=%x)
  ",
  			req, req->cmd_type);
f4507164e   Wanlong Gao   nbd: rename the n...
600
  		if (unlikely(!nbd->sock)) {
da6ccaaa7   Dan Streetman   nbd: ratelimit er...
601
602
603
  			dev_err_ratelimited(disk_to_dev(nbd->disk),
  					    "Attempted send on closed socket
  ");
4d48a542b   Paul Clements   nbd: fix I/O hang...
604
  			req->errors++;
d18509f59   Markus Pargmann   nbd: Restructure ...
605
  			nbd_end_request(nbd, req);
4d48a542b   Paul Clements   nbd: fix I/O hang...
606
607
608
  			spin_lock_irq(q->queue_lock);
  			continue;
  		}
f4507164e   Wanlong Gao   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   Linus Torvalds   Linux-2.6.12-rc2
612

f4507164e   Wanlong Gao   nbd: rename the n...
613
  		wake_up(&nbd->waiting_wq);
4b2f0260c   Herbert Xu   [PATCH] nbd: fix ...
614

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  		spin_lock_irq(q->queue_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  }
23272a675   Markus Pargmann   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   Markus Pargmann   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   Markus Pargmann   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   Jens Axboe   nbd: switch to us...
666
  		blk_queue_write_cache(nbd->disk->queue, true, false);
d02cf5310   Markus Pargmann   nbd: Move flag pa...
667
  	else
aafb1eecb   Jens Axboe   nbd: switch to us...
668
  		blk_queue_write_cache(nbd->disk->queue, false, false);
d02cf5310   Markus Pargmann   nbd: Move flag pa...
669
  }
30d53d9c1   Markus Pargmann   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   Pavel Machek   nbd: add locking ...
672
  /* Must be called with tx_lock held */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673

f4507164e   Wanlong Gao   nbd: rename the n...
674
  static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
1a2ad2112   Pavel Machek   nbd: add locking ...
675
676
  		       unsigned int cmd, unsigned long arg)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
  	switch (cmd) {
1a2ad2112   Pavel Machek   nbd: add locking ...
678
679
  	case NBD_DISCONNECT: {
  		struct request sreq;
f4507164e   Wanlong Gao   nbd: rename the n...
680
681
  		dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT
  ");
3a2d63f87   Paolo Bonzini   nbd: fsync and ki...
682
683
  		if (!nbd->sock)
  			return -EINVAL;
1a2ad2112   Pavel Machek   nbd: add locking ...
684

3a2d63f87   Paolo Bonzini   nbd: fsync and ki...
685
686
687
  		mutex_unlock(&nbd->tx_lock);
  		fsync_bdev(bdev);
  		mutex_lock(&nbd->tx_lock);
4f54eec83   FUJITA Tomonori   block: use blk_rq...
688
  		blk_rq_init(NULL, &sreq);
4f8c9510b   Christoph Hellwig   block: rename REQ...
689
  		sreq.cmd_type = REQ_TYPE_DRV_PRIV;
3a2d63f87   Paolo Bonzini   nbd: fsync and ki...
690
691
  
  		/* Check again after getting mutex back.  */
f4507164e   Wanlong Gao   nbd: rename the n...
692
  		if (!nbd->sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  			return -EINVAL;
3a2d63f87   Paolo Bonzini   nbd: fsync and ki...
694

696697cb5   Markus Pargmann   nbd: Change 'disc...
695
  		nbd->disconnect = true;
c378f70ad   Paul Clements   nbd: correct disc...
696

f4507164e   Wanlong Gao   nbd: rename the n...
697
  		nbd_send_req(nbd, &sreq);
c378f70ad   Paul Clements   nbd: correct disc...
698
  		return 0;
1a2ad2112   Pavel Machek   nbd: add locking ...
699
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
   
23272a675   Markus Pargmann   nbd: Remove signa...
701
702
  	case NBD_CLEAR_SOCK:
  		sock_shutdown(nbd);
f4507164e   Wanlong Gao   nbd: rename the n...
703
704
  		nbd_clear_que(nbd);
  		BUG_ON(!list_empty(&nbd->queue_head));
fded4e090   Paul Clements   nbd: clear waitin...
705
  		BUG_ON(!list_empty(&nbd->waiting_queue));
3a2d63f87   Paolo Bonzini   nbd: fsync and ki...
706
  		kill_bdev(bdev);
1a2ad2112   Pavel Machek   nbd: add locking ...
707
  		return 0;
1a2ad2112   Pavel Machek   nbd: add locking ...
708
709
  
  	case NBD_SET_SOCK: {
e25115786   Al Viro   switch nbd to soc...
710
  		int err;
23272a675   Markus Pargmann   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   Pavel Machek   nbd: add locking ...
721
  	}
37091fdd8   Markus Pargmann   nbd: Create size ...
722
  	case NBD_SET_BLKSIZE: {
5e454c67f   Arnd Bergmann   nbd: use correct ...
723
  		loff_t bsize = div_s64(nbd->bytesize, arg);
37091fdd8   Markus Pargmann   nbd: Create size ...
724
725
726
  
  		return nbd_size_set(nbd, bdev, arg, bsize);
  	}
1a2ad2112   Pavel Machek   nbd: add locking ...
727

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  	case NBD_SET_SIZE:
37091fdd8   Markus Pargmann   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   Pavel Machek   nbd: add locking ...
734

7fdfd4065   Paul Clements   NBD: allow hung n...
735
  	case NBD_SET_TIMEOUT:
f4507164e   Wanlong Gao   nbd: rename the n...
736
  		nbd->xmit_timeout = arg * HZ;
7e2893a16   Markus Pargmann   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   Paul Clements   NBD: allow hung n...
742
  		return 0;
1a2ad2112   Pavel Machek   nbd: add locking ...
743

2f0125088   Paul Clements   nbd: add set flag...
744
745
746
  	case NBD_SET_FLAGS:
  		nbd->flags = arg;
  		return 0;
1a2ad2112   Pavel Machek   nbd: add locking ...
747
748
  	case NBD_DO_IT: {
  		struct task_struct *thread;
1a2ad2112   Pavel Machek   nbd: add locking ...
749
  		int error;
6521d39a6   Markus Pargmann   nbd: Remove varia...
750
  		if (nbd->task_recv)
c91192d66   Pavel Machek   nbd: do not allow...
751
  			return -EBUSY;
e25115786   Al Viro   switch nbd to soc...
752
  		if (!nbd->sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  			return -EINVAL;
1a2ad2112   Pavel Machek   nbd: add locking ...
754

f4507164e   Wanlong Gao   nbd: rename the n...
755
  		mutex_unlock(&nbd->tx_lock);
1a2ad2112   Pavel Machek   nbd: add locking ...
756

d02cf5310   Markus Pargmann   nbd: Move flag pa...
757
  		nbd_parse_flags(nbd, bdev);
a336d2987   Paul Clements   nbd: handle disca...
758

cad73b270   Markus Pargmann   nbd: Rename funct...
759
  		thread = kthread_run(nbd_thread_send, nbd, "%s",
30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
760
  				     nbd_name(nbd));
1a2ad2112   Pavel Machek   nbd: add locking ...
761
  		if (IS_ERR(thread)) {
f4507164e   Wanlong Gao   nbd: rename the n...
762
  			mutex_lock(&nbd->tx_lock);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
763
  			return PTR_ERR(thread);
1a2ad2112   Pavel Machek   nbd: add locking ...
764
  		}
d06df60b9   Markus Pargmann   nbd: Replace kthr...
765

30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
766
  		nbd_dev_dbg_init(nbd);
37091fdd8   Markus Pargmann   nbd: Create size ...
767
  		error = nbd_thread_recv(nbd, bdev);
30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
768
  		nbd_dev_dbg_close(nbd);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
769
  		kthread_stop(thread);
1a2ad2112   Pavel Machek   nbd: add locking ...
770

f4507164e   Wanlong Gao   nbd: rename the n...
771
  		mutex_lock(&nbd->tx_lock);
193918307   Markus Pargmann   nbd: Remove 'hard...
772

36e47bee7   Markus Pargmann   nbd: sock_shutdow...
773
  		sock_shutdown(nbd);
f4507164e   Wanlong Gao   nbd: rename the n...
774
  		nbd_clear_que(nbd);
3a2d63f87   Paolo Bonzini   nbd: fsync and ki...
775
  		kill_bdev(bdev);
0e4f0f6f6   Markus Pargmann   nbd: Cleanup rese...
776
  		nbd_bdev_reset(bdev);
c378f70ad   Paul Clements   nbd: correct disc...
777
  		if (nbd->disconnect) /* user requested, ignore socket errors */
1f7b5cf1b   Markus Pargmann   nbd: Timeouts are...
778
779
780
  			error = 0;
  		if (nbd->timedout)
  			error = -ETIMEDOUT;
0e4f0f6f6   Markus Pargmann   nbd: Cleanup rese...
781
  		nbd_reset(nbd);
193918307   Markus Pargmann   nbd: Remove 'hard...
782
  		return error;
1a2ad2112   Pavel Machek   nbd: add locking ...
783
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  	case NBD_CLEAR_QUE:
4b2f0260c   Herbert Xu   [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   Linus Torvalds   Linux-2.6.12-rc2
789
  		return 0;
1a2ad2112   Pavel Machek   nbd: add locking ...
790

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  	case NBD_PRINT_DEBUG:
f4507164e   Wanlong Gao   nbd: rename the n...
792
  		dev_info(disk_to_dev(nbd->disk),
5eedf5415   WANG Cong   nbd: replace some...
793
794
  			"next = %p, prev = %p, head = %p
  ",
f4507164e   Wanlong Gao   nbd: rename the n...
795
796
  			nbd->queue_head.next, nbd->queue_head.prev,
  			&nbd->queue_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
  		return 0;
  	}
1a2ad2112   Pavel Machek   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   Wanlong Gao   nbd: rename the n...
805
  	struct nbd_device *nbd = bdev->bd_disk->private_data;
1a2ad2112   Pavel Machek   nbd: add locking ...
806
807
808
809
  	int error;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
f4507164e   Wanlong Gao   nbd: rename the n...
810
  	BUG_ON(nbd->magic != NBD_MAGIC);
1a2ad2112   Pavel Machek   nbd: add locking ...
811

f4507164e   Wanlong Gao   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   Pavel Machek   nbd: add locking ...
815
816
  
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
  }
83d5cde47   Alexey Dobriyan   const: make block...
818
  static const struct block_device_operations nbd_fops =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
  {
  	.owner =	THIS_MODULE,
8a6cfeb6d   Arnd Bergmann   block: push down ...
821
  	.ioctl =	nbd_ioctl,
263a3df18   Al Viro   nbd: use ->compat...
822
  	.compat_ioctl =	nbd_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  };
30d53d9c1   Markus Pargmann   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   Markus Pargmann   nbd: Fix debugfs ...
895
896
897
  
  	if (!nbd_dbg_dir)
  		return -EIO;
30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
898
899
  
  	dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
27ea43fe2   Markus Pargmann   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   Markus Pargmann   nbd: Add debugfs ...
905
906
  	}
  	nbd->dbg_dir = dir;
27ea43fe2   Markus Pargmann   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   Josef Bacik   nbd: pass the nbd...
911
  	debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops);
30d53d9c1   Markus Pargmann   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   Markus Pargmann   nbd: Fix debugfs ...
926
927
  	if (!dbg_dir)
  		return -EIO;
30d53d9c1   Markus Pargmann   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   Linus Torvalds   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   Laurent Vivier   NBD: add partitio...
969
  	int part_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970

5b7b18ccd   Adrian Bunk   [PATCH] drivers/b...
971
  	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972

d71a6d733   Laurent Vivier   NBD: add partitio...
973
  	if (max_part < 0) {
7742ce4ab   WANG Cong   nbd: lower the lo...
974
975
  		printk(KERN_ERR "nbd: max_part must be >= 0
  ");
d71a6d733   Laurent Vivier   NBD: add partitio...
976
977
978
979
  		return -EINVAL;
  	}
  
  	part_shift = 0;
5988ce239   Namhyung Kim   nbd: adjust 'max_...
980
  	if (max_part > 0) {
d71a6d733   Laurent Vivier   NBD: add partitio...
981
  		part_shift = fls(max_part);
5988ce239   Namhyung Kim   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   Namhyung Kim   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   Sudip Mukherjee   nbd: fix possible...
997
998
999
  	nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
  	if (!nbd_dev)
  		return -ENOMEM;
40be0c28b   Lars Marowsky-Bree   [PATCH] nbd: Don'...
1000
  	for (i = 0; i < nbds_max; i++) {
d71a6d733   Laurent Vivier   NBD: add partitio...
1001
  		struct gendisk *disk = alloc_disk(1 << part_shift);
1da177e4c   Linus Torvalds   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   Markus Pargmann   nbd: Rename funct...
1010
  		disk->queue = blk_init_queue(nbd_request_handler, &nbd_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
1012
1013
1014
  		if (!disk->queue) {
  			put_disk(disk);
  			goto out;
  		}
31dcfab0a   Jens Axboe   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   Mike Snitzer   block: disable en...
1019
  		queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, disk->queue);
a336d2987   Paul Clements   nbd: handle disca...
1020
  		disk->queue->limits.discard_granularity = 512;
2bb4cd5cc   Jens Axboe   block: have drive...
1021
  		blk_queue_max_discard_sectors(disk->queue, UINT_MAX);
a336d2987   Paul Clements   nbd: handle disca...
1022
  		disk->queue->limits.discard_zeroes_data = 0;
078be02b8   Michal Belczyk   nbd: increase def...
1023
1024
  		blk_queue_max_hw_sectors(disk->queue, 65536);
  		disk->queue->limits.max_sectors = 256;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
1034

30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
1035
  	nbd_dbg_init();
40be0c28b   Lars Marowsky-Bree   [PATCH] nbd: Don'...
1036
  	for (i = 0; i < nbds_max; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  		struct gendisk *disk = nbd_dev[i].disk;
f4507164e   Wanlong Gao   nbd: rename the n...
1038
  		nbd_dev[i].magic = NBD_MAGIC;
48cf6061b   Laurent Vivier   NBD: allow nbd to...
1039
  		INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  		spin_lock_init(&nbd_dev[i].queue_lock);
23272a675   Markus Pargmann   nbd: Remove signa...
1041
  		spin_lock_init(&nbd_dev[i].sock_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
  		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
82d4dc5ad   Ingo Molnar   [PATCH] sem2mutex...
1043
  		mutex_init(&nbd_dev[i].tx_lock);
7e2893a16   Markus Pargmann   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   Herbert Xu   [PATCH] nbd: fix ...
1047
  		init_waitqueue_head(&nbd_dev[i].active_wq);
48cf6061b   Laurent Vivier   NBD: allow nbd to...
1048
  		init_waitqueue_head(&nbd_dev[i].waiting_wq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
  		disk->major = NBD_MAJOR;
d71a6d733   Laurent Vivier   NBD: add partitio...
1050
  		disk->first_minor = i << part_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
  		disk->fops = &nbd_fops;
  		disk->private_data = &nbd_dev[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  		sprintf(disk->disk_name, "nbd%d", i);
0e4f0f6f6   Markus Pargmann   nbd: Cleanup rese...
1054
  		nbd_reset(&nbd_dev[i]);
1da177e4c   Linus Torvalds   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   Sven Wegener   nbd: fix memory l...
1064
  	kfree(nbd_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
1067
1068
1069
1070
  	return err;
  }
  
  static void __exit nbd_cleanup(void)
  {
  	int i;
30d53d9c1   Markus Pargmann   nbd: Add debugfs ...
1071
1072
  
  	nbd_dbg_close();
40be0c28b   Lars Marowsky-Bree   [PATCH] nbd: Don'...
1073
  	for (i = 0; i < nbds_max; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
  		struct gendisk *disk = nbd_dev[i].disk;
40be0c28b   Lars Marowsky-Bree   [PATCH] nbd: Don'...
1075
  		nbd_dev[i].magic = 0;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
1082
  	unregister_blkdev(NBD_MAJOR, "nbd");
f3944d61d   Sven Wegener   nbd: fix memory l...
1083
  	kfree(nbd_dev);
1da177e4c   Linus Torvalds   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   Lars Marowsky-Bree   [PATCH] nbd: Don'...
1093
  module_param(nbds_max, int, 0444);
d71a6d733   Laurent Vivier   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)");