diff mbox

[1/7] UBI: Add a new ioctl to support ubidump

Message ID 53BA499B.5090206@huawei.com
State RFC
Headers show

Commit Message

hujianyang July 7, 2014, 7:17 a.m. UTC
Add a new ioctl to dump EC header and VID header to user space. This
ioctl is called without lock so I think users *should not* run ubidump
when volume is mounted.

Struct ubi_ebdump_req is used to transfer data between user space and
kernel space. Can I find a way to set buffer length from '64' to
UBI_VID_HDR_SIZE and UBI_EC_HDR_SIZE?


Signed-off-by: hujianyang <hujianyang@huawei.com>
---
 drivers/mtd/ubi/cdev.c      | 50 +++++++++++++++++++++++++++++++++++++++++++++
 include/uapi/mtd/ubi-user.h | 15 ++++++++++++++
 2 files changed, 65 insertions(+)

Comments

Artem Bityutskiy July 16, 2014, 7:59 a.m. UTC | #1
On Mon, 2014-07-07 at 15:17 +0800, hujianyang wrote:
> Add a new ioctl to dump EC header and VID header to user space. This
> ioctl is called without lock so I think users *should not* run ubidump
> when volume is mounted.
> 
> Struct ubi_ebdump_req is used to transfer data between user space and
> kernel space. Can I find a way to set buffer length from '64' to
> UBI_VID_HDR_SIZE and UBI_EC_HDR_SIZE?
> 
> 
> Signed-off-by: hujianyang <hujianyang@huawei.com>

I've never seen an ioctl for retrieving an on-the-media data structure,
do you have any examples? I think the traditional way is that the
user-space reads all the information from the disk itself.

Do you really need to dump UBI headers?

Could you please drop this functionality for now, and provide an ubidump
which only dumps UBIFS data structures for now.

Then we can talk and think about the UBI-level headers dumping.
hujianyang July 16, 2014, 8:47 a.m. UTC | #2
Hi Artem,

Thank you for reviewing these patches.

> 
> Do you really need to dump UBI headers?
>

Yes, because I think ec_counter in ec_hdr and copy_flag, sqnum
in vid_hdr are useful.

Current ->read() can just read data from data_offset where the
leb located. And reading UBI headers by mtd functionality are
very complicated, we don't know pnum either.

Maybe we can try other way instead of this ioctl, by adding an
new function which can read the hole peb specified by lnum to
user space.
Artem Bityutskiy July 16, 2014, 10:30 a.m. UTC | #3
On Wed, 2014-07-16 at 16:47 +0800, hujianyang wrote:
> Hi Artem,
> 
> Thank you for reviewing these patches.
> 
> > 
> > Do you really need to dump UBI headers?
> >
> 
> Yes, because I think ec_counter in ec_hdr and copy_flag, sqnum
> in vid_hdr are useful.
> 
> Current ->read() can just read data from data_offset where the
> leb located. And reading UBI headers by mtd functionality are
> very complicated, we don't know pnum either.
> 
> Maybe we can try other way instead of this ioctl, by adding an
> new function which can read the hole peb specified by lnum to
> user space.

Yes, this is a lot better approach. But I'd still suggest to start with
a smaller step - ubidump without the UBI headers dumping support. Then
add the UBI headers dumping support as a separate step.
diff mbox

Patch

diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 7646220..5b94323 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -581,6 +581,56 @@  static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
 		break;
 	}

+	case UBI_IOCEBDUMP:
+	{
+		int pnum;
+		struct ubi_ebdump_req req;
+		struct ubi_ec_hdr *ec_hdr;
+		struct ubi_vid_hdr *vid_hdr;
+
+		err = copy_from_user(&req, argp,
+				     sizeof(struct ubi_ebdump_req));
+		if (err) {
+			err = -EFAULT;
+			break;
+		}
+
+		err = ubi_is_mapped(desc, req.lnum);
+		if (err <= 0)
+			break;
+		pnum = vol->eba_tbl[req.lnum];
+		req.pnum = pnum;
+
+		/*
+		 * No need to check return value of ubi_io_read(),
+		 * we will confirm the date in user space.
+		 */
+		ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
+		if (!ec_hdr) {
+			err = -ENOMEM;
+			break;
+		}
+		ubi_io_read_ec_hdr(ubi, pnum, ec_hdr, 0);
+		memcpy(req.ec_hdr, ec_hdr, UBI_EC_HDR_SIZE);
+		kfree(ec_hdr);
+
+		vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
+		if (!vid_hdr) {
+			err = -ENOMEM;
+			break;
+		}
+		ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1);
+		memcpy(req.vid_hdr, vid_hdr, UBI_VID_HDR_SIZE);
+		ubi_free_vid_hdr(ubi, vid_hdr);
+
+		err = copy_to_user(argp, &req,
+				   sizeof(struct ubi_ebdump_req));
+		if (err)
+			err = -EFAULT;
+
+		break;
+	}
+
 	default:
 		err = -ENOTTY;
 		break;
diff --git a/include/uapi/mtd/ubi-user.h b/include/uapi/mtd/ubi-user.h
index 1927b0d..76ff035 100644
--- a/include/uapi/mtd/ubi-user.h
+++ b/include/uapi/mtd/ubi-user.h
@@ -205,6 +205,8 @@ 
 #define UBI_IOCVOLCRBLK _IOW(UBI_VOL_IOC_MAGIC, 7, struct ubi_blkcreate_req)
 /* Remove the R/O block device */
 #define UBI_IOCVOLRMBLK _IO(UBI_VOL_IOC_MAGIC, 8)
+/* Dump LEB header */
+#define UBI_IOCEBDUMP _IOW(UBI_VOL_IOC_MAGIC, 9, struct ubi_ebdump_req)

 /* Maximum MTD device name length supported by UBI */
 #define MAX_UBI_MTD_NAME_LEN 127
@@ -442,4 +444,17 @@  struct ubi_blkcreate_req {
 	__s8  padding[128];
 }  __packed;

+/**
+ * struct ubi_ebdump_req - a data structure used in dump eraseblock header.
+ * @lnum: logical eraseblock num to dump
+ * @ec_hdr: ec_hdr to set
+ * @vid_hdr: vid_hdr to set
+ */
+struct ubi_ebdump_req {
+	__s32	lnum;
+	__s32	pnum;
+	char	ec_hdr[64];
+	char	vid_hdr[64];
+}  __packed;
+
 #endif /* __UBI_USER_H__ */