--- kernel/bsd/vfs/vfs_bio.c 2018/04/24 18:26:06 1.1.1.1 +++ kernel/bsd/vfs/vfs_bio.c 2018/04/24 18:31:23 1.1.1.2 @@ -151,8 +151,25 @@ int needbuffer; /* * Insq/Remq for the buffer free lists. */ -#define binsheadfree(bp, dp) TAILQ_INSERT_HEAD(dp, bp, b_freelist) -#define binstailfree(bp, dp) TAILQ_INSERT_TAIL(dp, bp, b_freelist) +#define binsheadfree(bp, dp) do { \ + TAILQ_INSERT_HEAD(dp, bp, b_freelist); \ + (bp)->b_timestamp = time.tv_sec; \ + } while (0) + +#define binstailfree(bp, dp) do { \ + TAILQ_INSERT_TAIL(dp, bp, b_freelist); \ + (bp)->b_timestamp = time.tv_sec; \ + } while (0) + + +/* Time in seconds before a buf on a list is considered as a stale buf */ +#define LRU_IS_STALE 120 /* default value for the LRU */ +#define AGE_IS_STALE 60 /* default value for the AGE */ + +int lru_is_stale = LRU_IS_STALE; +int age_is_stale = AGE_IS_STALE; + + void bremfree(bp) @@ -175,6 +192,7 @@ bremfree(bp) panic("bremfree: lost tail"); } TAILQ_REMOVE(dp, bp, b_freelist); + bp->b_timestamp = 0; } /* @@ -736,21 +754,46 @@ getnewbuf(slpflag, slptimeo) int slpflag, slptimeo; { register struct buf *bp; + register struct buf *lru_bp; + register struct buf *age_bp; + register int age_time, lru_time; int s; struct ucred *cred; start: s = splbio(); - if ((bp = bufqueues[BQ_AGE].tqh_first) != NULL || - (bp = bufqueues[BQ_LRU].tqh_first) != NULL) { - bremfree(bp); - } else { + + age_bp = bufqueues[BQ_AGE].tqh_first; + lru_bp = bufqueues[BQ_LRU].tqh_first; + + if (age_bp == NULL && lru_bp == NULL) { /* wait for a free buffer of any kind */ needbuffer = 1; tsleep(&needbuffer, slpflag|(PRIBIO+1), "getnewbuf", slptimeo); splx(s); return (0); } + if (age_bp == NULL) + bp = lru_bp; + else if (lru_bp == NULL) + bp = age_bp; + else { + if (((age_time = (time.tv_sec - age_bp->b_timestamp)) < 0) || + ((lru_time = (time.tv_sec - lru_bp->b_timestamp)) < 0)) { + /* time was set backwards */ + bp = age_bp; + /* + * we should probably re-timestamp eveything in the queues + * at this point with the current time + */ + } else { + if (lru_time >= lru_is_stale && age_time < age_is_stale) + bp = lru_bp; + else + bp = age_bp; + } + } + bremfree(bp); /* Buffer is no longer on free lists. */ SET(bp->b_flags, B_BUSY); @@ -973,6 +1016,7 @@ alloc_io_buf(vp) return (NULL); } TAILQ_REMOVE(&iobufqueue, bp, b_freelist); + bp->b_timestamp = 0; /* clear out various fields */ bp->b_flags = (B_BUSY | B_RAW);