svn commit: r272265 - user/marcel/mkimg

Marcel Moolenaar marcel at FreeBSD.org
Sun Sep 28 18:34:22 UTC 2014


Author: marcel
Date: Sun Sep 28 18:34:20 2014
New Revision: 272265
URL: http://svnweb.freebsd.org/changeset/base/272265

Log:
  Implement image_copyin_mapped():
  1.  If we can't seek, then let image_copyin_stream() deal with it.
  2.  Use SEEK_HOLE and SEEK_DATA to iterate over the regions of a
      sparse file.
  3.  Round or truncate to the sector size based on whether it's a
      hold or data. We truncate for holes and round for data. This to
      make sure to handle sparse files correctly when the sector size
      is larger than the file system's block/fragment size. Since we
      detect runts of zeroes for mmap'd data (to handle streams), we
      correct ourselves if such is applicable. We never mishandle
      data, which is the most important.
  
  I need to check with a file system that doesn't support sparse files
  what SEEK_HOLE and SEEK_DATA return. I'm thinking -1, which is what
  I don't handle yet. It's easy to do, because everything should be
  treated as data and we'll find the holes the hard way.
  
  While here: set DEBUG_FLAGS unconditionally to make sure I can always
  debug a core.

Modified:
  user/marcel/mkimg/Makefile
  user/marcel/mkimg/image.c

Modified: user/marcel/mkimg/Makefile
==============================================================================
--- user/marcel/mkimg/Makefile	Sun Sep 28 17:53:10 2014	(r272264)
+++ user/marcel/mkimg/Makefile	Sun Sep 28 18:34:20 2014	(r272265)
@@ -10,6 +10,8 @@ MKIMG_VERSION=20140927
 CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION}
 CFLAGS+=-DSPARSE_WRITE
 
+DEBUG_FLAGS=-O0 -gdwarf-2
+
 # List of formats to support
 SRCS+= \
 	qcow.c \

Modified: user/marcel/mkimg/image.c
==============================================================================
--- user/marcel/mkimg/image.c	Sun Sep 28 17:53:10 2014	(r272264)
+++ user/marcel/mkimg/image.c	Sun Sep 28 18:34:20 2014	(r272265)
@@ -307,8 +307,88 @@ image_copyin_stream(lba_t blk, int fd, u
 static int
 image_copyin_mapped(lba_t blk, int fd, uint64_t *sizep)
 {
+	off_t cur, data, end, hole, pos;
+	void *buf;
+	uint64_t bytesize;
+	size_t sz;
+	int error;
+
+	/*
+	 * We'd like to know the size of the file and we must
+	 * be able to seek in order to mmap(2). If this isn't
+	 * possible, then treat the file as a stream/pipe.
+	 */
+	end = lseek(fd, 0L, SEEK_END);
+	if (end == -1L)
+		return (image_copyin_stream(blk, fd, sizep));
+
+	/*
+	 * We need the file opened for the duration and our
+	 * caller is going to close the file. Make a dup(2)
+	 * so that control the faith of the descriptor.
+	 */
+	fd = dup(fd);
+	if (fd == -1)
+		return (errno);
 
-	return (image_copyin_stream(blk, fd, sizep));
+	bytesize = 0;
+	cur = pos = 0;
+	error = 0;
+	while (!error && cur < end) {
+		hole = lseek(fd, cur, SEEK_HOLE);
+		data = lseek(fd, cur, SEEK_DATA);
+
+		fprintf(stderr, "XXX: %s: cur=%jd, pos=%jd, hole=%jd, "
+		    "data=%jd\n", __func__, (intmax_t)cur, (intmax_t)pos,
+		    (intmax_t)hole, (intmax_t)data);
+
+		if (cur == hole && data > hole) {
+			hole = pos;
+			pos = data & ~(secsz - 1);
+
+			fprintf(stderr, "GAP %jd-%jd\n",
+			    (intmax_t)hole, (intmax_t)pos);
+
+			blk += (pos - hole) / secsz;
+			error = image_chunk_skipto(blk);
+
+			bytesize += pos - hole;
+			cur = data;
+		} else if (cur == data && hole > data) {
+			data = pos;
+			pos = (hole + secsz - 1) & ~(secsz - 1);
+
+			fprintf(stderr, "DATA %jd-%jd data\n",
+			    (intmax_t)data, (intmax_t)pos);
+
+			/* Sloppy... */
+			sz = pos - data;
+			assert((off_t)sz == pos - data);
+
+			buf = image_file_map(fd, data, sz);
+			if (buf != NULL) {
+				error = image_chunk_copyin(blk, buf, sz,
+				    data, fd);
+				image_file_unmap(buf, sz);
+			} else
+				error = errno;
+			blk += sz / secsz;
+			bytesize += sz;
+			cur = hole;
+		} else {
+			/*
+			 * I don't know what this means or whether it
+			 * can happen at all...
+			 */
+			error = EDOOFUS;
+			break;
+		}
+	}
+	if (error)
+		close(fd);
+	if (!error && sizep != NULL)
+		*sizep = bytesize;
+	return (error);
 }
 
 int


More information about the svn-src-user mailing list