[PATCH 5/5] brd: Add getgeo to block ops for fdisk

From: Boaz Harrosh
Date: Wed Nov 05 2014 - 09:10:59 EST


From: Boaz Harrosh <boaz@xxxxxxxxxxxxx>

Now when fdisk is run on brd it will ask some cryptic
questions about CHS. This is because the getgeo block operation
is not implemented.

With the usual emulated values of 64, 32, X and the default
size of 4M device, fdisk will offer 34 as possible first-sector,
And after the previous patch of 4K sectores it will offer
40 as possible first-sector.

But with the values presented here of 1, 1, 1 fdisk will offer
8 (4K) as possible first sector.

I have done a quick audit of the fdisk code. The CHS calculation
is very convoluted but at the end it comes out with a number.
Which is taken into consideration in first-sector to allow. With
all 1(s) this numbers is very small and other numbers come into
account. Also note that if the device is big like 1G (not sure what
is the threshold) fdisk will offer 1M (2048) as possible first-
sector, and it does not matter what numbers we give here.

Only fdisk is problematic both libgparted (and all applications
that use it) and cfdisk always offer 1M alignment and do not call
getgeo at all.

Signed-off-by: Boaz Harrosh <boaz@xxxxxxxxxxxxx>
---
drivers/block/brd.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 0026998..e0bc072 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -19,6 +19,7 @@
#include <linux/radix-tree.h>
#include <linux/fs.h>
#include <linux/slab.h>
+#include <linux/hdreg.h>

#include <asm/uaccess.h>

@@ -426,6 +427,23 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
return error;
}

+static int brd_getgeo(struct block_device *bd, struct hd_geometry *geo)
+{
+ /* Just tell fdisk to get out of the way. The math here is so
+ * convoluted and does not make any sense at all. With all 1s
+ * The math just gets out of the way.
+ * NOTE: I was trying to get some values that will make fdisk
+ * Want to align first sector on 4K (like 8, 16, 20, ... sectors) but
+ * nothing worked, I searched the net the math is not your regular
+ * simple multiplication at all. If you managed to get these please
+ * fix here. For now we use 4k physical sectors for this
+ */
+ geo->heads = 1;
+ geo->sectors = 1;
+ geo->cylinders = 1;
+ return 0;
+}
+
static const struct block_device_operations brd_fops = {
.owner = THIS_MODULE,
.rw_page = brd_rw_page,
@@ -433,6 +451,7 @@ static const struct block_device_operations brd_fops = {
#ifdef CONFIG_BLK_DEV_XIP
.direct_access = brd_direct_access,
#endif
+ .getgeo = brd_getgeo,
};

/*
--
1.9.3


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/