Changes needed in buffercache(9) for WAPBL

- All changes needed in vfs_bio.c
- Adding WAPBL headers
- Introducing buf_adjcnt to inform wapbl when a buffer has changed its size (get
  it from Bitrig)

Hi guys, with this diff I'm trying to introduce WAPBL to OpenBSD a
little more splitted than before.

If someone want to see all the implementation, you can get it on
https://github.com/radixo/openbsd-src/tree/wapbl

I hope to get the feature as soon as possible in OpenBSD.
Thanks in advance guys. :)

Index: sys/kern/vfs_bio.c
===================================================================
RCS file: /Volumes/CSP/cvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.170
diff -u -r1.170 vfs_bio.c
--- sys/kern/vfs_bio.c  19 Jul 2015 16:21:11 -0000      1.170
+++ sys/kern/vfs_bio.c  25 Nov 2015 14:37:01 -0000
@@ -56,7 +56,7 @@
 #include <sys/resourcevar.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
-#include <sys/specdev.h>
+#include <sys/wapbl.h>
 #include <uvm/uvm_extern.h>
 
 int nobuffers;
@@ -556,6 +556,16 @@
                mp = NULL;
 
        /*
+        * If using WAPBL, convert it to a delayed write 
+        */
+       if (mp && mp->mnt_wapbl) {
+               if (bp->b_iodone != mp->mnt_wapbl_op->wo_wapbl_biodone) {
+                       bdwrite(bp);
+                       return 0;
+               }
+       }
+       
+       /*
         * Remember buffer type, to switch on it later.  If the write was
         * synchronous, but the file system was mounted with MNT_ASYNC,
         * convert it to a delayed write.
@@ -628,7 +638,6 @@
        return (rv);
 }
 
-
 /*
  * Delayed write.
  *
@@ -647,6 +656,20 @@
 {
        int s;
 
+       /* If this is a tape block, write the block now. */
+       if (major(bp->b_dev) < nblkdev &&
+           bdevsw[major(bp->b_dev)].d_type == D_TAPE) {
+               bawrite(bp);
+               return;
+       }
+
+       if (wapbl_vphaswapbl(bp->b_vp)) {
+               struct mount *mp = wapbl_vptomp(bp->b_vp);
+
+               if (bp->b_iodone != mp->mnt_wapbl_op->wo_wapbl_biodone)
+                       WAPBL_ADD_BUF(mp, bp);
+       }
+
        /*
         * If the block hasn't been seen before:
         *      (1) Mark it as having been seen,
@@ -663,13 +686,6 @@
                curproc->p_ru.ru_oublock++;             /* XXX */
        }
 
-       /* If this is a tape block, write the block now. */
-       if (major(bp->b_dev) < nblkdev &&
-           bdevsw[major(bp->b_dev)].d_type == D_TAPE) {
-               bawrite(bp);
-               return;
-       }
-
        /* Otherwise, the "write" is done, so mark and release the buffer. */
        CLR(bp->b_flags, B_NEEDCOMMIT);
        SET(bp->b_flags, B_DONE);
@@ -743,12 +759,28 @@
         * Determine which queue the buffer should be on, then put it there.
         */
 
