From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:43360) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXxlY-0007Sc-8V for qemu-devel@nongnu.org; Tue, 06 Dec 2011 11:21:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RXxlO-0004RV-JW for qemu-devel@nongnu.org; Tue, 06 Dec 2011 11:21:12 -0500 Received: from mail.avalus.com ([89.16.176.221]:35109) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXxlO-0004RL-BW for qemu-devel@nongnu.org; Tue, 06 Dec 2011 11:21:02 -0500 Date: Tue, 06 Dec 2011 16:20:56 +0000 From: Alex Bligh Message-ID: <958CDBC95A3252B592B5E3C9@nimrod.local> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline Subject: [Qemu-devel] RFC: raw device support for block device targets Reply-To: Alex Bligh List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Alex Bligh qemu-img convert appears to support block devices as input, but not as output. That is irritating, as when using qemu-img convert to convert qcow to raw on a block partition, an intermediate file has to be used, which slows things down and pointlessly uses disk space. The problem is that ftruncate() is being called on the output file in order ensure it is sufficiently large, and this fails on block devices. I appreciate there may be other calls that fail depending on the input file format, but these will presumably be error checked at the time. Is it therefore worth skipping the ftruncate() if the block device is large enough, and at least attempting to proceed further? Something like the following (not-even compile tested) patch? -- Alex Bligh Signed-Off-By: Alex Bligh diff --git a/block/raw-posix.c b/block/raw-posix.c index 2ee5d69..be9a371 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -573,9 +573,29 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) if (fd < 0) { result = -errno; } else { + + struct stat sb; + + if (-1 == fstat(dest, &sb)) { + result = -errno; + goto close; + } + + /* block devices do not support truncate. If the device is large + enough, then it will do */ + + if (S_ISBLK(sb.st_mode)) { + /* divide to prevent overflow */ + if (sb.st_size / BDRV_SECTOR_SIZE < total_size) + result = -ENOSPC; + goto close; + } + if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { result = -errno; } + + close: if (close(fd) != 0) { result = -errno; }