Kernel: d_flush() flushes the write cache of a device, using the private
authorWill Sowerbutts <will@sowerbutts.com>
Sun, 11 Jan 2015 23:41:49 +0000 (23:41 +0000)
committerWill Sowerbutts <will@sowerbutts.com>
Sun, 11 Jan 2015 23:41:49 +0000 (23:41 +0000)
device ioctl BLOCK_FLUSH_CACHE.

d_flush() is called on a device whenever a writable file is closed.

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

index ce8d53d..0b0a7b0 100644 (file)
@@ -122,6 +122,7 @@ void bufsync(void)
                        bdwrite(bp);
                        if (!bp->bf_busy)
                                bp->bf_dirty = false;
+                       d_flush(bp->bf_dev);
                }
        }
 }
@@ -283,6 +284,13 @@ int d_ioctl(uint16_t dev, uint16_t request, char *data)
        return 0;
 }
 
+int d_flush(uint16_t dev)
+{
+       if (!validdev(dev))
+               panic("d_flush: bad device");
+       return (*dev_tab[major(dev)].dev_ioctl) (minor(dev), BLOCK_FLUSH_CACHE, 0);
+}
+
 /*
  *     No such device handler
  */
index ff4388a..eb3797f 100644 (file)
@@ -507,6 +507,7 @@ struct s_argblk {
  */
 #define SELECT_BEGIN           0x8000
 #define SELECT_END             0x8001
+#define BLOCK_FLUSH_CACHE       0x8002
 
 struct sysinfoblk {
   uint8_t infosize;            /* For expandability */
@@ -596,6 +597,7 @@ CODE1 int cdread(uint16_t dev, uint8_t flag);
 CODE1 int d_open(uint16_t dev, uint8_t flag);
 CODE1 int d_close(uint16_t dev);
 CODE1 int d_ioctl(uint16_t dev, uint16_t request, char *data);
+CODE1 int d_flush(uint16_t dev);
 CODE1 int cdwrite(uint16_t dev, uint8_t flag);
 CODE1 bool insq(struct s_queue *q, unsigned char c);
 CODE1 bool remq(struct s_queue *q, unsigned char *cp);
index cc4318f..2a7ca9a 100644 (file)
@@ -198,6 +198,7 @@ int16_t doclose(uint8_t uindex)
 {
        int8_t oftindex;
        inoptr ino;
+       uint16_t flush_dev = NO_DEVICE;
 
        if (!(ino = getinode(uindex)))
                return (-1);
@@ -207,8 +208,10 @@ int16_t doclose(uint8_t uindex)
        if (ino->c_refs == 1 && of_tab[oftindex].o_refs == 1) {
                if (isdevice(ino))
                        d_close((int) (ino->c_node.i_addr[0]));
+               if (getmode(ino) == F_REG && O_ACCMODE(of_tab[oftindex].o_access))
+                       flush_dev = ino->c_dev;
 #ifdef CONFIG_NET
-               if (issocket(ino)
+               if (issocket(ino))
                        sock_close(ino);
 #endif
        }
@@ -216,6 +219,10 @@ int16_t doclose(uint8_t uindex)
        udata.u_cloexec &= ~(1 << uindex);
        oft_deref(oftindex);
 
+       /* if we closed a file in write mode, flush the device's cache after inode has been deferenced */
+       if(flush_dev != NO_DEVICE)
+               d_flush(flush_dev);
+
        return (0);
 }
 
index a62c74e..6ce0d2e 100644 (file)
@@ -87,6 +87,7 @@ int16_t _sync(void)
                if (ino->c_refs > 0 && (ino->c_flags & CDIRTY)) {
                        wr_inode(ino);
                        ino->c_flags &= ~CDIRTY;
+                       /* WRS: also call d_flush(ino->c_dev) here? */
                }
 
         /* This now also indirectly does the superblocks as they