Patchwork [4/5] libmtd: add support for 64-bit offsets, OOB

login
register
mail settings
Submitter Kevin Cernekee
Date July 5, 2010, 10:10 p.m.
Message ID <b025d903aab9bff2a1f0ddadff7f31a8@localhost>
Download mbox | patch
Permalink /patch/57932/
State New
Headers show

Comments

Kevin Cernekee - July 5, 2010, 10:10 p.m.
Change mtd_erase() so that it attempts to use MEMERASE64 first, then falls
back to the old <2.6.31 MEMERASE if MEMERASE64 is unsupported.

Add mtd_read_oob(), mtd_write_oob() functions to wrap the OOB ioctls.
Similar ioctl fallback logic is used in these functions as well.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 include/libmtd.h |   26 +++++++++++++++++++++
 lib/libmtd.c     |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 88 insertions(+), 3 deletions(-)
Mike Frysinger - July 5, 2010, 10:58 p.m.
On Mon, Jul 5, 2010 at 18:10, Kevin Cernekee wrote:
> Change mtd_erase() so that it attempts to use MEMERASE64 first, then falls
> back to the old <2.6.31 MEMERASE if MEMERASE64 is unsupported.

very cool

> +               struct erase_info_user ei_old;
> +
> +               ei_old.start = (__u32)ei.start;
> +               ei_old.length = (__u32)ei.length;

the casts are useless since the assigned types are __u32

> +               struct mtd_oob_buf oob_old;
> +
> +               oob_old.start = (__u32)oob.start;
> +               oob_old.length = (__u32)oob.length;

