]> Zhao Yanbai Git Server - minix.git/commitdiff
VM: readd support for forgetting cached FS blocks 81/981/2
authorDavid van Moolenbroek <david@minix3.org>
Sun, 15 Sep 2013 16:55:42 +0000 (18:55 +0200)
committerLionel Sambuc <lionel@minix3.org>
Sat, 1 Mar 2014 08:04:53 +0000 (09:04 +0100)
Not all services involved in block I/O go through VM to access the
blocks they need.  As a result, the blocks in VM may become stale,
possibly causing corruption when the stale copy is restored by a
service that does go through VM later on.  This patch restores support
for forgetting cached blocks that belong to a particular device, and
makes the relevant file systems use this functionality 1) when
requested by VFS through REQ_FLUSH, and 2) upon unmount.

Change-Id: I0758c5ed8fe4b5ba81d432595d2113175776aff8

15 files changed:
commands/service/parse.c
etc/system.conf
include/minix/com.h
include/minix/vm.h
lib/libminixfs/cache.c
lib/libsys/vm_cache.c
servers/ext2/mount.c
servers/mfs/mount.c
servers/vm/cache.c
servers/vm/main.c
servers/vm/mem_cache.c
servers/vm/proto.h
test/test72.c
test/testvm.c
test/testvm.conf

index a84db8012dd738cee7d01a6a8a29b7a895623e5d..342080ba0ff3e8b07bf2ac125b5dd49e8a896a03 100644 (file)
@@ -734,6 +734,7 @@ struct
        { "PROCCTL",            VM_PROCCTL },
        { "MAPCACHEPAGE",       VM_MAPCACHEPAGE },
        { "SETCACHEPAGE",       VM_SETCACHEPAGE },
+       { "CLEARCACHE",         VM_CLEARCACHE },
        { "VFS_MMAP",           VM_VFS_MMAP },
        { "VFS_REPLY",          VM_VFS_REPLY },
        { NULL,                 0 },
