1 diff -urN linux-2.6.9/drivers/block/Kconfig linux-2.6.9-patched/drivers/block/Kconfig
2 --- linux-2.6.9/drivers/block/Kconfig 2004-10-18 16:53:43.000000000 -0500
3 +++ linux-2.6.9-patched/drivers/block/Kconfig 2004-10-22 13:27:52.938836304 -0500
5 your machine, or if you want to have a raid or loopback device
6 bigger than 2TB. Otherwise say N.
9 + tristate "Global network block device support"
15 source "drivers/s390/block/Kconfig"
18 diff -urN linux-2.6.9/drivers/block/Makefile linux-2.6.9-patched/drivers/block/Makefile
19 --- linux-2.6.9/drivers/block/Makefile 2004-10-18 16:54:55.000000000 -0500
20 +++ linux-2.6.9-patched/drivers/block/Makefile 2004-10-22 13:30:48.224188880 -0500
22 obj-$(CONFIG_VIODASD) += viodasd.o
23 obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
24 obj-$(CONFIG_BLK_DEV_UB) += ub.o
26 +obj-$(CONFIG_BLK_DEV_GNBD) += gnbd.o
27 diff -urN linux-2.6.9/drivers/block/gnbd.c linux-2.6.9-patched/drivers/block/gnbd.c
28 --- linux-2.6.9/drivers/block/gnbd.c 1969-12-31 18:00:00.000000000 -0600
29 +++ linux-2.6.9-patched/drivers/block/gnbd.c 2004-10-22 13:43:33.303879088 -0500
31 +/******************************************************************************
32 +*******************************************************************************
34 +** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
35 +** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
37 +** This copyrighted material is made available to anyone wishing to use,
38 +** modify, copy, or redistribute it subject to the terms and conditions
39 +** of the GNU General Public License v.2.
41 +*******************************************************************************
42 +******************************************************************************/
44 +/* Large chunks of this code were lifted from nbd.c */
46 +#include <linux/major.h>
48 +#include <linux/blkdev.h>
49 +#include <linux/module.h>
50 +#include <linux/init.h>
51 +#include <linux/sched.h>
52 +#include <linux/fs.h>
53 +#include <linux/bio.h>
54 +#include <linux/stat.h>
55 +#include <linux/errno.h>
56 +#include <linux/file.h>
57 +#include <linux/ioctl.h>
58 +#include <net/sock.h>
59 +#include <linux/in.h>
60 +#include <linux/buffer_head.h>
61 +#include <linux/miscdevice.h>
63 +#include <linux/devfs_fs_kernel.h>
65 +#include <asm/uaccess.h>
66 +#include <asm/types.h>
68 +#include <linux/gnbd.h>
70 +static int major_nr = 0;
71 +uint64_t insmod_time;
74 +#define GNBD_MAGIC 0x74d06100
77 +#define dprintk(flags, fmt...)
79 +#define dprintk(flags, fmt...) do { \
80 + if (debugflags & (flags)) printk(KERN_DEBUG fmt); \
82 +#define DBG_IOCTL 0x0004
83 +#define DBG_INIT 0x0010
84 +#define DBG_EXIT 0x0020
85 +#define DBG_BLKDEV 0x0100
86 +#define DBG_RX 0x0200
87 +#define DBG_TX 0x0400
88 +static unsigned int debugflags;
91 +static struct gnbd_device gnbd_dev[MAX_GNBD];
93 +struct request shutdown_req;
94 +struct request ping_req;
96 +static spinlock_t gnbd_lock = SPIN_LOCK_UNLOCKED;
98 +#define to_gnbd_dev(d) container_of(d, struct gnbd_device, class_dev)
100 +static void gnbd_class_release(struct class_device *class_dev)
102 + printk("releasing gnbd class\n");
103 + /* FIXME -- What the hell do I have to free up here */
106 +static struct class gnbd_class = {
108 + .release = gnbd_class_release
112 +static ssize_t show_pid(struct class_device *class_dev, char *buf)
114 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
115 + return sprintf(buf, "%d\n", dev->receiver_pid);
118 +static CLASS_DEVICE_ATTR(pid, S_IRUGO, show_pid, NULL);
120 +static ssize_t show_server(struct class_device *class_dev, char *buf)
122 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
123 + if (dev->server_name)
124 + return sprintf(buf, "%s/%hx\n", dev->server_name,
127 + return sprintf(buf, "\n");
130 +/* FIXME -- should a empty store free the memory */
131 +static ssize_t store_server(struct class_device *class_dev,
132 + const char *buf, size_t count)
135 + short unsigned int port;
137 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
138 + if (down_trylock(&dev->do_it_lock))
140 + if (dev->server_name)
141 + kfree(dev->server_name);
142 + dev->server_name = kmalloc(count + 1, GFP_KERNEL);
143 + if (!dev->server_name)
145 + memcpy(dev->server_name, buf, count);
146 + dev->server_name[count] = 0;
147 + ptr = strchr(dev->server_name, '/');
151 + res = sscanf(ptr, "%4hx", &port);
153 + up(&dev->do_it_lock);
156 + dev->server_port = port;
157 + up(&dev->do_it_lock);
161 +CLASS_DEVICE_ATTR(server, S_IRUGO | S_IWUSR, show_server, store_server);
163 +static ssize_t show_name(struct class_device *class_dev, char *buf)
165 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
166 + return sprintf(buf, "%s\n", dev->name);
169 +static ssize_t store_name(struct class_device *class_dev,
170 + const char *buf, size_t count)
173 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
174 + if (down_trylock(&dev->do_it_lock))
176 + res = sscanf(buf, "%31s", dev->name);
177 + up(&dev->do_it_lock);
183 +CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_name, store_name);
186 +static ssize_t show_sectors(struct class_device *class_dev, char *buf)
188 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
189 + return sprintf(buf, "%Lu\n",
190 + (unsigned long long)get_capacity(dev->disk));
193 +static ssize_t store_sectors(struct class_device *class_dev,
194 + const char *buf, size_t count)
198 + struct block_device *bdev;
199 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
201 + if (down_trylock(&dev->do_it_lock))
203 + res = sscanf(buf, "%Lu\n", &size);
205 + up(&dev->do_it_lock);
208 + /* FIXME -- should I switch the order here, so that I don't have
209 + capacity set to one thing and the bdev inode size set to another */
210 + set_capacity(dev->disk, size);
211 + bdev = bdget_disk(dev->disk, 0);
213 + down(&bdev->bd_inode->i_sem);
214 + i_size_write(bdev->bd_inode, (loff_t)size << 9);
215 + up(&bdev->bd_inode->i_sem);
218 + up(&dev->do_it_lock);
222 +CLASS_DEVICE_ATTR(sectors, S_IRUGO | S_IWUSR, show_sectors, store_sectors);
224 +static ssize_t show_usage(struct class_device *class_dev, char *buf)
226 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
227 + return sprintf(buf, "%d\n", dev->open_count);
230 +CLASS_DEVICE_ATTR(usage, S_IRUGO, show_usage, NULL);
232 +static ssize_t show_flags(struct class_device *class_dev, char *buf)
234 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
235 + return sprintf(buf, "0x%04x\n", dev->flags);
238 +static ssize_t store_flags(struct class_device *class_dev,
239 + const char *buf, size_t count)
243 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
244 + if (down_trylock(&dev->do_it_lock))
246 + res = sscanf(buf, "0x%hx", &dev->flags);
247 + up(&dev->do_it_lock);
254 +CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
256 +static ssize_t show_waittime(struct class_device *class_dev, char *buf)
258 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
259 + if (list_empty(&dev->queue_head))
260 + return sprintf(buf, "-1\n");
261 + return sprintf(buf, "%ld\n",
262 + ((long)jiffies - (long)dev->last_received) / HZ);
265 +CLASS_DEVICE_ATTR(waittime, S_IRUGO, show_waittime, NULL);
267 +static ssize_t show_connected(struct class_device *class_dev, char *buf)
269 + struct gnbd_device *dev = to_gnbd_dev(class_dev);
270 + return sprintf(buf, "%d\n", (dev->sock != NULL));
273 +CLASS_DEVICE_ATTR(connected, S_IRUGO, show_connected, NULL);
276 +static const char *ioctl_cmd_to_ascii(int cmd)
279 + case GNBD_DO_IT: return "do-it";
280 + case GNBD_CLEAR_QUE: return "clear-que";
281 + case GNBD_PRINT_DEBUG: return "print-debug";
282 + case GNBD_DISCONNECT: return "disconnect";
287 +static const char *gnbdcmd_to_ascii(int cmd)
290 + case GNBD_CMD_READ: return "read";
291 + case GNBD_CMD_WRITE: return "write";
292 + case GNBD_CMD_DISC: return "disconnect";
293 + case GNBD_CMD_PING: return "ping";
299 +static void gnbd_end_request(struct request *req)
301 + int uptodate = (req->errors == 0) ? 1 : 0;
302 + request_queue_t *q = req->q;
303 + unsigned long flags;
305 + dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
306 + req, uptodate? "done": "failed");
309 + printk("%s %d called gnbd_end_request with and error\n",
310 + current->comm, current->pid);
312 + spin_lock_irqsave(q->queue_lock, flags);
313 + if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
314 + end_that_request_last(req);
316 + spin_unlock_irqrestore(q->queue_lock, flags);
320 + * Send or receive packet.
322 +static int sock_xmit(struct socket *sock, int send, void *buf, int size,
325 + mm_segment_t oldfs;
329 + unsigned long flags;
334 + /* Allow interception of SIGKILL only
335 + * Don't allow other signals to interrupt the transmission */
336 + spin_lock_irqsave(¤t->sighand->siglock, flags);
337 + oldset = current->blocked;
338 + sigfillset(¤t->blocked);
339 + sigdelsetmask(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGTERM) |
341 + recalc_sigpending();
342 + spin_unlock_irqrestore(¤t->sighand->siglock, flags);
345 + sock->sk->sk_allocation = GFP_NOIO;
346 + iov.iov_base = buf;
347 + iov.iov_len = size;
348 + msg.msg_name = NULL;
349 + msg.msg_namelen = 0;
350 + msg.msg_iov = &iov;
351 + msg.msg_iovlen = 1;
352 + msg.msg_control = NULL;
353 + msg.msg_controllen = 0;
354 + msg.msg_namelen = 0;
355 + msg.msg_flags = msg_flags | MSG_NOSIGNAL;
358 + result = sock_sendmsg(sock, &msg, size);
360 + result = sock_recvmsg(sock, &msg, size, 0);
362 + if (signal_pending(current)) {
364 + spin_lock_irqsave(¤t->sighand->siglock, flags);
365 + printk(KERN_WARNING "gnbd (pid %d: %s) got signal %d\n",
366 + current->pid, current->comm,
367 + dequeue_signal(current, ¤t->blocked, &info));
368 + spin_unlock_irqrestore(¤t->sighand->siglock, flags);
375 + result = -EPIPE; /* short read */
380 + } while (size > 0);
382 + spin_lock_irqsave(¤t->sighand->siglock, flags);
383 + current->blocked = oldset;
384 + recalc_sigpending();
385 + spin_unlock_irqrestore(¤t->sighand->siglock, flags);
391 +static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
395 + void *kaddr = kmap(bvec->bv_page);
396 + result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
398 + kunmap(bvec->bv_page);
403 +#define gnbd_send_req(dev, req) __gnbd_send_req((dev), (dev)->sock, (req))
405 +int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock,
406 + struct request *req)
408 + int result, i, flags;
409 + struct gnbd_request request;
410 + unsigned long size = req->nr_sectors << 9;
412 + request.magic = htonl(GNBD_REQUEST_MAGIC);
413 + request.type = htonl(gnbd_cmd(req));
414 + request.from = cpu_to_be64((u64) req->sector << 9);
415 + request.len = htonl(size);
416 + memcpy(request.handle, &req, sizeof(req));
418 + down(&dev->tx_lock);
421 + printk(KERN_ERR "%s: Attempted send on closed socket\n",
422 + dev->disk->disk_name);
423 + result = -ENOTCONN;
427 + dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
428 + dev->disk->disk_name, req,
429 + gnbdcmd_to_ascii(gnbd_cmd(req)),
430 + (unsigned long long)req->sector << 9,
431 + req->nr_sectors << 9);
432 + result = sock_xmit(sock, 1, &request, sizeof(request),
433 + (gnbd_cmd(req) == GNBD_CMD_WRITE)? MSG_MORE: 0);
435 + printk(KERN_ERR "%s: Send control failed (result %d)\n",
436 + dev->disk->disk_name, result);
440 + if (gnbd_cmd(req) == GNBD_CMD_WRITE) {
443 + * we are really probing at internals to determine
444 + * whether to set MSG_MORE or not...
446 + rq_for_each_bio(bio, req) {
447 + struct bio_vec *bvec;
448 + bio_for_each_segment(bvec, bio, i) {
450 + if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
452 + dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
453 + dev->disk->disk_name, req,
455 + result = sock_send_bvec(sock, bvec, flags);
457 + printk(KERN_ERR "%s: Send data failed (result %d)\n",
458 + dev->disk->disk_name,
474 +static int gnbd_find_request(struct gnbd_device *dev, struct request *xreq)
476 + struct request *req;
477 + struct list_head *tmp;
479 + list_for_each(tmp, &dev->queue_head) {
480 + req = list_entry(tmp, struct request, queuelist);
488 +static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
491 + void *kaddr = kmap(bvec->bv_page);
492 + result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
494 + kunmap(bvec->bv_page);
498 +int gnbd_recv_req(struct gnbd_device *dev, struct request *req)
503 + rq_for_each_bio(bio, req) {
504 + struct bio_vec *bvec;
505 + bio_for_each_segment(bvec, bio, i) {
506 + result = sock_recv_bvec(dev->sock, bvec);
508 + printk(KERN_ERR "%s: Receive data failed (result %d)\n",
509 + dev->disk->disk_name,
513 + dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
514 + dev->disk->disk_name, req, bvec->bv_len);
520 +int gnbd_do_it(struct gnbd_device *dev)
523 + struct gnbd_reply reply;
524 + struct request *req;
525 + struct socket *sock = dev->sock;
527 + BUG_ON(dev->magic != GNBD_MAGIC);
529 + while((result = sock_xmit(sock, 0, &reply,sizeof(reply), MSG_WAITALL)) > 0){
530 + if (ntohl(reply.magic) == GNBD_KEEP_ALIVE_MAGIC)
531 + /* FIXME -- I should reset the wait time here */
534 + memcpy(&req, reply.handle, sizeof(req));
535 + if (req == &shutdown_req)
538 + if (!gnbd_find_request(dev, req)){
539 + printk(KERN_ERR "%s: Unexpected reply (%p)\n",
540 + dev->disk->disk_name, reply.handle);
543 + if (ntohl(reply.magic) != GNBD_REPLY_MAGIC) {
544 + printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
545 + dev->disk->disk_name,
546 + (unsigned long)ntohl(reply.magic));
549 + if (ntohl(reply.error)) {
550 + printk(KERN_ERR "%s: Other side returned error (%d)\n",
551 + dev->disk->disk_name, ntohl(reply.error));
555 + dprintk(DBG_RX, "%s: request %p: got reply\n",
556 + dev->disk->disk_name, req);
558 + if (gnbd_cmd(req) == GNBD_CMD_READ){
559 + result = gnbd_recv_req(dev, req);
564 + spin_lock(&dev->queue_lock);
565 + list_del_init(&req->queuelist);
566 + dev->last_received = jiffies;
567 + spin_unlock(&dev->queue_lock);
568 + if (req != &ping_req)
569 + gnbd_end_request(req);
571 + printk(KERN_ERR "%s: Receive control failed (result %d)\n",
572 + dev->disk->disk_name, result);
576 +void gnbd_clear_que(struct gnbd_device *dev)
578 + struct request *req;
580 + BUG_ON(dev->magic != GNBD_MAGIC);
584 + if (!list_empty(&dev->queue_head)) {
585 + req = list_entry(dev->queue_head.next, struct request, queuelist);
586 + list_del_init(&req->queuelist);
588 + if (req && req != &ping_req) {
590 + gnbd_end_request(req);
596 + * We always wait for result of write, for now. It would be nice to make it optional
598 + * if ((req->cmd == WRITE) && (dev->flags & GNBD_WRITE_NOCHK))
599 + * { printk( "Warning: Ignoring result!\n"); gnbd_end_request( req ); }
602 +static void do_gnbd_request(request_queue_t * q)
605 + struct request *req;
607 + while ((req = elv_next_request(q)) != NULL) {
608 + struct gnbd_device *dev;
610 + blkdev_dequeue_request(req);
611 + dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
612 + req->rq_disk->disk_name, req, req->flags);
614 + if (!(req->flags & REQ_CMD))
617 + dev = req->rq_disk->private_data;
619 + if (dev->receiver_pid == -1)
622 + BUG_ON(dev->magic != GNBD_MAGIC);
624 + gnbd_cmd(req) = GNBD_CMD_READ;
625 + if (rq_data_dir(req) == WRITE) {
626 + gnbd_cmd(req) = GNBD_CMD_WRITE;
627 + if (dev->flags & GNBD_READ_ONLY) {
628 + printk(KERN_ERR "%s: Write on read-only\n",
629 + dev->disk->disk_name);
635 + spin_unlock_irq(q->queue_lock);
637 + spin_lock(&dev->queue_lock);
639 + if (list_empty(&dev->queue_head))
640 + dev->last_received = jiffies;
641 + list_add(&req->queuelist, &dev->queue_head);
642 + spin_unlock(&dev->queue_lock);
644 + err = gnbd_send_req(dev, req);
646 + spin_lock_irq(q->queue_lock);
653 + spin_unlock(q->queue_lock);
654 + gnbd_end_request(req);
655 + spin_lock(q->queue_lock);
664 + * This is called before dev-sock is set, so you dodn't need
665 + * to worry about the tx_lock or the queue_lock
667 +static int gnbd_resend_requests(struct gnbd_device *dev, struct socket *sock)
670 + struct request *req;
671 + struct list_head *tmp;
673 + printk("resending requests\n");
674 + list_for_each(tmp, &dev->queue_head) {
675 + req = list_entry(tmp, struct request, queuelist);
676 + err = __gnbd_send_req(dev, sock, req);
679 + printk("failed trying to resend request (%d)\n", err);
687 +static int get_server_info(struct gnbd_device *dev, struct socket *sock)
689 + struct sockaddr_in server;
693 + err = sock->ops->getname(sock, (struct sockaddr *) &server, &len, 1);
695 + printk(KERN_WARNING "cannot get socket info, shutting down\n");
697 + dev->server_addr = server.sin_addr;
698 + dev->server_port = server.sin_port;
704 +static int gnbd_ctl_ioctl(struct inode *inode, struct file *file,
705 + unsigned int cmd, unsigned long arg)
707 + struct gnbd_device *dev = NULL;
708 + struct block_device *bdev;
712 + if (!capable(CAP_SYS_ADMIN))
715 + if (cmd == GNBD_DISCONNECT || cmd == GNBD_CLEAR_QUE ||
716 + cmd == GNBD_PING || cmd == GNBD_PRINT_DEBUG) {
717 + if (arg >= MAX_GNBD)
719 + dev = &gnbd_dev[arg];
720 + BUG_ON(dev->magic != GNBD_MAGIC);
723 + /* Anyone capable of this syscall can do *real bad* things */
724 + dprintk(DBG_IOCTL, "%s: gnbd_ioctl cmd=%s(0x%x) arg=%lu\n",
725 + dev->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
728 + case GNBD_DISCONNECT:
729 + printk(KERN_INFO "%s: GNBD_DISCONNECT\n", dev->disk->disk_name);
730 + spin_lock(&dev->open_lock);
731 + if (dev->open_count > 0){
732 + spin_unlock(&dev->open_lock);
735 + dev->receiver_pid = -1;
736 + spin_unlock(&dev->open_lock);
737 + /* There is no one using the device, you can disconnect it */
738 + if (dev->sock == NULL)
740 + gnbd_send_req(dev, &shutdown_req);
742 + case GNBD_CLEAR_QUE:
743 + if (down_interruptible(&dev->do_it_lock))
745 + dev->receiver_pid = -1;
746 + gnbd_clear_que(dev);
749 + blk_run_queue(dev->disk->queue);
751 + invalidate_bdev(bdev, 0);
753 + up(&dev->do_it_lock);
756 + if (copy_from_user(&req, (do_it_req_t *)arg, sizeof(req)))
758 + if (req.minor >= 128)
760 + dev = &gnbd_dev[req.minor];
761 + BUG_ON(dev->magic != GNBD_MAGIC);
765 + file = fget(req.sock_fd);
768 + inode = file->f_dentry->d_inode;
769 + if (!inode->i_sock) {
773 + if (down_trylock(&dev->do_it_lock)){
777 + error = gnbd_resend_requests(dev, SOCKET_I(inode));
779 + printk("quitting NBD_DO_IT\n");
780 + up(&dev->do_it_lock);
785 + dev->sock = SOCKET_I(inode);
786 + dev->receiver_pid = current->pid;
787 + blk_run_queue(dev->disk->queue);
788 + error = gnbd_do_it(dev);
789 + /* should I kill the socket first */
790 + up(&dev->do_it_lock);
791 + down(&dev->tx_lock);
793 + printk(KERN_WARNING "%s: shutting down socket\n",
794 + dev->disk->disk_name);
795 + dev->sock->ops->shutdown(dev->sock,
796 + SEND_SHUTDOWN|RCV_SHUTDOWN);
804 + printk("exitting GNBD_DO_IT ioctl\n");
807 + /* FIXME -- should I allow pings if everything is compeletely
809 + spin_lock(&dev->queue_lock);
810 + /* only one outstanding ping at a time */
811 + if (list_empty(&ping_req.queuelist)){
812 + if (list_empty(&dev->queue_head))
813 + dev->last_received = jiffies;
814 + list_add(&ping_req.queuelist, &dev->queue_head);
816 + spin_unlock(&dev->queue_lock);
817 + gnbd_send_req(dev, &ping_req); /* ignore the errors */
819 + case GNBD_PRINT_DEBUG:
820 + printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
821 + dev->disk->disk_name,
822 + dev->queue_head.next, dev->queue_head.prev,
825 + case GNBD_GET_TIME:
826 + if (copy_to_user((void *)arg, &insmod_time, sizeof(uint64_t))){
827 + printk(KERN_WARNING "couldn't compy time argument to user\n");
832 + /* FIXME -- should I print something, is EINVAL the right error */
836 +static int gnbd_open(struct inode *inode, struct file *file)
838 + struct gnbd_device *dev = inode->i_bdev->bd_disk->private_data;
839 + spin_lock(&dev->open_lock);
840 + if (dev->receiver_pid == -1){
841 + spin_unlock(&dev->open_lock);
844 + spin_unlock(&dev->open_lock);
845 + if ((file->f_mode & FMODE_WRITE) && (dev->flags & GNBD_READ_ONLY)){
846 + printk(KERN_INFO "cannot open read only gnbd device read/write");
851 + dev->bdev = inode->i_bdev;
855 +/* FIXME -- I don't sync the device at close. This means that If you write
856 + * something, and close the device, and expect that then it is written,
857 + * you are wrong.... This might cause problems */
858 +static int gnbd_release(struct inode *inode, struct file *file)
860 + struct gnbd_device *dev = inode->i_bdev->bd_disk->private_data;
863 + if (dev->open_count == 0)
868 +static struct file_operations _gnbd_ctl_fops =
870 + .ioctl = gnbd_ctl_ioctl,
871 + .owner = THIS_MODULE,
874 +static struct miscdevice _gnbd_misc =
876 + .minor = MISC_DYNAMIC_MINOR,
877 + .name = "gnbd_ctl",
878 + .devfs_name = "gnbd_ctl",
879 + .fops = &_gnbd_ctl_fops
882 +/* FIXME -- I should probably do more here */
883 +int __init gnbd_ctl_init(void)
887 + err = misc_register(&_gnbd_misc);
889 + printk("cannot register control device\n");
895 +void gnbd_ctl_cleanup(void)
897 + if (misc_deregister(&_gnbd_misc) < 0)
898 + printk("cannot deregister control device\n");
901 +static struct block_device_operations gnbd_fops =
904 + .release = gnbd_release,
905 + .owner = THIS_MODULE,
909 + * And here should be modules and kernel interface
910 + * (Just smiley confuses emacs :-)
913 +static int __init gnbd_init(void)
919 + if (sizeof(struct gnbd_request) != 28) {
920 + printk(KERN_CRIT "gnbd: sizeof gnbd_request needs to be 28 in order to work!\n" );
923 + shutdown_req.flags = REQ_SPECIAL;
924 + gnbd_cmd(&shutdown_req) = GNBD_CMD_DISC;
925 + shutdown_req.sector = 0;
926 + shutdown_req.nr_sectors = 0;
928 + ping_req.flags = REQ_SPECIAL;
929 + gnbd_cmd(&ping_req) = GNBD_CMD_PING;
930 + ping_req.sector = 0;
931 + ping_req.nr_sectors = 0;
933 + for (i = 0; i < MAX_GNBD; i++) {
934 + struct gendisk *disk = alloc_disk(1);
937 + gnbd_dev[i].disk = disk;
939 + * The new linux 2.5 block layer implementation requires
940 + * every gendisk to have its very own request_queue struct.
941 + * These structs are big so we dynamically allocate them.
943 + disk->queue = blk_init_queue(do_gnbd_request, &gnbd_lock);
944 + if (!disk->queue) {
949 + major_nr = register_blkdev(major_nr, "gnbd");
950 + if (major_nr < 0) {
951 + printk("gnbd: unable to get a major number\n");
956 + printk(KERN_INFO "gnbd: registered device at major %d\n", major_nr);
957 + dprintk(DBG_INIT, "gnbd: debugflags=0x%x\n", debugflags);
959 + devfs_mk_dir("gnbd_minor");
960 + err = class_register(&gnbd_class);
962 + goto out_unregister;
963 + for (i = 0; i < MAX_GNBD; i++) {
964 + struct gendisk *disk = gnbd_dev[i].disk;
965 + gnbd_dev[i].file = NULL;
966 + gnbd_dev[i].magic = GNBD_MAGIC;
967 + gnbd_dev[i].flags = 0;
968 + gnbd_dev[i].open_count = 0;
969 + gnbd_dev[i].receiver_pid = -1;
970 + gnbd_dev[i].server_name = NULL;
971 + gnbd_dev[i].server_port = 0;
972 + gnbd_dev[i].name[0] = '\0';
973 + gnbd_dev[i].bdev = NULL;
974 + spin_lock_init(&gnbd_dev[i].queue_lock);
975 + spin_lock_init(&gnbd_dev[i].open_lock);
976 + INIT_LIST_HEAD(&gnbd_dev[i].queue_head);
977 + init_MUTEX(&gnbd_dev[i].tx_lock);
978 + init_MUTEX(&gnbd_dev[i].do_it_lock);
979 + gnbd_dev[i].class_dev.class = &gnbd_class;
980 + sprintf(gnbd_dev[i].class_dev.class_id, "gnbd%d", i);
981 + err = class_device_register(&gnbd_dev[i].class_dev);
983 + printk("class_device_register failed with %d\n", err);
984 + goto out_unregister_class;
986 + if(class_device_create_file(&gnbd_dev[i].class_dev,
987 + &class_device_attr_pid))
988 + goto out_remove_file;
989 + if(class_device_create_file(&gnbd_dev[i].class_dev,
990 + &class_device_attr_server))
991 + goto out_remove_file;
992 + if(class_device_create_file(&gnbd_dev[i].class_dev,
993 + &class_device_attr_name))
994 + goto out_remove_file;
995 + if(class_device_create_file(&gnbd_dev[i].class_dev,
996 + &class_device_attr_sectors))
997 + goto out_remove_file;
998 + if(class_device_create_file(&gnbd_dev[i].class_dev,
999 + &class_device_attr_usage))
1000 + goto out_remove_file;
1001 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1002 + &class_device_attr_flags))
1003 + goto out_remove_file;
1004 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1005 + &class_device_attr_waittime))
1006 + goto out_remove_file;
1007 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1008 + &class_device_attr_connected))
1009 + goto out_remove_file;
1010 + disk->major = major_nr;
1011 + disk->first_minor = i;
1012 + disk->fops = &gnbd_fops;
1013 + disk->private_data = &gnbd_dev[i];
1014 + sprintf(disk->disk_name, "gnbd%d", i);
1015 + sprintf(disk->devfs_name, "gnbd_minor/%d", i);
1016 + set_capacity(disk, 0);
1018 + if(sysfs_create_link(&gnbd_dev[i].class_dev.kobj,
1019 + &gnbd_dev[i].disk->kobj, "block"))
1020 + goto out_remove_disk;
1024 + err = gnbd_ctl_init();
1026 + goto out_unregister_class;
1028 + insmod_time = (uint64_t) tv.tv_sec * 1000000 + tv.tv_usec;
1032 + del_gendisk(gnbd_dev[i].disk);
1034 + class_device_unregister(&gnbd_dev[i].class_dev);
1035 +out_unregister_class:
1037 + del_gendisk(gnbd_dev[i].disk);
1038 + class_device_unregister(&gnbd_dev[i].class_dev);
1041 + class_unregister(&gnbd_class);
1043 + unregister_blkdev(major_nr, "gnbd");
1046 + blk_cleanup_queue(gnbd_dev[i].disk->queue);
1047 + put_disk(gnbd_dev[i].disk);
1052 +static void __exit gnbd_cleanup(void)
1056 + gnbd_ctl_cleanup();
1057 + for (i = 0; i < MAX_GNBD; i++) {
1058 + struct gendisk *disk = gnbd_dev[i].disk;
1059 + class_device_unregister(&gnbd_dev[i].class_dev);
1061 + del_gendisk(disk);
1062 + blk_cleanup_queue(disk->queue);
1065 + if (gnbd_dev[i].server_name)
1066 + kfree(gnbd_dev[i].server_name);
1068 + class_unregister(&gnbd_class);
1069 + devfs_remove("gnbd");
1070 + unregister_blkdev(major_nr, "gnbd");
1071 + printk(KERN_INFO "gnbd: unregistered device at major %d\n", major_nr);
1074 +module_init(gnbd_init);
1075 +module_exit(gnbd_cleanup);
1077 +MODULE_DESCRIPTION("Network Block Device");
1078 +MODULE_LICENSE("GPL");
1081 +MODULE_PARM(debugflags, "i");
1082 +MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
1084 diff -urN linux-2.6.9/include/linux/gnbd.h linux-2.6.9-patched/include/linux/gnbd.h
1085 --- linux-2.6.9/include/linux/gnbd.h 1969-12-31 18:00:00.000000000 -0600
1086 +++ linux-2.6.9-patched/include/linux/gnbd.h 2004-10-22 13:39:34.000000000 -0500
1088 +/******************************************************************************
1089 +*******************************************************************************
1091 +** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
1092 +** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
1094 +** This copyrighted material is made available to anyone wishing to use,
1095 +** modify, copy, or redistribute it subject to the terms and conditions
1096 +** of the GNU General Public License v.2.
1098 +*******************************************************************************
1099 +******************************************************************************/
1101 +#ifndef LINUX_GNBD_H
1102 +#define LINUX_GNBD_H
1104 +#define GNBD_DO_IT _IO( 0xab, 0x20 )
1105 +#define GNBD_CLEAR_QUE _IO( 0xab, 0x21 )
1106 +#define GNBD_PRINT_DEBUG _IO( 0xab, 0x22 )
1107 +#define GNBD_DISCONNECT _IO( 0xab, 0x23 )
1108 +#define GNBD_PING _IO( 0xab, 0x24 )
1109 +#define GNBD_GET_TIME _IO( 0xab, 0x25 )
1112 + GNBD_CMD_READ = 0,
1113 + GNBD_CMD_WRITE = 1,
1114 + GNBD_CMD_DISC = 2,
1118 +#define gnbd_cmd(req) ((req)->cmd[0])
1119 +#define MAX_GNBD 128
1121 +/* values for flags field */
1122 +#define GNBD_READ_ONLY 0x0001
1124 +/* userspace doesn't need the gnbd_device structure */
1127 +struct gnbd_device {
1128 + unsigned short int flags;
1129 + struct socket * sock;
1130 + struct file * file; /* If == NULL, device is not ready, yet */
1132 + spinlock_t queue_lock;
1133 + spinlock_t open_lock;
1134 + struct list_head queue_head;/* Requests are added here... */
1135 + struct semaphore tx_lock;
1136 + struct gendisk *disk;
1137 + pid_t receiver_pid;
1138 + struct semaphore do_it_lock;
1140 + struct class_device class_dev;
1141 + unsigned short int server_port;
1142 + char *server_name;
1144 + unsigned long last_received;
1145 + struct block_device *bdev;
1148 +#endif /* __KERNEL__ */
1150 +/* These are sent over the network in the request/reply magic fields */
1152 +#define GNBD_REQUEST_MAGIC 0x37a07e00
1153 +#define GNBD_REPLY_MAGIC 0x41f09370
1154 +#define GNBD_KEEP_ALIVE_MAGIC 0x5B46D8C2
1155 +/* Do *not* use magics: 0x12560953 0x96744668. */
1158 + * This is the packet used for communication between client and
1159 + * server. All data are in network byte order.
1161 +struct gnbd_request {
1163 + uint32_t type; /* == READ || == WRITE why so long */
1164 + char handle[8]; /* why is this a char array instead of a u64 */
1169 + __attribute__ ((packed))
1170 +#endif /* __GNUC__ */
1174 + * This is the reply packet that gnbd-server sends back to the client after
1175 + * it has completed an I/O request (or an error occurs).
1177 +#define SIZE_OF_REPLY 16
1178 +struct gnbd_reply {
1180 + uint32_t error; /* 0 = ok, else error */
1181 + char handle[8]; /* handle you got from request */
1184 +struct do_it_req_s {
1185 + unsigned int minor;
1188 +typedef struct do_it_req_s do_it_req_t;
1190 +#endif /* LINUX_GNBD_H */