"tar tfv /dev/cd0" speedup patch

Juergen Lock nox at jelal.kn-bremen.de
Fri Feb 19 18:24:11 UTC 2010


On Thu, Feb 18, 2010 at 10:12:24PM -0800, Garrett Cooper wrote:
> On Thu, Feb 18, 2010 at 10:34 AM, Juergen Lock <nox at jelal.kn-bremen.de> wrote:
> > On Wed, Feb 17, 2010 at 10:38:30PM -0800, Tim Kientzle wrote:
> >> Juergen Lock wrote:
> >> >
> >> >  ...  since bsdtar/libarchive know iso9660 I just did the command in the
> >> > Subject.  It worked, but it was sloow... :(  Apparently it read all of
> >> > the disc without seeking.  The following patch fixes this, is something
> >> > like this desired?  If yes I could look how to do the same for Linux,
> >>
> >> Juergen,
> >>
> >> This is great!  If you can figure out how to get this
> >> right, I would really appreciate it.  If you have a
> >> tape drive handy, definitely test with that.  My first
> >> attempts here actually broke reading from tape drives,
> >> which is why the current code is so conservative.
> >>
> > Hmm I can't test on a tape atm but if I look at the kernel,
> >        http://fxr.watson.org/fxr/ident?i=DIOCGMEDIASIZE
> > DIOCGMEDIASIZE is only handled for geom, xen block devices, old CD drives
> > and pc98 floppies, and I'm pretty sure tapes don't use geom. :)
> >
> >> Minor style comments:
> >> >  else if (S_ISCHR(st.st_mode) &&
> >> >     !ioctl(fd, DIOCGMEDIASIZE, &mediasize) && mediasize) {
> >>
> >> Please be explicit:  S_ISCHR() && ioctl() == 0  && mediasize > 0
> >>
> >> >     archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
> >>
> >> extract_skip_file isn't needed here; we don't read the
> >> contents of device nodes.
> >>
> >> Let me know as soon as you have something you're confident of.
> >
> >  Ok here is a new version of the patch with these things fixed and the
> > Linux case added:  (Linux case not tested yet, and yes I did this on
> > stable/8.)
> >
> > Index: src/lib/libarchive/archive_read_open_filename.c
> > ===================================================================
> > RCS file: /home/scvs/src/lib/libarchive/archive_read_open_filename.c,v
> > retrieving revision 1.25.2.1
> > diff -u -p -r1.25.2.1 archive_read_open_filename.c
> > --- src/lib/libarchive/archive_read_open_filename.c     3 Aug 2009 08:13:06 -0000       1.25.2.1
> > +++ src/lib/libarchive/archive_read_open_filename.c     18 Feb 2010 18:14:16 -0000
> > @@ -44,6 +44,10 @@ __FBSDID("$FreeBSD: src/lib/libarchive/a
> >  #ifdef HAVE_UNISTD_H
> >  #include <unistd.h>
> >  #endif
> > +#ifdef __FreeBSD__
> > +#include <sys/ioctl.h>
> > +#include <sys/disk.h>
> > +#endif
> >
> >  #include "archive.h"
> >
> > @@ -83,6 +87,9 @@ archive_read_open_filename(struct archiv
> >        struct read_file_data *mine;
> >        void *b;
> >        int fd;
> > +#ifdef __FreeBSD__
> > +       off_t mediasize = 0;
> > +#endif
> >
> >        archive_clear_error(a);
> >        if (filename == NULL || filename[0] == '\0') {
> > @@ -143,6 +150,27 @@ archive_read_open_filename(struct archiv
> >                 */
> >                mine->can_skip = 1;
> >        }
> > +#ifdef __FreeBSD__
> > +       /*
> > +        * on FreeBSD if a device supports the DIOCGMEDIASIZE ioctl
> > +        * it is a disk-like device and should be seekable.
> > +        */
> > +       else if (S_ISCHR(st.st_mode) &&
> > +           ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0 && mediasize > 0) {
> > +               mine->can_skip = 1;
> > +       }
> > +#endif
> > +#ifdef __linux__
> 
> Is there any reason why a) you wouldn't check for other BSDs? b) you
> aren't doing something of the flavor...
> 
> #if defined(__FreeBSD__)
> 
> #elif defined(__linux__)
> 
> #endif

Okok, here's a new version of the patch that now also knows about
other BSDs and switched to #elif:  (only NetBSD actually tested tho
since I had a VM lying around, more testing welcome!)

 (Also if anyone wants to switch this to autoconf-style HAVE_FOO
handling they are welcome too... :)

 Enjoy,
	Juergen

Index: src/lib/libarchive/archive_read_open_filename.c
===================================================================
RCS file: /home/scvs/src/lib/libarchive/archive_read_open_filename.c,v
retrieving revision 1.25.2.1
diff -u -p -u -p -r1.25.2.1 archive_read_open_filename.c
--- src/lib/libarchive/archive_read_open_filename.c	3 Aug 2009 08:13:06 -0000	1.25.2.1
+++ src/lib/libarchive/archive_read_open_filename.c	19 Feb 2010 18:18:24 -0000
@@ -44,6 +44,17 @@ __FBSDID("$FreeBSD: src/lib/libarchive/a
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <sys/ioctl.h>
+#include <sys/disk.h>
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/dkio.h>
+#elif defined(__DragonFly__)
+#include <sys/ioctl.h>
+#include <sys/diskslice.h>
+#endif
 
 #include "archive.h"
 
@@ -83,6 +94,13 @@ archive_read_open_filename(struct archiv
 	struct read_file_data *mine;
 	void *b;
 	int fd;
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+	off_t mediasize = 0;
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+	struct disklabel dl;
+#elif defined(__DragonFly__)
+	struct partinfo pi;
+#endif
 
 	archive_clear_error(a);
 	if (filename == NULL || filename[0] == '\0') {
@@ -143,6 +161,45 @@ archive_read_open_filename(struct archiv
 		 */
 		mine->can_skip = 1;
 	}
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+	/*
+	 * on FreeBSD if a device supports the DIOCGMEDIASIZE ioctl
+	 * it is a disk-like device and should be seekable.
+	 */
+	else if (S_ISCHR(st.st_mode) &&
+	    ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0 && mediasize > 0) {
+		mine->can_skip = 1;
+	}
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+	/*
+	 * on Net/OpenBSD if a device supports the DIOCGDINFO ioctl
+	 * it is a disk-like device and should be seekable.
+	 */
+	else if ((S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) &&
+	    ioctl(fd, DIOCGDINFO, &dl) == 0 &&
+	    dl.d_partitions[DISKPART(st.st_rdev)].p_size > 0) {
+		mine->can_skip = 1;
+	}
+#elif defined(__DragonFly__)
+	/*
+	 * on DragonFly BSD if a device supports the DIOCGPART ioctl
+	 * it is a disk-like device and should be seekable.
+	 */
+	else if (S_ISCHR(st.st_mode) &&
+	    ioctl(fd, DIOCGPART, &pi) == 0 && pi.media_size > 0) {
+		mine->can_skip = 1;
+	}
+#elif defined(__linux__)
+	/*
+	 * on Linux just check whether its a block device and that
+	 * lseek works.  (Tapes are character devices there.)
+	 */
+	else if (S_ISBLK(st.st_mode) &&
+	    lseek(fd, 0, SEEK_CUR) == 0 && lseek(fd, 0, SEEK_SET) == 0 &&
+	    lseek(fd, 0, SEEK_END) > 0 && lseek(fd, 0, SEEK_SET) == 0) {
+		mine->can_skip = 1;
+	}
+#endif
 	return (archive_read_open2(a, mine,
 		NULL, file_read, file_skip, file_close));
 }


More information about the freebsd-hackers mailing list