+       /* If it's locked, don't report an error; try again later */
+       if (ISSET(bp->b_flags, (B_LOCKED|B_ERROR)) == (B_LOCKED|B_ERROR))
+               CLR(bp->b_flags, B_ERROR);
+       
        /* If it's not cacheable, or an error, mark it invalid. */
        if (ISSET(bp->b_flags, (B_NOCACHE|B_ERROR)))
                SET(bp->b_flags, B_INVAL);
 
        if (ISSET(bp->b_flags, B_INVAL)) {
                /*
+                * If using WAPBL
+                */
+               if (ISSET(bp->b_flags, B_LOCKED)) {
+                       if (wapbl_vphaswapbl(bp->b_vp)) {
+                               struct mount *mp = wapbl_vptomp(bp->b_vp);
+                               KASSERT(bp->b_iodone
+                                   != mp->mnt_wapbl_op->wo_wapbl_biodone);
+                               WAPBL_REMOVE_BUF(mp, bp);
+                       }
+               }
+               
+               /*
                 * If the buffer is invalid, free it now rather than leaving
                 * it in a queue and wasting memory.
                 */
@@ -1079,6 +1111,19 @@
                        if (!ISSET(bp->b_flags, B_DELWRI))
                                panic("Clean buffer on dirty queue");
 #endif
+
+
+#ifdef WAPBL
+                       if (ISSET(bp->b_flags, B_LOCKED) &&
+                           wapbl_vphaswapbl(bp->b_vp)) {
+                               brelse(bp);
+                               struct mount *mp = wapbl_vptomp(bp->b_vp);
+                               wapbl_flush(mp->mnt_wapbl, 1);
+                               s = splbio();
+                               continue;
+                       }
+#endif /* WAPBL */
+                       
                        if (LIST_FIRST(&bp->b_dep) != NULL &&
                            !ISSET(bp->b_flags, B_DEFERRED) &&
                            buf_countdeps(bp, 0, 0)) {
@@ -1206,6 +1251,17 @@
 }
 #endif
 
+void
+buf_adjcnt(struct buf *bp, long ncount)
+{
+       KASSERT(ncount <= bp->b_bufsize);
+       long ocount = bp->b_bcount;
+       bp->b_bcount = ncount;
+       if (wapbl_vphaswapbl(bp->b_vp))
+               WAPBL_RESIZE_BUF(wapbl_vptomp(bp->b_vp), bp, bp->b_bufsize,
+                   ocount);
+}
+
 /* bufcache freelist code below */
 /*
  * Copyright (c) 2014 Ted Unangst <t...@openbsd.org>
Index: sys/sys/buf.h
===================================================================
RCS file: /Volumes/CSP/cvs/src/sys/sys/buf.h,v
retrieving revision 1.99
diff -u -r1.99 buf.h
--- sys/sys/buf.h       19 Jul 2015 16:21:11 -0000      1.99
+++ sys/sys/buf.h       25 Nov 2015 14:51:02 -0000
@@ -221,12 +221,14 @@
 #define        B_COLD          0x01000000      /* buffer is on the cold queue 
*/
 #define        B_BC            0x02000000      /* buffer is managed by the 
cache */
 #define        B_DMA           0x04000000      /* buffer is DMA reachable */
+#define        B_LOCKED        0x08000000      /* Locked in core (not 
reusable). */
 
 #define        B_BITS  "\20\001AGE\002NEEDCOMMIT\003ASYNC\004BAD\005BUSY" \
     "\006CACHE\007CALL\010DELWRI\011DONE\012EINTR\013ERROR" \
     "\014INVAL\015NOCACHE\016PHYS\017RAW\020READ" \
     "\021WANTED\022WRITEINPROG\023XXX(FORMAT)\024DEFERRED" \
-    "\025SCANNED\026DAEMON\027RELEASED\030WARM\031COLD\032BC\033DMA"
+    "\025SCANNED\026DAEMON\027RELEASED\030WARM\031COLD\032BC\033DMA" \
+    "\034LOCKED"
 
 /*
  * This structure describes a clustered I/O.  It is stored in the b_saveaddr
@@ -292,6 +294,7 @@
 void   bufinit(void);
 void   buf_dirty(struct buf *);
 void    buf_undirty(struct buf *);
+void   buf_adjcnt(struct buf *, long);
 int    bwrite(struct buf *);
 struct buf *getblk(struct vnode *, daddr_t, int, int, int);
 struct buf *geteblk(int);
Index: sys/sys/mount.h
===================================================================
RCS file: /Volumes/CSP/cvs/src/sys/sys/mount.h,v
retrieving revision 1.121
diff -u -r1.121 mount.h
--- sys/sys/mount.h     8 Sep 2014 01:47:06 -0000       1.121
+++ sys/sys/mount.h     25 Nov 2015 14:46:45 -0000
@@ -358,6 +358,11 @@
        int             mnt_maxsymlinklen;      /* max size of short symlink */
        struct statfs   mnt_stat;               /* cache of filesystem stats */
        void            *mnt_data;              /* private data */
