kernel - SWAP CACHE part 19/many - distinguish bulk data in HAMMER block dev
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 12 Feb 2010 04:54:05 +0000 (20:54 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 12 Feb 2010 05:00:33 +0000 (21:00 -0800)
* Add buf->flags/B_NOTMETA, vm_page->flags/PG_NOTMETA.  If set the pages
  underlying the buffer will not be considered meta-data from the
  point of view of the swapcache.

* HAMMER must sometimes access bulk data via the block device instead of
  via a file vnode.  For example, the reblocking and mirroring code.
  We do not want this data to be misinterpreted as meta-data when
  the meta-data-only swapcache is turned on, otherwise it will blow
  out the actual meta-data in the swapcache.

  HAMMER_RECTYPE_DATA and HAMMER_RECTYPE_DB are considered normal data.
  All other record types (e.g. direntry, inode, etc) are meta-data.

sys/kern/vfs_bio.c
sys/sys/buf.h
sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_io.c
sys/vfs/hammer/hammer_reblock.c
sys/vm/vm_page.h
sys/vm/vm_swapcache.c

index ff55bd6..c5c9e6e 100644 (file)
@@ -1645,6 +1645,13 @@ vfs_vmio_release(struct buf *bp)
                m = bp->b_xio.xio_pages[i];
                bp->b_xio.xio_pages[i] = NULL;
 
+               /*
+                * The VFS is telling us this is not a meta-data buffer
+                * even if it is backed by a block device.
+                */
+               if (bp->b_flags & B_NOTMETA)
+                       vm_page_flag_set(m, PG_NOTMETA);
+
                /*
                 * This is a very important bit of code.  We try to track
                 * VM page use whether the pages are wired into the buffer
index 1b4cc0d..0eb08f1 100644 (file)
@@ -275,11 +275,17 @@ struct buf {
  *     B_NOCACHE       Request that the buffer and backing store be
  *                     destroyed on completion.  If B_DELWRI is set and the
  *                     write fails, the buffer remains intact.
+ *
+ *     B_NOTMETA       May be set on block device buffers representing
+ *                     file data (i.e. which aren't really meta-data),
+ *                     which will cause the buffer cache to set PG_NOTMETA
+ *                     in the VM pages when releasing them and the
+ *                     swapcache to not try to cache them.
  */
 
 #define        B_AGE           0x00000001      /* Reuse more quickly */
 #define        B_NEEDCOMMIT    0x00000002      /* Append-write in progress. */
-#define        B_UNUSED2       0x00000004
+#define        B_NOTMETA       0x00000004      /* This really isn't metadata */
 #define        B_DIRECT        0x00000008      /* direct I/O flag (pls free vmio) */
 #define        B_DEFERRED      0x00000010      /* vfs-controlled deferment */
 #define        B_CACHE         0x00000020      /* Bread found us in the cache. */
index 96a8108..b41a16c 100644 (file)
@@ -1286,6 +1286,7 @@ void hammer_io_clear_modify(struct hammer_io *io, int inval);
 void hammer_io_clear_modlist(struct hammer_io *io);
 void hammer_io_flush_sync(hammer_mount_t hmp);
 void hammer_io_clear_error(struct hammer_io *io);
+void hammer_io_notmeta(hammer_buffer_t buffer);
 
 void hammer_modify_volume(hammer_transaction_t trans, hammer_volume_t volume,
                        void *base, int len);
index bfa7e93..fc093e0 100644 (file)
@@ -726,6 +726,26 @@ hammer_btree_extract(hammer_cursor_t cursor, int flags)
        KKASSERT(data_len >= 0 && data_len <= HAMMER_XBUFSIZE);
        cursor->data = hammer_bread_ext(hmp, data_off, data_len,
                                        &error, &cursor->data_buffer);
+
+       /*
+        * Mark the data buffer as not being meta-data if it isn't
+        * meta-data (sometimes bulk data is accessed via a volume
+        * block device).
+        */
+       if (error == 0) {
+               switch(elm->leaf.base.rec_type) {
+               case HAMMER_RECTYPE_DATA:
+               case HAMMER_RECTYPE_DB:
+                       hammer_io_notmeta(cursor->data_buffer);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /*
+        * Deal with CRC errors on the extracted data.
+        */
        if (error == 0 &&
            hammer_crc_test_leaf(cursor->data, &elm->leaf) == 0) {
                kprintf("CRC DATA @ %016llx/%d FAILED\n",
index d679e64..5842b56 100644 (file)
@@ -208,6 +208,21 @@ hammer_io_clear_error(struct hammer_io *io)
        }
 }
 
+/*
+ * This is an advisory function only which tells the buffer cache
+ * the bp is not a meta-data buffer, even though it is backed by
+ * a block device.
+ *
+ * This is used by HAMMER's reblocking code to avoid trying to
+ * swapcache the filesystem's data when it is read or written
+ * by the reblocking code.
+ */
+void
+hammer_io_notmeta(hammer_buffer_t buffer)
+{
+       buffer->io.bp->b_flags |= B_NOTMETA;
+}
+
 
 #define HAMMER_MAXRA   4
 
index 5acae81..a27a1be 100644 (file)
@@ -389,6 +389,7 @@ hammer_reblock_data(struct hammer_ioc_reblock *reblock,
                                  0, &error);
        if (error)
                goto done;
+       hammer_io_notmeta(data_buffer);
 
        /*
         * Move the data
index e9ecc14..d04f48c 100644 (file)
@@ -337,6 +337,8 @@ extern struct vpgqueues vm_page_queues[PQ_COUNT];
 #define PG_MARKER      0x1000          /* special queue marker page */
 #define PG_RAM         0x2000          /* read ahead mark */
 #define PG_SWAPPED     0x4000          /* backed by swap */
+#define PG_NOTMETA     0x8000          /* do not back with swap */
+       /* u_short, only 16 flag bits */
 
 /*
  * Misc constants.
index f2db5fe..ee316c7 100644 (file)
@@ -417,7 +417,7 @@ vm_swapcache_test(vm_page_t m)
 {
        vm_object_t object;
 
-       if (m->flags & (PG_BUSY | PG_UNMANAGED))
+       if (m->flags & (PG_BUSY | PG_UNMANAGED | PG_NOTMETA))
                return(1);
        if (m->busy || m->hold_count || m->wire_count)
                return(1);