1 diff -urN linux-2.6.7/drivers/block/Kconfig linux-2.6.7-patched/drivers/block/Kconfig
2 --- linux-2.6.7/drivers/block/Kconfig 2004-06-16 00:19:01.000000000 -0500
3 +++ linux-2.6.7-patched/drivers/block/Kconfig 2004-06-17 16:38:45.000000000 -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.7/drivers/block/Makefile linux-2.6.7-patched/drivers/block/Makefile
19 --- linux-2.6.7/drivers/block/Makefile 2004-06-16 00:19:52.000000000 -0500
20 +++ linux-2.6.7-patched/drivers/block/Makefile 2004-06-17 16:38:45.000000000 -0500
23 obj-$(CONFIG_VIODASD) += viodasd.o
24 obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
26 +obj-$(CONFIG_BLK_DEV_GNBD) += gnbd.o
27 diff -urN linux-orig/drivers/block/gnbd.c linux-patched/drivers/block/gnbd.c
28 --- linux-orig/drivers/block/gnbd.c 1969-12-31 18:00:00.000000000 -0600
29 +++ linux-patched/drivers/block/gnbd.c 2004-06-30 16:48:06.000000000 -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 + struct gnbd_device *dev = req->rq_disk->private_data;
304 + unsigned long flags;
306 + dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
307 + req, uptodate? "done": "failed");
310 + printk("%s %d called gnbd_end_request with and error\n",
311 + current->comm, current->pid);
313 + spin_lock(&dev->queue_lock);
314 + while (req->ref_count > 1) { /* still in send */
315 + spin_unlock(&dev->queue_lock);
316 + printk(KERN_DEBUG "%s: request %p still in use (%d), waiting\n",
317 + dev->disk->disk_name, req, req->ref_count);
318 + set_current_state(TASK_UNINTERRUPTIBLE);
319 + schedule_timeout(HZ); /* wait a second */
320 + spin_lock(&dev->queue_lock);
322 + spin_unlock(&dev->queue_lock);
324 + spin_lock_irqsave(q->queue_lock, flags);
325 + if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
326 + end_that_request_last(req);
328 + spin_unlock_irqrestore(q->queue_lock, flags);
332 + * Send or receive packet.
334 +static int sock_xmit(struct socket *sock, int send, void *buf, int size,
337 + mm_segment_t oldfs;
341 + unsigned long flags;
346 + /* Allow interception of SIGKILL only
347 + * Don't allow other signals to interrupt the transmission */
348 + spin_lock_irqsave(¤t->sighand->siglock, flags);
349 + oldset = current->blocked;
350 + sigfillset(¤t->blocked);
351 + sigdelsetmask(¤t->blocked, sigmask(SIGKILL));
352 + recalc_sigpending();
353 + spin_unlock_irqrestore(¤t->sighand->siglock, flags);
356 + sock->sk->sk_allocation = GFP_NOIO;
357 + iov.iov_base = buf;
358 + iov.iov_len = size;
359 + msg.msg_name = NULL;
360 + msg.msg_namelen = 0;
361 + msg.msg_iov = &iov;
362 + msg.msg_iovlen = 1;
363 + msg.msg_control = NULL;
364 + msg.msg_controllen = 0;
365 + msg.msg_namelen = 0;
366 + msg.msg_flags = msg_flags | MSG_NOSIGNAL;
369 + result = sock_sendmsg(sock, &msg, size);
371 + result = sock_recvmsg(sock, &msg, size, 0);
373 + if (signal_pending(current)) {
375 + spin_lock_irqsave(¤t->sighand->siglock, flags);
376 + printk(KERN_WARNING "gnbd (pid %d: %s) got signal %d\n",
377 + current->pid, current->comm,
378 + dequeue_signal(current, ¤t->blocked, &info));
379 + spin_unlock_irqrestore(¤t->sighand->siglock, flags);
386 + result = -EPIPE; /* short read */
391 + } while (size > 0);
393 + spin_lock_irqsave(¤t->sighand->siglock, flags);
394 + current->blocked = oldset;
395 + recalc_sigpending();
396 + spin_unlock_irqrestore(¤t->sighand->siglock, flags);
402 +static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
406 + void *kaddr = kmap(bvec->bv_page);
407 + result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
409 + kunmap(bvec->bv_page);
414 +#define gnbd_send_req(dev, req) __gnbd_send_req((dev), (dev)->sock, (req))
416 +int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock,
417 + struct request *req)
419 + int result, i, flags;
420 + struct gnbd_request request;
421 + unsigned long size = req->nr_sectors << 9;
423 + request.magic = htonl(GNBD_REQUEST_MAGIC);
424 + request.type = htonl(gnbd_cmd(req));
425 + request.from = cpu_to_be64((u64) req->sector << 9);
426 + request.len = htonl(size);
427 + memcpy(request.handle, &req, sizeof(req));
429 + down(&dev->tx_lock);
432 + printk(KERN_ERR "%s: Attempted send on closed socket\n",
433 + dev->disk->disk_name);
434 + result = -ENOTCONN;
438 + dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
439 + dev->disk->disk_name, req,
440 + gnbdcmd_to_ascii(gnbd_cmd(req)),
441 + (unsigned long long)req->sector << 9,
442 + req->nr_sectors << 9);
443 + result = sock_xmit(sock, 1, &request, sizeof(request),
444 + (gnbd_cmd(req) == GNBD_CMD_WRITE)? MSG_MORE: 0);
446 + printk(KERN_ERR "%s: Send control failed (result %d)\n",
447 + dev->disk->disk_name, result);
451 + if (gnbd_cmd(req) == GNBD_CMD_WRITE) {
454 + * we are really probing at internals to determine
455 + * whether to set MSG_MORE or not...
457 + rq_for_each_bio(bio, req) {
458 + struct bio_vec *bvec;
459 + bio_for_each_segment(bvec, bio, i) {
461 + if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
463 + dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
464 + dev->disk->disk_name, req,
466 + result = sock_send_bvec(sock, bvec, flags);
468 + printk(KERN_ERR "%s: Send data failed (result %d)\n",
469 + dev->disk->disk_name,
485 +static int gnbd_find_request(struct gnbd_device *dev, struct request *xreq)
487 + struct request *req;
488 + struct list_head *tmp;
490 + list_for_each(tmp, &dev->queue_head) {
491 + req = list_entry(tmp, struct request, queuelist);
499 +static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
502 + void *kaddr = kmap(bvec->bv_page);
503 + result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
505 + kunmap(bvec->bv_page);
509 +int gnbd_recv_req(struct gnbd_device *dev, struct request *req)
514 + rq_for_each_bio(bio, req) {
515 + struct bio_vec *bvec;
516 + bio_for_each_segment(bvec, bio, i) {
517 + result = sock_recv_bvec(dev->sock, bvec);
519 + printk(KERN_ERR "%s: Receive data failed (result %d)\n",
520 + dev->disk->disk_name,
524 + dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
525 + dev->disk->disk_name, req, bvec->bv_len);
531 +int gnbd_do_it(struct gnbd_device *dev)
534 + struct gnbd_reply reply;
535 + struct request *req;
536 + struct socket *sock = dev->sock;
538 + BUG_ON(dev->magic != GNBD_MAGIC);
540 + while((result = sock_xmit(sock, 0, &reply,sizeof(reply), MSG_WAITALL)) > 0){
541 + if (ntohl(reply.magic) == GNBD_KEEP_ALIVE_MAGIC)
542 + /* FIXME -- I should reset the wait time here */
545 + memcpy(&req, reply.handle, sizeof(req));
546 + if (req == &shutdown_req)
549 + if (!gnbd_find_request(dev, req)){
550 + printk(KERN_ERR "%s: Unexpected reply (%p)\n",
551 + dev->disk->disk_name, reply.handle);
554 + if (ntohl(reply.magic) != GNBD_REPLY_MAGIC) {
555 + printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
556 + dev->disk->disk_name,
557 + (unsigned long)ntohl(reply.magic));
560 + if (ntohl(reply.error)) {
561 + printk(KERN_ERR "%s: Other side returned error (%d)\n",
562 + dev->disk->disk_name, ntohl(reply.error));
566 + dprintk(DBG_RX, "%s: request %p: got reply\n",
567 + dev->disk->disk_name, req);
569 + if (gnbd_cmd(req) == GNBD_CMD_READ){
570 + result = gnbd_recv_req(dev, req);
575 + spin_lock(&dev->queue_lock);
576 + list_del_init(&req->queuelist);
577 + dev->last_received = jiffies;
578 + spin_unlock(&dev->queue_lock);
579 + if (req != &ping_req)
580 + gnbd_end_request(req);
582 + printk(KERN_ERR "%s: Receive control failed (result %d)\n",
583 + dev->disk->disk_name, result);
587 +void gnbd_clear_que(struct gnbd_device *dev)
589 + struct request *req;
591 + BUG_ON(dev->magic != GNBD_MAGIC);
595 + if (!list_empty(&dev->queue_head)) {
596 + req = list_entry(dev->queue_head.next, struct request, queuelist);
597 + list_del_init(&req->queuelist);
599 + if (req && req != &ping_req) {
601 + gnbd_end_request(req);
607 + * We always wait for result of write, for now. It would be nice to make it optional
609 + * if ((req->cmd == WRITE) && (dev->flags & GNBD_WRITE_NOCHK))
610 + * { printk( "Warning: Ignoring result!\n"); gnbd_end_request( req ); }
613 +static void do_gnbd_request(request_queue_t * q)
616 + struct request *req;
618 + while ((req = elv_next_request(q)) != NULL) {
619 + struct gnbd_device *dev;
621 + blkdev_dequeue_request(req);
622 + dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
623 + req->rq_disk->disk_name, req, req->flags);
625 + if (!(req->flags & REQ_CMD))
628 + dev = req->rq_disk->private_data;
630 + if (dev->receiver_pid == -1)
633 + BUG_ON(dev->magic != GNBD_MAGIC);
635 + gnbd_cmd(req) = GNBD_CMD_READ;
636 + if (rq_data_dir(req) == WRITE) {
637 + gnbd_cmd(req) = GNBD_CMD_WRITE;
638 + if (dev->flags & GNBD_READ_ONLY) {
639 + printk(KERN_ERR "%s: Write on read-only\n",
640 + dev->disk->disk_name);
646 + spin_unlock_irq(q->queue_lock);
648 + spin_lock(&dev->queue_lock);
650 + if (list_empty(&dev->queue_head))
651 + dev->last_received = jiffies;
652 + list_add(&req->queuelist, &dev->queue_head);
653 + req->ref_count++; /* make sure req does not get freed */
654 + spin_unlock(&dev->queue_lock);
656 + err = gnbd_send_req(dev, req);
658 + spin_lock(&dev->queue_lock);
660 + spin_unlock(&dev->queue_lock);
661 + spin_lock_irq(q->queue_lock);
668 + spin_unlock(q->queue_lock);
669 + gnbd_end_request(req);
670 + spin_lock(q->queue_lock);
679 + * This is called before dev-sock is set, so you dodn't need
680 + * to worry about the tx_lock or the queue_lock
682 +static int gnbd_resend_requests(struct gnbd_device *dev, struct socket *sock)
685 + struct request *req;
686 + struct list_head *tmp;
688 + printk("resending requests\n");
689 + list_for_each(tmp, &dev->queue_head) {
690 + req = list_entry(tmp, struct request, queuelist);
691 + err = __gnbd_send_req(dev, sock, req);
694 + printk("failed trying to resend request (%d)\n", err);
702 +static int get_server_info(struct gnbd_device *dev, struct socket *sock)
704 + struct sockaddr_in server;
708 + err = sock->ops->getname(sock, (struct sockaddr *) &server, &len, 1);
710 + printk(KERN_WARNING "cannot get socket info, shutting down\n");
712 + dev->server_addr = server.sin_addr;
713 + dev->server_port = server.sin_port;
719 +static int gnbd_ctl_ioctl(struct inode *inode, struct file *file,
720 + unsigned int cmd, unsigned long arg)
722 + struct gnbd_device *dev = NULL;
723 + struct block_device *bdev;
727 + if (!capable(CAP_SYS_ADMIN))
730 + if (cmd == GNBD_DISCONNECT || cmd == GNBD_CLEAR_QUE ||
731 + cmd == GNBD_PING || cmd == GNBD_PRINT_DEBUG) {
732 + if (arg >= MAX_GNBD)
734 + dev = &gnbd_dev[arg];
735 + BUG_ON(dev->magic != GNBD_MAGIC);
738 + /* Anyone capable of this syscall can do *real bad* things */
739 + dprintk(DBG_IOCTL, "%s: gnbd_ioctl cmd=%s(0x%x) arg=%lu\n",
740 + dev->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
743 + case GNBD_DISCONNECT:
744 + printk(KERN_INFO "%s: GNBD_DISCONNECT\n", dev->disk->disk_name);
745 + spin_lock(&dev->open_lock);
746 + if (dev->open_count > 0){
747 + spin_unlock(&dev->open_lock);
750 + dev->receiver_pid = -1;
751 + spin_unlock(&dev->open_lock);
752 + /* There is no one using the device, you can disconnect it */
753 + if (dev->sock == NULL)
755 + gnbd_send_req(dev, &shutdown_req);
757 + case GNBD_CLEAR_QUE:
758 + if (down_interruptible(&dev->do_it_lock))
760 + dev->receiver_pid = -1;
761 + gnbd_clear_que(dev);
764 + blk_run_queue(dev->disk->queue);
766 + invalidate_bdev(bdev, 0);
768 + up(&dev->do_it_lock);
771 + if (copy_from_user(&req, (do_it_req_t *)arg, sizeof(req)))
773 + if (req.minor >= 128)
775 + dev = &gnbd_dev[req.minor];
776 + BUG_ON(dev->magic != GNBD_MAGIC);
780 + file = fget(req.sock_fd);
783 + inode = file->f_dentry->d_inode;
784 + if (!inode->i_sock) {
788 + if (down_trylock(&dev->do_it_lock)){
792 + /* FIXME -- Why do this? I connected with the
793 + server. I know what these values are */
795 + error = get_server_info(dev, SOCKET_I(inode));
801 + error = gnbd_resend_requests(dev, SOCKET_I(inode));
803 + printk("quitting NBD_DO_IT\n");
804 + up(&dev->do_it_lock);
809 + dev->sock = SOCKET_I(inode);
810 + dev->receiver_pid = current->pid;
811 + blk_run_queue(dev->disk->queue);
812 + error = gnbd_do_it(dev);
813 + /* should I kill the socket first */
814 + up(&dev->do_it_lock);
815 + down(&dev->tx_lock);
817 + printk(KERN_WARNING "%s: shutting down socket\n",
818 + dev->disk->disk_name);
819 + dev->sock->ops->shutdown(dev->sock,
820 + SEND_SHUTDOWN|RCV_SHUTDOWN);
828 + printk("exitting GNBD_DO_IT ioctl\n");
831 + /* FIXME -- should I allow pings if everything is compeletely
833 + spin_lock(&dev->queue_lock);
834 + /* only one outstanding ping at a time */
835 + if (list_empty(&ping_req.queuelist)){
836 + if (list_empty(&dev->queue_head))
837 + dev->last_received = jiffies;
838 + list_add(&ping_req.queuelist, &dev->queue_head);
840 + spin_unlock(&dev->queue_lock);
841 + gnbd_send_req(dev, &ping_req); /* ignore the errors */
843 + case GNBD_PRINT_DEBUG:
844 + printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
845 + dev->disk->disk_name,
846 + dev->queue_head.next, dev->queue_head.prev,
849 + case GNBD_GET_TIME:
850 + if (copy_to_user((void *)arg, &insmod_time, sizeof(uint64_t))){
851 + printk(KERN_WARNING "couldn't compy time argument to user\n");
856 + /* FIXME -- should I print something, is EINVAL the right error */
860 +static int gnbd_open(struct inode *inode, struct file *file)
862 + struct gnbd_device *dev = inode->i_bdev->bd_disk->private_data;
863 + spin_lock(&dev->open_lock);
864 + if (dev->receiver_pid == -1){
865 + spin_unlock(&dev->open_lock);
868 + spin_unlock(&dev->open_lock);
869 + if ((file->f_mode & FMODE_WRITE) && (dev->flags & GNBD_READ_ONLY)){
870 + printk(KERN_INFO "cannot open read only gnbd device read/write");
875 + dev->bdev = inode->i_bdev;
879 +/* FIXME -- I don't sync the device at close. This means that If you write
880 + * something, and close the device, and expect that then it is written,
881 + * you are wrong.... This might cause problems */
882 +static int gnbd_release(struct inode *inode, struct file *file)
884 + struct gnbd_device *dev = inode->i_bdev->bd_disk->private_data;
887 + if (dev->open_count == 0)
892 +static struct file_operations _gnbd_ctl_fops =
894 + .ioctl = gnbd_ctl_ioctl,
895 + .owner = THIS_MODULE,
898 +static struct miscdevice _gnbd_misc =
900 + .minor = MISC_DYNAMIC_MINOR,
901 + .name = "gnbd_ctl",
902 + .devfs_name = "gnbd_ctl",
903 + .fops = &_gnbd_ctl_fops
906 +/* FIXME -- I should probably do more here */
907 +int __init gnbd_ctl_init(void)
911 + err = misc_register(&_gnbd_misc);
913 + printk("cannot register control device\n");
919 +void gnbd_ctl_cleanup(void)
921 + if (misc_deregister(&_gnbd_misc) < 0)
922 + printk("cannot deregister control device\n");
925 +static struct block_device_operations gnbd_fops =
928 + .release = gnbd_release,
929 + .owner = THIS_MODULE,
933 + * And here should be modules and kernel interface
934 + * (Just smiley confuses emacs :-)
937 +static int __init gnbd_init(void)
943 + if (sizeof(struct gnbd_request) != 28) {
944 + printk(KERN_CRIT "gnbd: sizeof gnbd_request needs to be 28 in order to work!\n" );
947 + shutdown_req.flags = REQ_SPECIAL;
948 + gnbd_cmd(&shutdown_req) = GNBD_CMD_DISC;
949 + shutdown_req.sector = 0;
950 + shutdown_req.nr_sectors = 0;
952 + ping_req.flags = REQ_SPECIAL;
953 + gnbd_cmd(&ping_req) = GNBD_CMD_PING;
954 + ping_req.sector = 0;
955 + ping_req.nr_sectors = 0;
957 + for (i = 0; i < MAX_GNBD; i++) {
958 + struct gendisk *disk = alloc_disk(1);
961 + gnbd_dev[i].disk = disk;
963 + * The new linux 2.5 block layer implementation requires
964 + * every gendisk to have its very own request_queue struct.
965 + * These structs are big so we dynamically allocate them.
967 + disk->queue = blk_init_queue(do_gnbd_request, &gnbd_lock);
968 + if (!disk->queue) {
973 + major_nr = register_blkdev(major_nr, "gnbd");
974 + if (major_nr < 0) {
975 + printk("gnbd: unable to get a major number\n");
980 + printk(KERN_INFO "gnbd: registered device at major %d\n", major_nr);
981 + dprintk(DBG_INIT, "gnbd: debugflags=0x%x\n", debugflags);
983 + devfs_mk_dir("gnbd_minor");
984 + err = class_register(&gnbd_class);
986 + goto out_unregister;
987 + for (i = 0; i < MAX_GNBD; i++) {
988 + struct gendisk *disk = gnbd_dev[i].disk;
989 + gnbd_dev[i].file = NULL;
990 + gnbd_dev[i].magic = GNBD_MAGIC;
991 + gnbd_dev[i].flags = 0;
992 + gnbd_dev[i].open_count = 0;
993 + gnbd_dev[i].receiver_pid = -1;
994 + gnbd_dev[i].server_name = NULL;
995 + gnbd_dev[i].server_port = 0;
996 + gnbd_dev[i].name[0] = '\0';
997 + gnbd_dev[i].bdev = NULL;
998 + spin_lock_init(&gnbd_dev[i].queue_lock);
999 + spin_lock_init(&gnbd_dev[i].open_lock);
1000 + INIT_LIST_HEAD(&gnbd_dev[i].queue_head);
1001 + init_MUTEX(&gnbd_dev[i].tx_lock);
1002 + init_MUTEX(&gnbd_dev[i].do_it_lock);
1003 + gnbd_dev[i].class_dev.class = &gnbd_class;
1004 + sprintf(gnbd_dev[i].class_dev.class_id, "gnbd%d", i);
1005 + err = class_device_register(&gnbd_dev[i].class_dev);
1007 + printk("class_device_register failed with %d\n", err);
1008 + goto out_unregister_class;
1010 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1011 + &class_device_attr_pid))
1012 + goto out_remove_file;
1013 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1014 + &class_device_attr_server))
1015 + goto out_remove_file;
1016 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1017 + &class_device_attr_name))
1018 + goto out_remove_file;
1019 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1020 + &class_device_attr_sectors))
1021 + goto out_remove_file;
1022 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1023 + &class_device_attr_usage))
1024 + goto out_remove_file;
1025 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1026 + &class_device_attr_flags))
1027 + goto out_remove_file;
1028 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1029 + &class_device_attr_waittime))
1030 + goto out_remove_file;
1031 + if(class_device_create_file(&gnbd_dev[i].class_dev,
1032 + &class_device_attr_connected))
1033 + goto out_remove_file;
1034 + disk->major = major_nr;
1035 + disk->first_minor = i;
1036 + disk->fops = &gnbd_fops;
1037 + disk->private_data = &gnbd_dev[i];
1038 + sprintf(disk->disk_name, "gnbd%d", i);
1039 + sprintf(disk->devfs_name, "gnbd_minor/%d", i);
1040 + set_capacity(disk, 0);
1042 + if(sysfs_create_link(&gnbd_dev[i].class_dev.kobj,
1043 + &gnbd_dev[i].disk->kobj, "block"))
1044 + goto out_remove_disk;
1048 + err = gnbd_ctl_init();
1050 + goto out_unregister_class;
1052 + insmod_time = (uint64_t) tv.tv_sec * 1000000 + tv.tv_usec;
1056 + del_gendisk(gnbd_dev[i].disk);
1058 + class_device_unregister(&gnbd_dev[i].class_dev);
1059 +out_unregister_class:
1061 + del_gendisk(gnbd_dev[i].disk);
1062 + class_device_unregister(&gnbd_dev[i].class_dev);
1065 + class_unregister(&gnbd_class);
1067 + unregister_blkdev(major_nr, "gnbd");
1070 + blk_cleanup_queue(gnbd_dev[i].disk->queue);
1071 + put_disk(gnbd_dev[i].disk);
1076 +static void __exit gnbd_cleanup(void)
1080 + gnbd_ctl_cleanup();
1081 + for (i = 0; i < MAX_GNBD; i++) {
1082 + struct gendisk *disk = gnbd_dev[i].disk;
1084 + del_gendisk(disk);
1085 + blk_cleanup_queue(disk->queue);
1088 + if (gnbd_dev[i].server_name)
1089 + kfree(gnbd_dev[i].server_name);
1091 + class_unregister(&gnbd_class);
1092 + devfs_remove("gnbd");
1093 + unregister_blkdev(major_nr, "gnbd");
1094 + printk(KERN_INFO "gnbd: unregistered device at major %d\n", major_nr);
1097 +module_init(gnbd_init);
1098 +module_exit(gnbd_cleanup);
1100 +MODULE_DESCRIPTION("Network Block Device");
1101 +MODULE_LICENSE("GPL");
1104 +MODULE_PARM(debugflags, "i");
1105 +MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
1107 diff -urN linux-orig/include/linux/gnbd.h linux-patched/include/linux/gnbd.h
1108 --- linux-orig/include/linux/gnbd.h 1969-12-31 18:00:00.000000000 -0600
1109 +++ linux-patched/include/linux/gnbd.h 2004-06-30 16:48:06.000000000 -0500
1111 +/******************************************************************************
1112 +*******************************************************************************
1114 +** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
1115 +** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
1117 +** This copyrighted material is made available to anyone wishing to use,
1118 +** modify, copy, or redistribute it subject to the terms and conditions
1119 +** of the GNU General Public License v.2.
1121 +*******************************************************************************
1122 +******************************************************************************/
1124 +#ifndef LINUX_GNBD_H
1125 +#define LINUX_GNBD_H
1127 +#define GNBD_DO_IT _IO( 0xab, 0x20 )
1128 +#define GNBD_CLEAR_QUE _IO( 0xab, 0x21 )
1129 +#define GNBD_PRINT_DEBUG _IO( 0xab, 0x22 )
1130 +#define GNBD_DISCONNECT _IO( 0xab, 0x23 )
1131 +#define GNBD_PING _IO( 0xab, 0x24 )
1132 +#define GNBD_GET_TIME _IO( 0xab, 0x25 )
1135 + GNBD_CMD_READ = 0,
1136 + GNBD_CMD_WRITE = 1,
1137 + GNBD_CMD_DISC = 2,
1141 +#define gnbd_cmd(req) ((req)->cmd[0])
1142 +#define MAX_GNBD 128
1144 +/* values for flags field */
1145 +#define GNBD_READ_ONLY 0x0001
1147 +/* userspace doesn't need the gnbd_device structure */
1150 +struct gnbd_device {
1151 + unsigned short int flags;
1152 + struct socket * sock;
1153 + struct file * file; /* If == NULL, device is not ready, yet */
1155 + spinlock_t queue_lock;
1156 + spinlock_t open_lock;
1157 + struct list_head queue_head;/* Requests are added here... */
1158 + struct semaphore tx_lock;
1159 + struct gendisk *disk;
1160 + pid_t receiver_pid;
1161 + struct semaphore do_it_lock;
1163 + struct class_device class_dev;
1164 + unsigned short int server_port;
1165 + char *server_name;
1167 + unsigned long last_received;
1168 + struct block_device *bdev;
1171 +#endif /* __KERNEL__ */
1173 +/* These are sent over the network in the request/reply magic fields */
1175 +#define GNBD_REQUEST_MAGIC 0x37a07e00
1176 +#define GNBD_REPLY_MAGIC 0x41f09370
1177 +#define GNBD_KEEP_ALIVE_MAGIC 0x5B46D8C2
1178 +/* Do *not* use magics: 0x12560953 0x96744668. */
1181 + * This is the packet used for communication between client and
1182 + * server. All data are in network byte order.
1184 +struct gnbd_request {
1186 + uint32_t type; /* == READ || == WRITE why so long */
1187 + char handle[8]; /* why is this a char array instead of a u64 */
1192 + __attribute__ ((packed))
1193 +#endif /* __GNUC__ */
1197 + * This is the reply packet that gnbd-server sends back to the client after
1198 + * it has completed an I/O request (or an error occurs).
1200 +#define SIZE_OF_REPLY 16
1201 +struct gnbd_reply {
1203 + uint32_t error; /* 0 = ok, else error */
1204 + char handle[8]; /* handle you got from request */
1207 +struct do_it_req_s {
1208 + unsigned int minor;
1211 +typedef struct do_it_req_s do_it_req_t;
1213 +#endif /* LINUX_GNBD_H */