Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern Try to coalesce writes to the journal in MAXPHYS si...
details: https://anonhg.NetBSD.org/src/rev/45b9b69123c9
branches: trunk
changeset: 783155:45b9b69123c9
user: hannken <hannken%NetBSD.org@localhost>
date: Sat Dec 08 07:24:42 2012 +0000
description:
Try to coalesce writes to the journal in MAXPHYS sized and aligned blocks.
Speeds up wapbl_flush() on raid5 by a factor of 3-4.
Discussed on tech-kern.
Needs pullup to NetBSD-6.
diffstat:
sys/kern/vfs_wapbl.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 95 insertions(+), 5 deletions(-)
diffs (177 lines):
diff -r 9ee7560d46d8 -r 45b9b69123c9 sys/kern/vfs_wapbl.c
--- a/sys/kern/vfs_wapbl.c Sat Dec 08 07:05:23 2012 +0000
+++ b/sys/kern/vfs_wapbl.c Sat Dec 08 07:24:42 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_wapbl.c,v 1.53 2012/11/17 10:10:17 hannken Exp $ */
+/* $NetBSD: vfs_wapbl.c,v 1.54 2012/12/08 07:24:42 hannken Exp $ */
/*-
* Copyright (c) 2003, 2008, 2009 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
#define WAPBL_INTERNAL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_wapbl.c,v 1.53 2012/11/17 10:10:17 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_wapbl.c,v 1.54 2012/12/08 07:24:42 hannken Exp $");
#include <sys/param.h>
#include <sys/bitops.h>
@@ -184,6 +184,10 @@
SIMPLEQ_HEAD(, wapbl_entry) wl_entries; /* On disk transaction
accounting */
+
+ u_char *wl_buffer; /* l: buffer for wapbl_buffered_write() */
+ daddr_t wl_buffer_dblk; /* l: buffer disk block address */
+ size_t wl_buffer_used; /* l: buffer current use */
};
#ifdef WAPBL_DEBUG_PRINT
@@ -489,6 +493,9 @@
wl->wl_dealloclens = wapbl_alloc(sizeof(*wl->wl_dealloclens) *
wl->wl_dealloclim);
+ wl->wl_buffer = wapbl_alloc(MAXPHYS);
+ wl->wl_buffer_used = 0;
+
wapbl_inodetrk_init(wl, WAPBL_INODETRK_SIZE);
/* Initialize the commit header */
@@ -537,6 +544,7 @@
sizeof(*wl->wl_deallocblks) * wl->wl_dealloclim);
wapbl_free(wl->wl_dealloclens,
sizeof(*wl->wl_dealloclens) * wl->wl_dealloclim);
+ wapbl_free(wl->wl_buffer, MAXPHYS);
wapbl_inodetrk_free(wl);
wapbl_free(wl, sizeof(*wl));
@@ -716,6 +724,7 @@
sizeof(*wl->wl_deallocblks) * wl->wl_dealloclim);
wapbl_free(wl->wl_dealloclens,
sizeof(*wl->wl_dealloclens) * wl->wl_dealloclim);
+ wapbl_free(wl->wl_buffer, MAXPHYS);
wapbl_inodetrk_free(wl);
cv_destroy(&wl->wl_reclaimable_cv);
@@ -791,6 +800,81 @@
}
/*
+ * Flush buffered data if any.
+ */
+static int
+wapbl_buffered_flush(struct wapbl *wl)
+{
+ int error;
+
+ if (wl->wl_buffer_used == 0)
+ return 0;
+
+ error = wapbl_doio(wl->wl_buffer, wl->wl_buffer_used,
+ wl->wl_devvp, wl->wl_buffer_dblk, B_WRITE);
+ wl->wl_buffer_used = 0;
+
+ return error;
+}
+
+/*
+ * Write data to the log.
+ * Try to coalesce writes and emit MAXPHYS aligned blocks.
+ */
+static int
+wapbl_buffered_write(void *data, size_t len, struct wapbl *wl, daddr_t pbn)
+{
+ int error;
+ size_t resid;
+
+ /*
+ * If not adjacent to buffered data flush first. Disk block
+ * address is always valid for non-empty buffer.
+ */
+ if (wl->wl_buffer_used > 0 &&
+ pbn != wl->wl_buffer_dblk + btodb(wl->wl_buffer_used)) {
+ error = wapbl_buffered_flush(wl);
+ if (error)
+ return error;
+ }
+ /*
+ * If this write goes to an empty buffer we have to
+ * save the disk block address first.
+ */
+ if (wl->wl_buffer_used == 0)
+ wl->wl_buffer_dblk = pbn;
+ /*
+ * Remaining space so this buffer ends on a MAXPHYS boundary.
+ *
+ * Cannot become less or equal zero as the buffer would have been
+ * flushed on the last call then.
+ */
+ resid = MAXPHYS - dbtob(wl->wl_buffer_dblk % btodb(MAXPHYS)) -
+ wl->wl_buffer_used;
+ KASSERT(resid > 0);
+ KASSERT(dbtob(btodb(resid)) == resid);
+ if (len >= resid) {
+ memcpy(wl->wl_buffer + wl->wl_buffer_used, data, resid);
+ wl->wl_buffer_used += resid;
+ error = wapbl_doio(wl->wl_buffer, wl->wl_buffer_used,
+ wl->wl_devvp, wl->wl_buffer_dblk, B_WRITE);
+ data = (uint8_t *)data + resid;
+ len -= resid;
+ wl->wl_buffer_dblk = pbn + btodb(resid);
+ wl->wl_buffer_used = 0;
+ if (error)
+ return error;
+ }
+ KASSERT(len < MAXPHYS);
+ if (len > 0) {
+ memcpy(wl->wl_buffer + wl->wl_buffer_used, data, len);
+ wl->wl_buffer_used += len;
+ }
+
+ return 0;
+}
+
+/*
* Off is byte offset returns new offset for next write
* handles log wraparound
*/
@@ -813,7 +897,7 @@
#ifdef _KERNEL
pbn = btodb(pbn << wl->wl_log_dev_bshift);
#endif
- error = wapbl_write(data, slen, wl->wl_devvp, pbn);
+ error = wapbl_buffered_write(data, slen, wl, pbn);
if (error)
return error;
data = (uint8_t *)data + slen;
@@ -824,7 +908,7 @@
#ifdef _KERNEL
pbn = btodb(pbn << wl->wl_log_dev_bshift);
#endif
- error = wapbl_write(data, len, wl->wl_devvp, pbn);
+ error = wapbl_buffered_write(data, len, wl, pbn);
if (error)
return error;
off += len;
@@ -1967,6 +2051,9 @@
int error;
daddr_t pbn;
+ error = wapbl_buffered_flush(wl);
+ if (error)
+ return error;
/*
* flush disk cache to ensure that blocks we've written are actually
* written to the stable storage before the commit header.
@@ -1998,7 +2085,10 @@
#ifdef _KERNEL
pbn = btodb(pbn << wc->wc_log_dev_bshift);
#endif
- error = wapbl_write(wc, wc->wc_len, wl->wl_devvp, pbn);
+ error = wapbl_buffered_write(wc, wc->wc_len, wl, pbn);
+ if (error)
+ return error;
+ error = wapbl_buffered_flush(wl);
if (error)
return error;
Home |
Main Index |
Thread Index |
Old Index