From: Will Sowerbutts Date: Sun, 11 Jan 2015 23:41:49 +0000 (+0000) Subject: Kernel: d_flush() flushes the write cache of a device, using the private X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=f4b220f4081fc1864fe1c668e166f5460e6bdd46;p=FUZIX.git Kernel: d_flush() flushes the write cache of a device, using the private device ioctl BLOCK_FLUSH_CACHE. d_flush() is called on a device whenever a writable file is closed. --- diff --git a/Kernel/devio.c b/Kernel/devio.c index ce8d53da..0b0a7b0a 100644 --- a/Kernel/devio.c +++ b/Kernel/devio.c @@ -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 */ diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index ff4388a1..eb3797fc 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -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); diff --git a/Kernel/inode.c b/Kernel/inode.c index cc4318fd..2a7ca9aa 100644 --- a/Kernel/inode.c +++ b/Kernel/inode.c @@ -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); } diff --git a/Kernel/syscall_fs.c b/Kernel/syscall_fs.c index a62c74e2..6ce0d2e2 100644 --- a/Kernel/syscall_fs.c +++ b/Kernel/syscall_fs.c @@ -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