nbd fixes

From: Pavel Machek (pavel@suse.cz)
Date: Thu Mar 09 2000 - 17:59:46 EST


Hi!

Nbd was broken by block device changes [it currently does not work at
all]. Now it is fixed (with andrea's cooperation). Please apply.

                                                                Pavel
PS: James, please test this.

--- clean/drivers/block/nbd.c Mon Feb 21 10:32:22 2000
+++ linux/drivers/block/nbd.c Thu Mar 9 23:55:45 2000
@@ -4,7 +4,7 @@
  * Note that you can not swap over this thing, yet. Seems to work but
  * deadlocks sometimes - you can not swap over TCP in general.
  *
- * Copyright 1997 Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+ * Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
  *
  * (part of code stolen from loop.c)
  *
@@ -24,6 +24,7 @@
  * structure with userland
  */
 
+#undef NBD_PLUGGABLE
 #define PARANOIA
 #include <linux/major.h>
 
@@ -62,10 +63,11 @@
 static int requests_out;
 #endif
 
+static void nbd_plug_device(request_queue_t *q, kdev_t dev) { }
+
 static int nbd_open(struct inode *inode, struct file *file)
 {
         int dev;
- struct nbd_device *nbdev;
 
         if (!inode)
                 return -EINVAL;
@@ -73,12 +75,7 @@
         if (dev >= MAX_NBD)
                 return -ENODEV;
 
- nbdev = &nbd_dev[dev];
         nbd_dev[dev].refcnt++;
- if (!(nbdev->flags & NBD_INITIALISED)) {
- init_MUTEX(&nbdev->queue_lock);
- nbdev->flags |= NBD_INITIALISED;
- }
         MOD_INC_USE_COUNT;
         return 0;
 }
@@ -215,12 +212,18 @@
 void nbd_do_it(struct nbd_device *lo)
 {
         struct request *req;
+ int dequeued;
 
         down (&lo->queue_lock);
- while (!list_empty(&lo->queue_head)) {
+ while (1) {
+ up (&lo->queue_lock);
                 req = nbd_read_stat(lo);
- if (!req)
+ down (&lo->queue_lock);
+
+ if (!req) {
+ printk(KERN_ALERT "req should never be null\n" );
                         goto out;
+ }
 #ifdef PARANOIA
                 if (req != blkdev_entry_prev_request(&lo->queue_head)) {
                         printk(KERN_ALERT "NBD: I have problem...\n");
@@ -237,9 +240,11 @@
                 list_del(&req->queue);
                 up (&lo->queue_lock);
                 
- nbd_end_request(req);
+ dequeued = nbd_end_request(req);
 
                 down (&lo->queue_lock);
+ if (!dequeued)
+ list_add(&req->queue, &lo->queue_head);
         }
  out:
         up (&lo->queue_lock);
@@ -248,26 +253,36 @@
 void nbd_clear_que(struct nbd_device *lo)
 {
         struct request *req;
+ int dequeued;
+
+#ifdef PARANOIA
+ if (lo->magic != LO_MAGIC) {
+ printk(KERN_ERR "NBD: nbd_dev[] corrupted: Not enough magic when clearing!\n");
+ return;
+ }
+#endif
 
         while (!list_empty(&lo->queue_head)) {
                 req = blkdev_entry_prev_request(&lo->queue_head);
 #ifdef PARANOIA
+ if (!req) {
+ printk( KERN_ALERT "NBD: panic, panic, panic\n" );
+ break;
+ }
                 if (lo != &nbd_dev[MINOR(req->rq_dev)]) {
                         printk(KERN_ALERT "NBD: request corrupted when clearing!\n");
                         continue;
                 }
- if (lo->magic != LO_MAGIC) {
- printk(KERN_ERR "NBD: nbd_dev[] corrupted: Not enough magic when clearing!\n");
- return;
- }
 #endif
                 req->errors++;
                 list_del(&req->queue);
                 up(&lo->queue_lock);
 
- nbd_end_request(req);
+ dequeued = nbd_end_request(req);
 
                 down(&lo->queue_lock);
+ if (!dequeued)
+ list_add(&req->queue, &lo->queue_head);
         }
 }
 
@@ -289,6 +304,10 @@
 
         while (!QUEUE_EMPTY) {
                 req = CURRENT;
+#ifdef PARANOIA
+ if (!req)
+ FAIL("que not empty but no request?");
+#endif
                 dev = MINOR(req->rq_dev);
 #ifdef PARANOIA
                 if (dev >= MAX_NBD)
@@ -469,12 +488,17 @@
         blksize_size[MAJOR_NR] = nbd_blksizes;
         blk_size[MAJOR_NR] = nbd_sizes;
         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
+#ifndef NBD_PLUGGABLE
+ blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), nbd_plug_device);
+#endif
         blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
         for (i = 0; i < MAX_NBD; i++) {
                 nbd_dev[i].refcnt = 0;
                 nbd_dev[i].file = NULL;
                 nbd_dev[i].magic = LO_MAGIC;
                 nbd_dev[i].flags = 0;
+ INIT_LIST_HEAD(&nbd_dev[i].queue_head);
+ init_MUTEX(&nbd_dev[i].queue_lock);
                 nbd_blksizes[i] = 1024;
                 nbd_blksize_bits[i] = 10;
                 nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
--- clean/include/linux/nbd.h Sat Feb 19 19:52:22 2000
+++ linux/include/linux/nbd.h Thu Mar 9 23:15:04 2000
@@ -30,22 +30,35 @@
 extern int requests_out;
 #endif
 
-static void
+static int
 nbd_end_request(struct request *req)
 {
         unsigned long flags;
+ int ret = 0;
 
 #ifdef PARANOIA
         requests_out++;
 #endif
+ /*
+ * This is a very dirty hack that we have to do to handle
+ * merged requests because end_request stuff is a bit
+ * broken. The fact we have to do this only if there
+ * aren't errors looks even more silly.
+ */
+ if (!req->errors) {
+ req->sector += req->current_nr_sectors;
+ req->nr_sectors -= req->current_nr_sectors;
+ }
+
         spin_lock_irqsave(&io_request_lock, flags);
         if (end_that_request_first( req, !req->errors, "nbd" ))
                 goto out;
+ ret = 1;
         end_that_request_last( req );
 
 out:
         spin_unlock_irqrestore(&io_request_lock, flags);
- return;
+ return ret;
 }
 
 #define MAX_NBD 128
@@ -56,7 +69,6 @@
         int harderror; /* Code of hard error */
 #define NBD_READ_ONLY 0x0001
 #define NBD_WRITE_NOCHK 0x0002
-#define NBD_INITIALISED 0x0004
         struct socket * sock;
         struct file * file; /* If == NULL, device is not ready, yet */
         int magic; /* FIXME: not if debugging is off */

-- 
I'm pavel@ucw.cz. "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents me at discuss@linmodems.org

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Mar 15 2000 - 21:00:17 EST