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>