index dc81ce5ce92eb889af59121e63a0930c1fdf3996..950cd6b08670b25752507718d2788d5655921673 100644 (file)
@@ -110,7 +110,7 @@ service mfs
 {
        ipc     ALL_SYS;        # All system ipc targets allowed
        system  BASIC;          # Only basic kernel calls allowed
-       vm      MAPCACHEPAGE SETCACHEPAGE;
+       vm      MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
        io      NONE;           # No I/O range allowed
        irq     NONE;           # No IRQ allowed
        sigmgr          rs;     # Signal manager is RS
@@ -137,7 +137,7 @@ service ext2
 {
        ipc     ALL_SYS;        # All system ipc targets allowed
        system  BASIC;          # Only basic kernel calls allowed
-       vm      MAPCACHEPAGE SETCACHEPAGE;
+       vm      MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
        io      NONE;           # No I/O range allowed
        irq     NONE;           # No IRQ allowed
        sigmgr          rs;     # Signal manager is RS
@@ -150,7 +150,7 @@ service pfs
 {
        ipc     ALL_SYS;        # All system ipc targets allowed
        system  BASIC;          # Only basic kernel calls allowed
-       vm      MAPCACHEPAGE SETCACHEPAGE;
+       vm      MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
        io      NONE;           # No I/O range allowed
        irq     NONE;           # No IRQ allowed
        sigmgr          rs;     # Signal manager is RS
index c7629f0b637d24f32de771ccf52c2388b10175ae..3847825f701b25fdd63ebc5f13b2fc1ebc6b40ad 100644 (file)
 /* To VM: identify cache block in FS */
 #define VM_SETCACHEPAGE                (VM_RQ_BASE+27)
 
+/* To VM: clear all cache blocks for a device */
+#define VM_CLEARCACHE          (VM_RQ_BASE+28)
+
 /* To VFS: fields for request from VM. */
 #      define VFS_VMCALL_REQ           m10_i1
 #      define VFS_VMCALL_FD            m10_i2
index a4388ddb394e0fde0ba481fe18a45d43436a00d6..f41cbf0029078fc20c4b570684a3048647bad4c9 100644 (file)
@@ -72,6 +72,8 @@ int vm_set_cacheblock(void *block, u32_t dev, u64_t dev_offset,
 void *vm_map_cacheblock(u32_t dev, u64_t dev_offset,
         u64_t ino, u64_t ino_offset, u32_t *flags, int blocksize);
 
+int vm_clear_cache(u32_t dev);
+
 /* flags for vm cache functions */
 #define VMMC_FLAGS_LOCKED      0x01    /* someone is updating the flags; don't read/write */
 #define VMMC_DIRTY             0x02    /* dirty buffer and it may not be evicted */
index 0f2f78ed6ed961a71ec64c38bafe2c6e7fd055ae..1968918ed6fdfe7b395d20ed9a09b8595c418067 100644 (file)
@@ -577,6 +577,8 @@ void lmfs_invalidate(
                bp->data = NULL;
        }
   }
+
+  vm_clear_cache(device);
 }
 
 /*===========================================================================*
index ce844acf0cae6ae54c61f02bd0e7c22e25a109bd..171ba39c8ed65004e93a29611ea61a6e38c04b85 100644 (file)
@@ -60,3 +60,17 @@ int vm_set_cacheblock(void *block, u32_t dev, u64_t dev_offset,
        return vm_cachecall(&m, VM_SETCACHEPAGE, block, dev, dev_offset,
                ino, ino_offset, flags, blocksize);
 }
+
+int
+vm_clear_cache(u32_t dev)
+{
+       message m;
+
+       assert(dev != NO_DEV);
+
+       memset(&m, 0, sizeof(m));
+
+       m.m_u.m_vmmcp.dev = dev;
+
+       return _taskcall(VM_PROC_NR, VM_CLEARCACHE, &m);
+}
index f97edc0621456c066ff47f02bb84a98a7633a349..c2d76ff1f48a04ee9bacca843b3e33680bbfe2c8 100644 (file)
@@ -241,6 +241,9 @@ int fs_unmount()
   /* Close the device the file system lives on. */
   bdev_close(fs_dev);
 
+  /* Throw all blocks out of the VM cache, to prevent corruption later. */
+  lmfs_invalidate(fs_dev);
+
   /* Finish off the unmount. */
   superblock->s_dev = NO_DEV;
   unmountdone = TRUE;
index 60a6b50f771ff17032d46d486504155c80965374..efdcb299b0e45d3c2e0ba2113875a453d6a7aa86 100644 (file)
@@ -187,6 +187,9 @@ int fs_unmount()
   /* Close the device the file system lives on. */
   bdev_close(fs_dev);
 
+  /* Throw out blocks out of the VM cache, to prevent corruption later. */
+  lmfs_invalidate(fs_dev);
+
   /* Finish off the unmount. */
   superblock.s_dev = NO_DEV;
   unmountdone = TRUE;
index fd6be5ab3e683a578efd02a6f37700b3ee6f53cd..6935357d0924a91de6aee0495e7d2c4f02df11fd 100644 (file)
@@ -304,6 +304,25 @@ int cache_freepages(int pages)
        return freed;
 }
 
+/*
+ * Remove all pages that are associated with the given device.
+ */
+void
+clear_cache_bydev(dev_t dev)
+{
+       struct cached_page *cp, *ncp;
+       int h;
+
+       for (h = 0; h < HASHSIZE; h++) {
+               for (cp = cache_hash_bydev[h]; cp != NULL; cp = ncp) {
+                       ncp = cp->hash_next_dev;
+
+                       if (cp->dev == dev)
+                               rmcache(cp);
+               }
+       }
+}
+
 void get_stats_info(struct vm_stats_info *vsi)
 {
         vsi->vsi_cached = cached_pages;
index c882cf068ee9e18dcaeb7919e7af3d6eb27bb58c..58fe36a6cb37c24bef5f362b76ff064c736ec56e 100644 (file)
@@ -485,6 +485,7 @@ void init_vm(void)
        /* Cache blocks. */
        CALLMAP(VM_MAPCACHEPAGE, do_mapcache);
        CALLMAP(VM_SETCACHEPAGE, do_setcache);
+       CALLMAP(VM_CLEARCACHE, do_clearcache);
 
        /* getrusage */
        CALLMAP(VM_GETRUSAGE, do_getrusage);
index 674efe4c732daeffd671744e979930e2d43c15d1..6a359d77cb2aa2053688e7e4f2ee6795084859b5 100644 (file)
@@ -238,3 +238,17 @@ do_setcache(message *msg)
        return OK;
 }
 
+/*
+ * A file system wants to invalidate all pages belonging to a certain device.
+ */
+int
+do_clearcache(message *msg)
+{
+       dev_t dev;
+
+       dev = msg->m_u.m_vmmcp.dev;
+
+       clear_cache_bydev(dev);
+
+       return OK;
+}
index 5092a875f088a6f5c9b48e398eba84414f9910a8..995a99e6d5560122a19e249a9030b70b642b603f 100644 (file)
@@ -218,6 +218,7 @@ void shared_setsource(struct vir_region *vr, endpoint_t ep, struct vir_region *s
 /* mem_cache.c */
 int do_mapcache(message *m);
 int do_setcache(message *m);
+int do_clearcache(message *m);
 
 /* cache.c */
 struct cached_page *find_cached_page_bydev(dev_t dev, u64_t dev_off,
@@ -229,6 +230,7 @@ int cache_freepages(int pages);
 void get_stats_info(struct vm_stats_info *vsi);
 void cache_lru_touch(struct cached_page *hb);
 void rmcache(struct cached_page *cp);
+void clear_cache_bydev(dev_t dev);
 
 /* vfs.c */
 int vfs_request(int reqno, int fd, struct vmproc *vmp, u64_t offset,
index 9c6ff3f90b5a473b286d9eb53db2e105276ff387..4407fc239ab76e9410aacbeb82650a1045deffcd 100644 (file)
@@ -224,16 +224,6 @@ panic(const char *fmt, ...)
        exit(1);
 }
 
-int vm_forgetblock(u64_t id)
-{
-       return ENOSYS;
-}
-
-void vm_forgetblocks(void)
-{
-       return;
-}
-
 int
 vm_info_stats(struct vm_stats_info *vsi)
 {
@@ -274,6 +264,11 @@ void *vm_map_cacheblock(u32_t dev, u64_t dev_offset,
        return MAP_FAILED;
 }
 
+int vm_clear_cache(u32_t dev)
+{
+       return 0;
+}
+
 int
 main(int argc, char *argv[])
 {
index d42d211a9ec4caec4c2b55f7916cbd9c2d390daf..847f93e120ee380f32c0407953fe30c30ae13719 100644 (file)
@@ -177,6 +177,8 @@ main(int argc, char *argv[])
 
        writepipe(&info);
 
+       vm_clear_cache(MYDEV);
+
        return 0;
 }
 
index 24aed285e6410688673096f6088764e0ca6bc40e..ec42c0e252b030f4f6e8d03152b65cd645f5b6ae 100644 (file)
@@ -1,7 +1,7 @@
 service testvm {
        ipc     ALL;    # All system ipc targets allowed
        system  BASIC;          # Only basic kernel calls allowed
-       vm      MAPCACHEPAGE SETCACHEPAGE;
+       vm      MAPCACHEPAGE SETCACHEPAGE CLEARCACHE;
        io      NONE;           # No I/O range allowed
        irq     NONE;           # No IRQ allowed
        sigmgr          rs;     # Signal manager is RS