On Mon, May 04, 2009 at 01:43:02PM -0400, Cole Robinson wrote:
Add an extra 'inputvol' parameter to the file volume building
routines. This
allows us to easily reuse the duplicate functionality.
@@ -1032,15 +1046,68 @@ static int createRaw(virConnectPtr conn,
virReportSystemError(conn, errno,
_("cannot extend file '%s'"),
vol->target.path);
- close(fd);
- return -1;
+ goto cleanup;
+ }
+
+ remain = vol->capacity;
+
+ if (inputfd != -1) {
+ size_t bytes = 1024 * 1024;
+ int sparse_interval = 512;
+ int amtread = -1;
+
+ while (amtread != 0) {
+ char buf[bytes];
Preferrable not to allocate 1 MB on the stack, since not all OS
default to such large stacks as Linux does for threads.
+ char *tmp;
+ int newamt;
+
+ if (remain < bytes)
+ bytes = remain;
+
+ if ((amtread = saferead(inputfd, buf, bytes)) < 0) {
+ virReportSystemError(conn, errno,
+ _("failed reading from file
'%s'"),
+ inputvol->target.path);
+ goto cleanup;
+ }
+ remain -= amtread;
+
+ /* Loop over amt read in 512 byte increments, looking for sparse
+ * blocks */
+ tmp = buf;
+ newamt = amtread;
+ do {
+ int interval = ((sparse_interval > newamt) ? newamt
+ : sparse_interval );
+ int sparse_counter = interval;
+
+ while (sparse_counter-- && *(tmp+sparse_counter) ==
'\0')
+ continue;
+
+ if (sparse_counter < 0) {
+ if (lseek(fd, interval, SEEK_CUR) < 0) {
+ virReportSystemError(conn, errno,
+ _("cannot extend file
'%s'"),
+ vol->target.path);
+ goto cleanup;
+ }
+ } else if (safewrite(fd, tmp, interval) < 0) {
+ virReportSystemError(conn, errno,
+ _("failed writing to file
'%s'"),
+ vol->target.path);
+ goto cleanup;
+
+ }
+
+ tmp += interval;
+ } while ((newamt -= sparse_interval) > 0);
+ }
I'm finding this bit of code a little hard to follow. Since you're scanning
in fixed 512 byte chunks, how about just doing
char buf[512];
memset(buf, 0, sizeof buf);
and then just doing a simple loop using memcmp(tmp, buf) over the 1 MB
data. Sure, the current code allows for detection of chunks of zeros
< 512 in size, but since data is allocated in underlying FS in at least
that size chunks, its not worth trying to detect zeros < 512 in length
Regards,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|