From owner-svn-src-head@freebsd.org Mon Nov 16 01:30:00 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4A239A2F5EE; Mon, 16 Nov 2015 01:30:00 +0000 (UTC) (envelope-from jmg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 06E091965; Mon, 16 Nov 2015 01:29:59 +0000 (UTC) (envelope-from jmg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tAG1TxFr080630; Mon, 16 Nov 2015 01:29:59 GMT (envelope-from jmg@FreeBSD.org) Received: (from jmg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tAG1Tx0V080628; Mon, 16 Nov 2015 01:29:59 GMT (envelope-from jmg@FreeBSD.org) Message-Id: <201511160129.tAG1Tx0V080628@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jmg set sender to jmg@FreeBSD.org using -f From: John-Mark Gurney Date: Mon, 16 Nov 2015 01:29:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r290900 - head/sbin/restore X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Nov 2015 01:30:00 -0000 Author: jmg Date: Mon Nov 16 01:29:58 2015 New Revision: 290900 URL: https://svnweb.freebsd.org/changeset/base/290900 Log: If you backup a large file that is mostly holes, previously we'd issue a seek for every block... For large (Exabyte sized files) this would issue lots of unneeded seeks, so combine them... Thanks for the work Jan, sorry took so long to commit... And an item completed off the IdeasPage! Submitted by: Jan Sucan Modified: head/sbin/restore/tape.c Modified: head/sbin/restore/tape.c ============================================================================== --- head/sbin/restore/tape.c Mon Nov 16 01:09:25 2015 (r290899) +++ head/sbin/restore/tape.c Mon Nov 16 01:29:58 2015 (r290900) @@ -107,6 +107,7 @@ static char *setupextattr(int); static void xtrattr(char *, long); static void set_extattr_link(char *, void *, int); static void set_extattr_fd(int, char *, void *, int); +static void skiphole(void (*)(char *, long), long *); static int gethead(struct s_spcl *); static void readtape(char *); static void setdumpnum(void); @@ -927,6 +928,20 @@ skipfile(void) } /* + * Skip a hole in an output file + */ +static void +skiphole(void (*skip)(char *, long), long *seekpos) +{ + char buf[MAXBSIZE]; + + if (*seekpos > 0) { + (*skip)(buf, *seekpos); + *seekpos = 0; + } +} + +/* * Extract a file from the tape. * When an allocated block is found it is passed to the fill function; * when an unallocated block (hole) is found, a zeroed buffer is passed @@ -938,14 +953,15 @@ getfile(void (*datafill)(char *, long), { int i; off_t size; + long seekpos; int curblk, attrsize; void (*fillit)(char *, long); - static char clearedbuf[MAXBSIZE]; char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; char junk[TP_BSIZE]; curblk = 0; size = spcl.c_size; + seekpos = 0; attrsize = spcl.c_extsize; if (spcl.c_type == TS_END) panic("ran off end of tape\n"); @@ -974,22 +990,30 @@ loop: if (readmapflag || spcl.c_addr[i]) { readtape(&buf[curblk++][0]); if (curblk == fssize / TP_BSIZE) { + skiphole(skip, &seekpos); (*fillit)((char *)buf, (long)(size > TP_BSIZE ? fssize : (curblk - 1) * TP_BSIZE + size)); curblk = 0; } } else { if (curblk > 0) { + skiphole(skip, &seekpos); (*fillit)((char *)buf, (long)(size > TP_BSIZE ? curblk * TP_BSIZE : (curblk - 1) * TP_BSIZE + size)); curblk = 0; } - (*skip)(clearedbuf, (long)(size > TP_BSIZE ? - TP_BSIZE : size)); + /* + * We have a block of a hole. Don't skip it + * now, because there may be next adjacent + * block of the hole in the file. Postpone the + * seek until next file write. + */ + seekpos += (long)(size > TP_BSIZE ? TP_BSIZE : size); } if ((size -= TP_BSIZE) <= 0) { if (size > -TP_BSIZE && curblk > 0) { + skiphole(skip, &seekpos); (*fillit)((char *)buf, (long)((curblk * TP_BSIZE) + size)); curblk = 0;