Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Jul 2002 12:18:21 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Andreas Koch <koch@eis.cs.tu-bs.de>
Cc:        freebsd-stable@FreeBSD.ORG
Subject:   Re: 4.6-RC: Glacial speed of dump backups
Message-ID:  <200207221918.g6MJILhI054586@apollo.backplane.com>
References:  <20020606204948.GA4540@ultra4.eis.cs.tu-bs.de> <20020722081614.E367@gsmx07.alcatel.com.au> <20020722100408.GP26095@ultra4.eis.cs.tu-bs.de>

next in thread | previous in thread | raw e-mail | index | archive | help
    Hi guys.  I've been following this thread and it occured to me
    that it might be possible to write a very quick cache if we 
    ignored shareability between forked dumps.

    I've done so.   It actually does appear to make a considerable
    difference even with a tiny (4MB default) cache.  Please try the 
    below patch and tell me what you think.  It isn't perfect and 
    I'm sure bad things could happen on machines which do not have
    much memory, and I haven't tested it all that much, but....

						-Matt

:Peter,
:
:many thanks for the reply, I had already given up hope of seeing one
:at all :-)
:
:I have already been looking at the NetBSD dump shortly after my initial
:message. Their version has a _considerably_ improved internal buffering
:architecture.  However, my time-limited porting efforts have not been
:...
:So, it appears some more effort is required here.  I plan to look into
:this more closely, but I am currently swamped at work.  However, the
:potential gains seem to be worthwhile:  On our preliminary benchmarks,
:NetBSD dump running on a low-end Athlon (from a 7.2K rpm SCSI disk)
:_easily_ beats the backup throughput of Solaris 2.8 dump (mirrored 15K
:rpm SCSI disks) on a U280R (2x USIII+ 1GHz).
:
:Andreas Koch
: -- for now making do with the dump | team kludge ...
:-- 
:Andreas Koch                                      Email  : koch@eis.cs.tu-bs.de


Index: Makefile
===================================================================
RCS file: /home/ncvs/src/sbin/dump/Makefile,v
retrieving revision 1.12.2.2
diff -u -r1.12.2.2 Makefile
--- Makefile	5 Oct 2001 15:49:11 -0000	1.12.2.2
+++ Makefile	22 Jul 2002 17:31:09 -0000
@@ -17,7 +17,7 @@
 LINKS=	${BINDIR}/dump ${BINDIR}/rdump
 CFLAGS+=-DRDUMP
 CFLAGS+=-I${.CURDIR}/../../libexec/rlogind
-SRCS=	itime.c main.c optr.c dumprmt.c tape.c traverse.c unctime.c
+SRCS=	itime.c main.c optr.c dumprmt.c tape.c traverse.c unctime.c cache.c
 MAN=	dump.8
 MLINKS+=dump.8 rdump.8
 
