devio: Fix the long standing buffer flushing FIXME
authorAlan Cox <alan@linux.intel.com>
Fri, 15 May 2015 23:47:58 +0000 (00:47 +0100)
committerAlan Cox <alan@linux.intel.com>
Fri, 15 May 2015 23:47:58 +0000 (00:47 +0100)
We now drop buffers on the final close of a device. This makes mounting
different floppy disks work reliably.

Kernel/devio.c
Kernel/include/kernel.h

index 6eed647..a6a19af 100644 (file)
@@ -116,18 +116,23 @@ void *zerobuf(void)
        return b;
 }
 
+static void bdput(bufptr bp)
+{
+       bdwrite(bp);
+       if (bp->bf_busy == BF_FREE)
+               bp->bf_dirty = false;
+       d_flush(bp->bf_dev);
+}
 
 void bufsync(void)
 {
        bufptr bp;
 
+       /* FIXME: this can generate a lot of d_flush calls when you have
+          plenty of buffers */
        for (bp = bufpool; bp < bufpool + NBUFS; ++bp) {
-               if ((bp->bf_dev != NO_DEVICE) && bp->bf_dirty) {
-                       bdwrite(bp);
-                       if (bp->bf_busy == BF_FREE)
-                               bp->bf_dirty = false;
-                       d_flush(bp->bf_dev);
-               }
+               if ((bp->bf_dev != NO_DEVICE) && bp->bf_dirty)
+                       bdput(bp);
        }
 }
 
@@ -142,6 +147,17 @@ bufptr bfind(uint16_t dev, blkno_t blk)
        return NULL;
 }
 
+void bdrop(uint16_t dev)
+{
+       bufptr bp;
+
+       for (bp = bufpool; bp < bufpool + NBUFS; ++bp) {
+               if (bp->bf_dev == dev) {
+                       bdput(bp);
+                       bp->bf_dev = NO_DEVICE;
+                }
+       }
+}
 
 bufptr freebuf(void)
 {
@@ -242,8 +258,6 @@ int cdwrite(uint16_t dev, uint8_t flag)
        return ((*dev_tab[major(dev)].dev_write) (minor(dev), 1, flag));
 }
 
-// WRS: swapread(), swapwrite() removed.
-
 int d_open(uint16_t dev, uint8_t flag)
 {
        if (!validdev(dev))
@@ -251,14 +265,11 @@ int d_open(uint16_t dev, uint8_t flag)
        return ((*dev_tab[major(dev)].dev_open) (minor(dev), flag));
 }
 
-
-/* FIXME: on the last close we ought to flush/invalidate any bufs
-   for this device so we can support swapping between media properly
-   (right now the cache is so small it happens to work...) */
 int d_close(uint16_t dev)
 {
        if (!validdev(dev))
                panic("d_close: bad device");
+        bdrop(dev);
        return (*dev_tab[major(dev)].dev_close) (minor(dev));
 }
 
index 8f972e0..dd4db59 100644 (file)
@@ -632,6 +632,7 @@ extern void *tmpbuf(void);
 extern void *zerobuf(void);
 extern void bufsync(void);
 extern bufptr bfind(uint16_t dev, blkno_t blk);
+extern void bdrop(uint16_t dev);
 extern bufptr freebuf(void);
 extern void bufinit(void);
 extern void bufdiscard(bufptr bp);