summaryrefslogtreecommitdiffstats
path: root/sys/nfsserver
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2002-07-10 17:02:32 +0000
committerdillon <dillon@FreeBSD.org>2002-07-10 17:02:32 +0000
commitda4e111a550227f9bab8d24999ea76a11cc5b780 (patch)
treee267b121c9bda07891245d5c4f7da3f13b8e5cdf /sys/nfsserver
parente555a85c675bd5ce423b4c39497e6569cd3d3e1b (diff)
downloadFreeBSD-src-da4e111a550227f9bab8d24999ea76a11cc5b780.zip
FreeBSD-src-da4e111a550227f9bab8d24999ea76a11cc5b780.tar.gz
Replace the global buffer hash table with per-vnode splay trees using a
methodology similar to the vm_map_entry splay and the VM splay that Alan Cox is working on. Extensive testing has appeared to have shown no increase in overhead. Disadvantages Dirties more cache lines during lookups. Not as fast as a hash table lookup (but still N log N and optimal when there is locality of reference). Advantages vnode->v_dirtyblkhd is now perfectly sorted, making fsync/sync/filesystem syncer operate more efficiently. I get to rip out all the old hacks (some of which were mine) that tried to keep the v_dirtyblkhd tailq sorted. The per-vnode splay tree should be easier to lock / SMPng pushdown on vnodes will be easier. This commit along with another that Alan is working on for the VM page global hash table will allow me to implement ranged fsync(), optimize server-side nfs commit rpcs, and implement partial syncs by the filesystem syncer (aka filesystem syncer would detect that someone is trying to get the vnode lock, remembers its place, and skip to the next vnode). Note that the buffer cache splay is somewhat more complex then other splays due to special handling of background bitmap writes (multiple buffers with the same lblkno in the same vnode), and B_INVAL discontinuities between the old hash table and the existence of the buffer on the v_cleanblkhd list. Suggested by: alc
Diffstat (limited to 'sys/nfsserver')
-rw-r--r--sys/nfsserver/nfs_serv.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 73bee42..131c0b4 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -3695,8 +3695,14 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
* If we have a buffer and it is marked B_DELWRI we
* have to lock and write it. Otherwise the prior
* write is assumed to have already been committed.
+ *
+ * gbincore() can return invalid buffers now so we
+ * have to check that bit as well (though B_DELWRI
+ * should not be set if B_INVAL is set there could be
+ * a race here since we haven't locked the buffer).
*/
- if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) {
+ if ((bp = gbincore(vp, lblkno)) != NULL &&
+ (bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI) {
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL);
continue; /* retry */
OpenPOWER on IntegriCloud