+       struct wapbl_ops
+                       *mnt_wapbl_op;          /* logging ops */
+       struct wapbl    *mnt_wapbl;             /* log info */
+       struct wapbl_replay
+                       *mnt_wapbl_replay;      /* replay support XXX: what? */
 };
 
 /*
@@ -501,6 +506,51 @@
 extern int bufbackoff(struct uvm_constraint_range*, long);
 
 /*
+ * This operations vector is so wapbl can be wrapped into a filesystem lkm.
+ * XXX Eventually, we want to move this functionality
+ * down into the filesystems themselves so that this isn't needed.
+ */
+struct wapbl_ops {
+       void (*wo_wapbl_discard)(struct wapbl *);
+       int (*wo_wapbl_replay_isopen)(struct wapbl_replay *);
+       int (*wo_wapbl_replay_can_read)(struct wapbl_replay *, daddr_t, long);
+       int (*wo_wapbl_replay_read)(struct wapbl_replay *, void *, daddr_t,
+           long);
+       void (*wo_wapbl_add_buf)(struct wapbl *, struct buf *);
+       void (*wo_wapbl_remove_buf)(struct wapbl *, struct buf *);
+       void (*wo_wapbl_resize_buf)(struct wapbl *, struct buf *, long, long);
+       int (*wo_wapbl_begin)(struct wapbl *, const char *, int);
+       void (*wo_wapbl_end)(struct wapbl *);
+       void (*wo_wapbl_junlock_assert)(struct wapbl *);
+       void (*wo_wapbl_biodone)(struct buf *);
+};
+#define WAPBL_DISCARD(MP)                                              \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_discard)((MP)->mnt_wapbl)
+#define WAPBL_REPLAY_ISOPEN(MP)                                                
\
+    (*(MP)->mnt_wapbl_op->wo_wapbl_replay_isopen)((MP)->mnt_wapbl_replay)
+#define WAPBL_REPLAY_CAN_READ(MP, BLK, LEN)                            \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_replay_can_read)((MP)->mnt_wapbl_replay, \
+    (BLK), (LEN))
+#define WAPBL_REPLAY_READ(MP, DATA, BLK, LEN)                          \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_replay_read)((MP)->mnt_wapbl_replay,        
\
+    (DATA), (BLK), (LEN))
+#define WAPBL_ADD_BUF(MP, BP)                                          \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_add_buf)((MP)->mnt_wapbl, (BP))
+#define WAPBL_REMOVE_BUF(MP, BP)                                       \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_remove_buf)((MP)->mnt_wapbl, (BP))
+#define WAPBL_RESIZE_BUF(MP, BP, OLDSZ, OLDCNT)                                
\
+    (*(MP)->mnt_wapbl_op->wo_wapbl_resize_buf)((MP)->mnt_wapbl, (BP),  \
+    (OLDSZ), (OLDCNT))
+#define WAPBL_BEGIN(MP)                                                        
\
+    (*(MP)->mnt_wapbl_op->wo_wapbl_begin)((MP)->mnt_wapbl,             \
+    __FILE__, __LINE__)
+#define WAPBL_END(MP)                                                  \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_end)((MP)->mnt_wapbl)
+#define WAPBL_JUNLOCK_ASSERT(MP)                                       \
+    (*(MP)->mnt_wapbl_op->wo_wapbl_junlock_assert)((MP)->mnt_wapbl)
+
+
+/*
  * Operations supported on mounted file system.
  */
 struct nameidata;

Reply via email to