Index: cache.c
===================================================================
RCS file: cache.c
diff -N cache.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ cache.c	22 Jul 2002 19:15:21 -0000
@@ -0,0 +1,129 @@
+/*
+ * CACHE.C
+ *
+ *	Block cache for dump
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#ifdef sunos
+#include <sys/vnode.h>
+
+#include <ufs/fs.h>
+#include <ufs/fsdir.h>
+#include <ufs/inode.h>
+#else
+#include <ufs/ufs/dir.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+#endif
+
+#include <protocols/dumprestore.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#ifdef __STDC__
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+#include "dump.h"
+
+typedef struct Block {
+	struct Block	*b_HNext;	/* must be first field */
+	off_t		b_Offset;
+	char		*b_Data;
+} Block;
+
+#define HFACTOR		4
+
+static char  *DataBase;
+static Block **BlockHash;
+static int   BlockSize;
+static int   HSize;
+static int   NBlocks;
+
+static void
+cinit(void)
+{
+	int i;
+	int hi;
+	Block *base;
+
+	if ((BlockSize = sblock->fs_bsize * 4) > MAXBSIZE)
+		BlockSize = MAXBSIZE;
+	NBlocks = cachesize / BlockSize;
+	HSize = NBlocks / HFACTOR;
+
+	msg("Cache %d MB, blocksize = %d\n", NBlocks * BlockSize, BlockSize);
+
+	base = calloc(sizeof(Block), NBlocks);
+	BlockHash = calloc(sizeof(Block *), HSize);
+	DataBase = mmap(NULL, NBlocks * BlockSize, 
+			PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
+	for (i = 0; i < NBlocks; ++i) {
+		base[i].b_Data = DataBase + i * BlockSize;
+		base[i].b_Offset = (off_t)-1;
+		hi = i / HFACTOR;
+		base[i].b_HNext = BlockHash[hi];
+		BlockHash[hi] = &base[i];
+	}
+}
+
+ssize_t
+cread(int fd, void *buf, size_t nbytes, off_t offset)
+{
+	Block *blk;
+	Block **pblk;
+	Block **ppblk;
+	int hi;
+	int n;
+	off_t mask;
+
+	if (sblock->fs_bsize && DataBase == NULL)
+		cinit();
+	mask = ~(off_t)(BlockSize - 1);
+	if (nbytes > BlockSize ||
+	    ((offset ^ (offset + nbytes - 1)) & mask) != 0) {
+		return(pread(fd, buf, nbytes, offset));
+	}
+	hi = (offset / BlockSize) % HSize;
+	pblk = &BlockHash[hi];
+	ppblk = NULL;
+	while ((blk = *pblk) != NULL) {
+		if (((blk->b_Offset ^ offset) & mask) == 0) {
+#if 0
+			fprintf(stderr, "%08llx %d (%08x)\n", offset, nbytes, 
+			    sblock->fs_size * sblock->fs_fsize);
+#endif
+			break;
+		}
+		ppblk = pblk;
+		pblk = &blk->b_HNext;
+	}
+	if (blk == NULL) {
+		blk = *ppblk;
+		pblk = ppblk;
+		blk->b_Offset = offset & mask;
+		n = pread(fd, blk->b_Data, BlockSize, blk->b_Offset);
+		if (n != BlockSize) {
+			blk->b_Offset = (off_t)-1;
+			blk = NULL;
+		}
+	}
+	if (blk) {
+		bcopy(blk->b_Data + (offset - blk->b_Offset), buf, nbytes);
+		*pblk = blk->b_HNext;
+		blk->b_HNext = BlockHash[hi];
+		BlockHash[hi] = blk;
+		return(nbytes);
+	} else {
+		return(pread(fd, buf, nbytes, offset));
+	}
+}
+
Index: dump.h
===================================================================
RCS file: /home/ncvs/src/sbin/dump/dump.h,v
retrieving revision 1.7.6.3
diff -u -r1.7.6.3 dump.h
--- dump.h	23 Feb 2002 22:32:51 -0000	1.7.6.3
+++ dump.h	22 Jul 2002 18:21:01 -0000
@@ -77,6 +77,7 @@
 int	etapes;		/* estimated number of tapes */
 int	nonodump;	/* if set, do not honor UF_NODUMP user flags */
 int	unlimited;	/* if set, write to end of medium */
+int	cachesize;	/* size of block cache */
 
 int	notify;		/* notify operator flag */
 int	blockswritten;	/* number of blocks written on current tape */
Index: main.c
===================================================================
RCS file: /home/ncvs/src/sbin/dump/main.c,v
retrieving revision 1.20.2.8
diff -u -r1.20.2.8 main.c
--- main.c	1 Jul 2002 00:35:49 -0000	1.20.2.8
+++ main.c	22 Jul 2002 18:51:37 -0000
@@ -84,6 +84,7 @@
 int	ntrec = NTREC;	/* # tape blocks in each tape record */
 int	cartridge = 0;	/* Assume non-cartridge tape */
 int	dokerberos = 0;	/* Use Kerberos authentication */
+int	cachesize = 4 * 1024 * 1024;	/* block cache size */
 long	dev_bsize = 1;	/* recalculated below */
 long	blocksperfile;	/* output blocks per file */
 char	*host = NULL;	/* remote host (if any) */
@@ -125,9 +126,9 @@
 
 	obsolete(&argc, &argv);
 #ifdef KERBEROS
-#define optstring "0123456789aB:b:cd:f:h:kns:ST:uWwD:"
+#define optstring "0123456789aB:b:cd:f:h:kns:ST:uWwD:C:"
 #else
-#define optstring "0123456789aB:b:cd:f:h:ns:ST:uWwD:"
+#define optstring "0123456789aB:b:cd:f:h:ns:ST:uWwD:C:"
 #endif
 	while ((ch = getopt(argc, argv, optstring)) != -1)
 #undef optstring
@@ -168,6 +169,10 @@
 
 		case 'D':
 			dumpdates = optarg;
+			break;
+
+		case 'C':
+			cachesize = numarg("cachesize", 0, 0) * 1024 * 1024;
 			break;
 
 		case 'h':
Index: traverse.c
===================================================================
RCS file: /home/ncvs/src/sbin/dump/traverse.c,v
retrieving revision 1.10.2.4
diff -u -r1.10.2.4 traverse.c
--- traverse.c	14 Jul 2001 13:51:37 -0000	1.10.2.4
+++ traverse.c	22 Jul 2002 17:31:33 -0000
@@ -601,7 +601,7 @@
 	int cnt, i;
 
 loop:
-	if ((cnt = pread(diskfd, buf, size, ((off_t)blkno << dev_bshift))) ==
+	if ((cnt = cread(diskfd, buf, size, ((off_t)blkno << dev_bshift))) ==
 						size)
 		return;
 	if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) {

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200207221918.g6MJILhI054586>