From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40885) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZlfSK-0004qu-VC for qemu-devel@nongnu.org; Mon, 12 Oct 2015 11:56:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZlfSJ-0001SX-Os for qemu-devel@nongnu.org; Mon, 12 Oct 2015 11:56:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39918) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZlfSJ-0001SN-I5 for qemu-devel@nongnu.org; Mon, 12 Oct 2015 11:56:07 -0400 References: <1444446115-3796-1-git-send-email-crosthwaite.peter@gmail.com> From: John Snow Message-ID: <561BD814.5090005@redhat.com> Date: Mon, 12 Oct 2015 11:56:04 -0400 MIME-Version: 1.0 In-Reply-To: <1444446115-3796-1-git-send-email-crosthwaite.peter@gmail.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [RFC] Block device size rounding List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Peter Crosthwaite , qemu-devel@nongnu.org Cc: kwolf@redhat.com, saipava@xilinx.com, stefanha@redhat.com, Peter Crosthwaite On 10/09/2015 11:01 PM, Peter Crosthwaite wrote: > I have in interesting problem with SD cards, where if you pass a block > device that is not multiple-of-512k size the last bit gets chopped off. > The problem is the card can only report a 512kX size to the guest, so > a significant rounding is needed one way or the other. The current > round-down policy causes crashing boots because parts of my guest > file-system are missing. >=20 > The below patch works around it, by changing to round-up and simply > ignoring reads and writes past the end of the block device file. >=20 > What is the correct action here though? If the file is writeable should > we just allow the device to extend its size? Is that possible already? > Just zero-pad read-only? >=20 Read-only seems like an easy case of append zeroes. Read-write ... well, we can't write-protect just half of a 512k block. Forcibly extending the size might be the only viable solution. I would almost suggest doing a sparse allocation for the remainder of the block and don't extend the physical size until the first write to that block, but then we have the strange situation where: - QEMU may extend your image according to the device model, sometimes - Or sometimes not. People don't seem to like unpredictability much, so maybe just outright extending the image is the best thing to do, because then it can be documented. I also suppose an interactive warning prompt wouldn't work either ("Hey, this file is a pinch too small for this device, may I extend it y/n?"), since there's no existing protocol for negotiating that sort of thing and it might cause management layers to explode... Probably just forcibly increasing the size on RW or refusing to use the file altogether are probably the sane deterministic things we want. > The same could be applied to pflash, where the device init barfs if the > backing file is too small (the devices are inited of a constant size, > not based on the block device size). >=20 > Requiring the user to pad files in a device dependent way is a little > user-unfriendly. >=20 > Regards, > Peter > --- > hw/sd/sd.c | 19 +++++++++++++------ > 1 file changed, 13 insertions(+), 6 deletions(-) >=20 > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > index 3e2a451..539bb72 100644 > --- a/hw/sd/sd.c > +++ b/hw/sd/sd.c > @@ -248,13 +248,18 @@ static const uint8_t sd_csd_rw_mask[16] =3D { > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, > }; > =20 > -static void sd_set_csd(SDState *sd, uint64_t size) > +static uint64_t sd_set_csd(SDState *sd, uint64_t size) > { > - uint32_t csize =3D (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1; > - uint32_t sectsize =3D (1 << (SECTOR_SHIFT + 1)) - 1; > - uint32_t wpsize =3D (1 << (WPGROUP_SHIFT + 1)) - 1; > + uint64_t actual_size; > =20 > if (size <=3D 0x40000000) { /* Standard Capacity SD */ > + uint32_t sectsize =3D (1 << (SECTOR_SHIFT + 1)) - 1; > + uint32_t wpsize =3D (1 << (WPGROUP_SHIFT + 1)) - 1; > + uint32_t csize; > + > + actual_size =3D ROUND_UP(size, 1 << (CMULT_SHIFT + HWBLOCK_SHI= FT)); > + csize =3D (actual_size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1; > + > sd->csd[0] =3D 0x00; /* CSD structure */ > sd->csd[1] =3D 0x26; /* Data read access-time-1 */ > sd->csd[2] =3D 0x00; /* Data read access-time-2 */ > @@ -281,7 +286,8 @@ static void sd_set_csd(SDState *sd, uint64_t size) > sd->csd[14] =3D 0x00; /* File format group */ > sd->csd[15] =3D (sd_crc7(sd->csd, 15) << 1) | 1; > } else { /* SDHC */ > - size /=3D 512 * 1024; > + actual_size =3D ROUND_UP(size, 512 * 1024); > + size =3D actual_size / (512 * 1024); > size -=3D 1; > sd->csd[0] =3D 0x40; > sd->csd[1] =3D 0x0e; > @@ -301,6 +307,7 @@ static void sd_set_csd(SDState *sd, uint64_t size) > sd->csd[15] =3D 0x00; > sd->ocr |=3D 1 << 30; /* High Capacity SD Memory Card */ > } > + return actual_size; > } > =20 > static void sd_set_rca(SDState *sd) > @@ -408,7 +415,7 @@ static void sd_reset(SDState *sd) > sd_set_ocr(sd); > sd_set_scr(sd); > sd_set_cid(sd); > - sd_set_csd(sd, size); > + size =3D sd_set_csd(sd, size); > sd_set_cardstatus(sd); > sd_set_sdstatus(sd); > =20 >=20 --=20 =97js