same here
-mike
Artem Bityutskiy - July 6, 2010, 4:02 a.m.
On Mon, 2010-07-05 at 15:10 -0700, Kevin Cernekee wrote:
> Change mtd_erase() so that it attempts to use MEMERASE64 first, then falls
> back to the old <2.6.31 MEMERASE if MEMERASE64 is unsupported.
> 
> Add mtd_read_oob(), mtd_write_oob() functions to wrap the OOB ioctls.
> Similar ioctl fallback logic is used in these functions as well.
> 
> Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
> ---
>  include/libmtd.h |   26 +++++++++++++++++++++
>  lib/libmtd.c     |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 88 insertions(+), 3 deletions(-)
> 
> diff --git a/include/libmtd.h b/include/libmtd.h
> index 0aea966..2241343 100644
> --- a/include/libmtd.h
> +++ b/include/libmtd.h
> @@ -149,6 +149,32 @@ int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd);
>  int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb);
>  
>  /**
> + * mtd_read_oob - read OOB bytes
> + * @fd: MTD device node file descriptor
> + * @start: page-aligned start address
> + * @length: number of OOB bytes to read
> + * @data: read buffer
> + *
> + * This function reads @length OOB bytes starting from address @start on
> + * MTD device described by @fd. Returns %0 in case of success and %-1 in
> + * case of failure.
> + */
> +int mtd_read_oob(int fd, uint64_t start, uint64_t length, void *data);
> +
> +/**
> + * mtd_write_oob - write OOB bytes
> + * @fd: MTD device node file descriptor
> + * @start: page-aligned start address
> + * @length: number of OOB bytes to write
> + * @data: write buffer
> + *
> + * This function writes @length OOB bytes starting from address @start on
> + * MTD device described by @fd. Returns %0 in case of success and %-1 in
> + * case of failure.
> + */
> +int mtd_write_oob(int fd, uint64_t start, uint64_t length, void *data);
> +
> +/**
>   * mtd_torture - torture an eraseblock.
>   * @mtd: MTD device description object
>   * @fd: MTD device node file descriptor
> diff --git a/lib/libmtd.c b/lib/libmtd.c
> index 3ff031c..368493b 100644
> --- a/lib/libmtd.c
> +++ b/lib/libmtd.c
> @@ -32,6 +32,7 @@
>  #include <sys/stat.h>
>  #include <sys/ioctl.h>
>  #include <mtd/mtd-user.h>
> +#include <mtd/mtd-abi.h>
>  
>  #include <libmtd.h>
>  #include "libmtd_int.h"
> @@ -791,11 +792,69 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
>  
>  int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb)
>  {
> -	struct erase_info_user ei;
> +	int ret;
> +	struct erase_info_user64 ei;
>  
> -	ei.start = eb * mtd->eb_size;;
> +	ei.start = (__u64)eb * mtd->eb_size;
>  	ei.length = mtd->eb_size;
> -	return ioctl(fd, MEMERASE, &ei);
> +	ret = ioctl(fd, MEMERASE64, &ei);
> +
> +	if (ret < 0 && errno == ENOTTY) {
> +		struct erase_info_user ei_old;
> +
> +		ei_old.start = (__u32)ei.start;
> +		ei_old.length = (__u32)ei.length;
> +
> +		if (ei_old.start != ei.start) {
> +			errno = EOVERFLOW;
> +			return -1;
> +		}
> +
> +		ret = ioctl(fd, MEMERASE, &ei_old);
> +	}
> +
> +	return ret;
> +}

Kevin, looks like a good sanitization in general, thanks. But let's
avoid calling 2 ioctls for old kernels - just introduce a flag in
'struct mtd_dev_info' and check whether 64-bit offsets are supported.

Patch

diff --git a/include/libmtd.h b/include/libmtd.h
index 0aea966..2241343 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -149,6 +149,32 @@  int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd);
 int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb);
 
 /**
+ * mtd_read_oob - read OOB bytes
+ * @fd: MTD device node file descriptor
+ * @start: page-aligned start address
+ * @length: number of OOB bytes to read
+ * @data: read buffer
+ *
+ * This function reads @length OOB bytes starting from address @start on
+ * MTD device described by @fd. Returns %0 in case of success and %-1 in
+ * case of failure.
+ */
+int mtd_read_oob(int fd, uint64_t start, uint64_t length, void *data);
+
+/**
+ * mtd_write_oob - write OOB bytes
+ * @fd: MTD device node file descriptor
+ * @start: page-aligned start address
+ * @length: number of OOB bytes to write
+ * @data: write buffer
+ *
+ * This function writes @length OOB bytes starting from address @start on
+ * MTD device described by @fd. Returns %0 in case of success and %-1 in
+ * case of failure.
+ */
+int mtd_write_oob(int fd, uint64_t start, uint64_t length, void *data);
+
+/**
  * mtd_torture - torture an eraseblock.
  * @mtd: MTD device description object
  * @fd: MTD device node file descriptor
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 3ff031c..368493b 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -32,6 +32,7 @@ 
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <mtd/mtd-user.h>
+#include <mtd/mtd-abi.h>
 
 #include <libmtd.h>
 #include "libmtd_int.h"
@@ -791,11 +792,69 @@  int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
 
 int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb)
 {
-	struct erase_info_user ei;
+	int ret;
+	struct erase_info_user64 ei;
 
-	ei.start = eb * mtd->eb_size;;
+	ei.start = (__u64)eb * mtd->eb_size;
 	ei.length = mtd->eb_size;
-	return ioctl(fd, MEMERASE, &ei);
+	ret = ioctl(fd, MEMERASE64, &ei);
+
+	if (ret < 0 && errno == ENOTTY) {
+		struct erase_info_user ei_old;
+
+		ei_old.start = (__u32)ei.start;
+		ei_old.length = (__u32)ei.length;
+
+		if (ei_old.start != ei.start) {
+			errno = EOVERFLOW;
+			return -1;
+		}
+
+		ret = ioctl(fd, MEMERASE, &ei_old);
+	}
+
+	return ret;
+}
+
+static int mtd_oob_op(int cmd, int cmd_old, int fd, uint64_t start,
+	uint64_t length, void *data)
+{
+	int ret;
+	struct mtd_oob_buf64 oob;
+
+	oob.start = start;
+	oob.length = length;
+	oob.usr_ptr = (__u64)(unsigned long)data;
+
+	ret = ioctl(fd, cmd, &oob);
+
+	if (ret < 0 && errno == ENOTTY) {
+		struct mtd_oob_buf oob_old;
+
+		oob_old.start = (__u32)oob.start;
+		oob_old.length = (__u32)oob.length;
+		oob_old.ptr = data;
+
+		if (oob_old.start != oob.start ||
+				oob_old.length != oob.length) {
+			errno = EOVERFLOW;
+			return -1;
+		}
+
+		ret = ioctl(fd, cmd_old, &oob_old);
+	}
+
+	return ret;
+}
+
+int mtd_read_oob(int fd, uint64_t start, uint64_t length, void *data)
+{
+	return mtd_oob_op(MEMREADOOB64, MEMREADOOB, fd, start, length, data);
+}
+
+int mtd_write_oob(int fd, uint64_t start, uint64_t length, void *data)
+{
+	return mtd_oob_op(MEMWRITEOOB64, MEMWRITEOOB, fd, start, length, data);
 }
 
 /* Patterns to write to a physical eraseblock when torturing it */