]> www.infradead.org Git - mtd-utils.git/commitdiff
libmtd: Add support to access OOB available size
authorXiaolei Li <xiaolei.li@mediatek.com>
Tue, 10 Apr 2018 07:36:55 +0000 (15:36 +0800)
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Tue, 10 Apr 2018 13:38:56 +0000 (15:38 +0200)
This patch exposes OOB available size to user. Then user can use
OOB free area according to OOB available size.

Steps to get OOB available size:
First, access /sys/class/mtd/mtdX/oobavail. If not exist, then
try to get ecc layout by ioctl "ECCGETLAYOUT". If none of them
work, set OOB available size to 0.

Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
include/libmtd.h
lib/libmtd.c
lib/libmtd_int.h
lib/libmtd_legacy.c

index db85fb4a28802e0ebdcae778cbaed0859d94932a..cc24af81bd17264fbb89c6168db5851d1864cbb7 100644 (file)
@@ -66,6 +66,7 @@ struct mtd_info
  * @min_io_size: minimum input/output unit size
  * @subpage_size: sub-page size
  * @oob_size: OOB size (zero if the device does not have OOB area)
+ * @oobavail: free OOB size
  * @region_cnt: count of additional erase regions
  * @writable: zero if the device is read-only
  * @bb_allowed: non-zero if the MTD device may have bad eraseblocks
@@ -84,6 +85,7 @@ struct mtd_dev_info
        int min_io_size;
        int subpage_size;
        int oob_size;
+       int oobavail;
        int region_cnt;
        unsigned int writable:1;
        unsigned int bb_allowed:1;
index 86c89ae220357c086cf622f5e92731e7d8c6af63..73822290d87a5ff9c3af345c955a9f160bc119eb 100644 (file)
@@ -614,6 +614,10 @@ libmtd_t libmtd_open(void)
        if (!lib->mtd_oob_size)
                goto out_error;
 
+       lib->mtd_oobavail = mkpath(lib->mtd, MTD_OOBAVAIL);
+       if (!lib->mtd_oobavail)
+               goto out_error;
+
        lib->mtd_region_cnt = mkpath(lib->mtd, MTD_REGION_CNT);
        if (!lib->mtd_region_cnt)
                goto out_error;
@@ -637,6 +641,7 @@ void libmtd_close(libmtd_t desc)
        free(lib->mtd_flags);
        free(lib->mtd_region_cnt);
        free(lib->mtd_oob_size);
+       free(lib->mtd_oobavail);
        free(lib->mtd_subpage_size);
        free(lib->mtd_min_io_size);
        free(lib->mtd_size);
@@ -769,6 +774,15 @@ int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd)
                return -1;
        if (dev_read_pos_int(lib->mtd_oob_size, mtd_num, &mtd->oob_size))
                return -1;
+       if (dev_read_pos_int(lib->mtd_oobavail, mtd_num, &mtd->oobavail)) {
+               /*
+                * Fail to access oobavail sysfs file,
+                * try ioctl ECCGETLAYOUT. */
+               mtd->oobavail = legacy_get_mtd_oobavail1(mtd_num);
+               /* Set 0 as default if can not get valid ecc layout */
+               if (mtd->oobavail < 0)
+                       mtd->oobavail = 0;
+       }
        if (dev_read_pos_int(lib->mtd_region_cnt, mtd_num, &mtd->region_cnt))
                return -1;
        if (dev_read_hex_int(lib->mtd_flags, mtd_num, &ret))
index 03b086356879efbd88eef4f6d08a52a0f39f3a1a..c0514d2589c655b830988318b55d452a9d27d6d0 100644 (file)
@@ -44,6 +44,7 @@ extern "C" {
 #define MTD_MIN_IO_SIZE  "writesize"
 #define MTD_SUBPAGE_SIZE "subpagesize"
 #define MTD_OOB_SIZE     "oobsize"
+#define MTD_OOBAVAIL     "oobavail"
 #define MTD_REGION_CNT   "numeraseregions"
 #define MTD_FLAGS        "flags"
 
@@ -63,6 +64,7 @@ extern "C" {
  * @mtd_min_io_size: minimum I/O unit size file pattern
  * @mtd_subpage_size: sub-page size file pattern
  * @mtd_oob_size: MTD device OOB size file pattern
+ * @mtd_oobavail: MTD device free OOB size file pattern
  * @mtd_region_cnt: count of additional erase regions file pattern
  * @mtd_flags: MTD device flags file pattern
  * @sysfs_supported: non-zero if sysfs is supported by MTD
@@ -92,6 +94,7 @@ struct libmtd
        char *mtd_min_io_size;
        char *mtd_subpage_size;
        char *mtd_oob_size;
+       char *mtd_oobavail;
        char *mtd_region_cnt;
        char *mtd_flags;
        unsigned int sysfs_supported:1;
@@ -103,6 +106,8 @@ int legacy_dev_present(int mtd_num);
 int legacy_mtd_get_info(struct mtd_info *info);
 int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd);
 int legacy_get_dev_info1(int dev_num, struct mtd_dev_info *mtd);
+int legacy_get_mtd_oobavail(const char *node);
+int legacy_get_mtd_oobavail1(int mtd_num);
 
 #ifdef __cplusplus
 }
index 46f51fda3dd51eb0f74b5e7d8faa91c3bfa33f89..e1ab48ec38cedc660aabbd7ce8eb1403fc3253ad 100644 (file)
@@ -215,6 +215,46 @@ int legacy_mtd_get_info(struct mtd_info *info)
        return 0;
 }
 
+int legacy_get_mtd_oobavail(const char *node)
+{
+       struct stat st;
+       struct nand_ecclayout_user usrlay;
+       int fd, ret;
+
+       if (stat(node, &st))
+               return sys_errmsg("cannot open \"%s\"", node);
+
+       if (!S_ISCHR(st.st_mode)) {
+               errno = EINVAL;
+               return errmsg("\"%s\" is not a character device", node);
+       }
+
+       fd = open(node, O_RDONLY);
+       if (fd == -1)
+               return sys_errmsg("cannot open \"%s\"", node);
+
+       ret = ioctl(fd, ECCGETLAYOUT, &usrlay);
+       if (ret < 0) {
+               sys_errmsg("ECCGETLAYOUT ioctl request failed");
+               goto out_close;
+       }
+
+       ret = usrlay.oobavail;
+
+out_close:
+       close(fd);
+
+       return ret;
+}
+
+int legacy_get_mtd_oobavail1(int mtd_num)
+{
+       char node[sizeof(MTD_DEV_PATT) + 20];
+
+       sprintf(node, MTD_DEV_PATT, mtd_num);
+       return legacy_get_mtd_oobavail(node);
+}
+
 /**
  * legacy_get_dev_info - legacy version of 'mtd_get_dev_info()'.
  * @node: name of the MTD device node
@@ -335,6 +375,9 @@ int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd)
 
        close(fd);
 
+       ret = legacy_get_mtd_oobavail(node);
+       mtd->oobavail = ret > 0 ? ret : 0;
+
        /*
         * Unfortunately, the device name is not available via ioctl, and
         * we have to parse /proc/mtd to get it.