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;