]> www.infradead.org Git - mtd-utils.git/commitdiff
libubi: support atomic LEB change ioctl
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Fri, 25 Jan 2008 14:43:07 +0000 (16:43 +0200)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Fri, 25 Jan 2008 14:44:06 +0000 (16:44 +0200)
And add testing for this feature.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
tests/ubi-tests/Makefile
tests/ubi-tests/io_update.c
ubi-utils/include/libubi.h
ubi-utils/src/libubi.c

index b5c7e2f9ad9cf15250f65b62199a5c77a347e3e5..0566ebc5fdc4b66098d77a982ab430e93f1b662e 100644 (file)
@@ -1,6 +1,7 @@
 LIBUBI_PATH=../../ubi-utils/
 LIBUBI_SRC_PATH=../../ubi-utils/src
 LIBUBI_HEADER_PATH=../../ubi-utils/include
+UBI_HEADERS_PATH=../../include/
 UBIUTILS_PATH=../../ubi-utils/
 
 CC := $(CROSS)gcc
@@ -15,7 +16,7 @@ HELPERS=$(addprefix helpers/, $(HELPER_NAMES))
 # it removes the. If you want to prevent the removal, uncomment the below
 #.SECONDARY: $(addsuffix .o, $(TESTS)) $(addsuffix .o, $(HELPERS))
 
-CFLAGS += -Wall -I$(LIBUBI_HEADER_PATH) -L. -O2
+CFLAGS += -Wall -I$(LIBUBI_HEADER_PATH) -I $(UBI_HEADERS_PATH) -L. -O2
 
 all: ubi-utils libubi $(TESTS) $(HELPERS)
 
index d433239189065d9785e07f924ede562e1fb10521..f7a122efe2fdf2241a504b393a356b78c1ea7dfa 100644 (file)
@@ -17,7 +17,7 @@
  *
  * Author: Artem B. Bityutskiy
  *
- * Test UBI volume update.
+ * Test UBI volume update and atomic LEB change
  */
 
 #include <stdio.h>
@@ -28,7 +28,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include "libubi.h"
+
+#include <libubi.h>
+#include <mtd/ubi-user.h>
 #define TESTNAME "io_update"
 #include "common.h"
 
@@ -65,12 +67,15 @@ const char *node;
 /*
  * test_update1 - helper function for test_update().
  */
-static int test_update1(struct ubi_vol_info *vol_info)
+static int test_update1(struct ubi_vol_info *vol_info, int leb_change)
 {
+       long long total_len = leb_change ? vol_info->leb_size
+                                        : vol_info->rsvd_bytes;
        int sequences[SEQ_SZ][3] = SEQUENCES(dev_info.min_io_size,
-                                            vol_info->leb_size);
+                                            leb_change ? dev_info.min_io_size * 2
+                                                       : vol_info->leb_size);
        char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
-       unsigned char buf[vol_info->rsvd_bytes];
+       unsigned char buf[total_len];
        int fd, i, j;
 
        sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
@@ -86,14 +91,30 @@ static int test_update1(struct ubi_vol_info *vol_info)
        for (i = 0; i < SEQ_SZ; i++) {
                int ret, stop = 0, len = 0;
                off_t off = 0;
-               unsigned char buf1[vol_info->rsvd_bytes];
-
-               if (ubi_update_start(libubi, fd, vol_info->rsvd_bytes)) {
-                       failed("ubi_update_start");
-                       goto close;
+               long long test_len;
+               unsigned char buf1[total_len];
+
+               /*
+                * test_len is LEB size (if we test atomic LEB change) or
+                * volume size (if we test update). For better test coverage,
+                * use a little smaller LEB change/update length.
+                */
+               test_len = total_len - (rand() % (total_len / 10));
+
+               if (leb_change) {
+                       if (ubi_leb_change_start(libubi, fd, 0, test_len,
+                                                UBI_SHORTTERM)) {
+                               failed("ubi_update_start");
+                               goto close;
+                       }
+               } else {
+                       if (ubi_update_start(libubi, fd, test_len)) {
+                               failed("ubi_update_start");
+                               goto close;
+                       }
                }
 
-               for (j = 0; off < vol_info->rsvd_bytes; j++) {
+               for (j = 0; off < test_len; j++) {
                        int n, rnd_len, l;
 
                        if (!stop) {
@@ -108,13 +129,18 @@ static int test_update1(struct ubi_vol_info *vol_info)
                         * and the other part with 0xFFs to test how UBI
                         * stripes 0xFFs multiple of I/O unit size.
                         */
-                       if (off + l > vol_info->rsvd_bytes)
-                               l = vol_info->rsvd_bytes - off;
+                       if (off + l > test_len)
+                               l = test_len - off;
                        rnd_len = rand() % (l + 1);
                        for (n = 0; n < rnd_len; n++)
                                buf[off + n] = (unsigned char)rand();
                                memset(buf + off + rnd_len, 0xFF, l - rnd_len);
 
+                       /*
+                        * Deliberately pass len instead of l (len may be
+                        * greater then l if this is the last chunk) because
+                        * UBI have to read only l bytes anyway.
+                        */
                        ret = write(fd, buf + off, len);
                        if (ret < 0) {
                                failed("write");
@@ -133,25 +159,31 @@ static int test_update1(struct ubi_vol_info *vol_info)
 
                /* Check data */
                if ((ret = lseek(fd, SEEK_SET, 0)) != 0) {
-                       if (ret < 0)
-                               failed("lseek");
+                       failed("lseek");
                        err_msg("cannot seek to 0");
                        goto close;
                }
-               memset(buf1, 0x01, vol_info->rsvd_bytes);
-               ret = read(fd, buf1, vol_info->rsvd_bytes + 1);
+
+               memset(buf1, 0x01, test_len);
+
+               if (vol_info->type == UBI_STATIC_VOLUME)
+                       /*
+                        * Static volume must not let use read more then it
+                        * contains.
+                        */
+                       ret = read(fd, buf1, test_len + 100);
+               else
+                       ret = read(fd, buf1, test_len);
                if (ret < 0) {
                        failed("read");
-                       err_msg("failed to read %d bytes",
-                               vol_info->rsvd_bytes + 1);
+                       err_msg("failed to read %d bytes", test_len);
                        goto close;
                }
-               if (ret != vol_info->rsvd_bytes) {
-                       err_msg("failed to read %d bytes, read %d",
-                               vol_info->rsvd_bytes, ret);
+               if (ret != test_len) {
+                       err_msg("failed to read %d bytes, read %d", test_len, ret);
                        goto close;
                }
-               if (memcmp(buf, buf1, vol_info->rsvd_bytes)) {
+               if (memcmp(buf, buf1, test_len)) {
                        err_msg("data corruption");
                        goto close;
                }
@@ -166,7 +198,7 @@ close:
 }
 
 /**
- * test_update - check volume update capabilities.
+ * test_update - check volume update and atomic LEB change capabilities.
  *
  * @type  volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
  *
@@ -208,11 +240,18 @@ static int test_update(int type)
                        goto remove;
                }
 
-               if (test_update1(&vol_info)) {
+               if (test_update1(&vol_info, 0)) {
                        err_msg("alignment = %d", req.alignment);
                        goto remove;
                }
 
+               if (vol_info.type != UBI_STATIC_VOLUME) {
+                       if (test_update1(&vol_info, 1)) {
+                               err_msg("alignment = %d", req.alignment);
+                               goto remove;
+                       }
+               }
+
                if (ubi_rmvol(libubi, node, req.vol_id)) {
                        failed("ubi_rmvol");
                        return -1;
index 61d886f846753cee5e3be5821b36a8bd639e2a9e..5f7510851a1c732d70c4ebb2b7edb21d90388966 100644 (file)
@@ -146,7 +146,7 @@ struct ubi_dev_info
  * @rsvd_bytes: how many bytes are reserved for this volume
  * @rsvd_lebs: how many logical eraseblocks are reserved for this volume
  * @leb_size: logical eraseblock size of this volume (may be less then
- *           device's logical eraseblock size due to alignment)
+ *            device's logical eraseblock size due to alignment)
  * @corrupted: non-zero if the volume is corrupted
  * @name: volume name (null-terminated)
  */
@@ -329,10 +329,25 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
  * @bytes: how many bytes will be written to the volume
  *
  * This function initiates UBI volume update and returns %0 in case of success
- * and %-1 in case of error.
+ * and %-1 in case of error. The caller is assumed to write @bytes data to the
+ * volume @fd afterwards.
  */
 int ubi_update_start(libubi_t desc, int fd, long long bytes);
 
+/**
+ * ubi_update_start - start atomic LEB change.
+ * @desc: UBI library descriptor
+ * @fd: volume character devie file descriptor
+ * @lnum: LEB number to change
+ * @bytes: how many bytes of new data will be written to the LEB
+ * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
+ *
+ * This function initiates atomic LEB change operation and returns %0 in case
+ * of success and %-1 in case of error. he caller is assumed to write @bytes
+ * data to the volume @fd afterwards.
+ */
+int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype);
+
 #ifdef __cplusplus
 }
 #endif
index be06f70a8c45131e5bfcf6984434fc39bfb33067..023fa07c02ce73f1d4a9271d831b9fb4b8646f0a 100644 (file)
@@ -1012,6 +1012,21 @@ int ubi_update_start(libubi_t desc, int fd, long long bytes)
        return 0;
 }
 
+int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
+{
+       struct ubi_leb_change_req req;
+
+       desc = desc;
+       memset(&req, 0, sizeof(struct ubi_leb_change_req));
+       req.lnum = lnum;
+       req.bytes = bytes;
+       req.dtype = dtype;
+
+       if (ioctl(fd, UBI_IOCEBCH, &req))
+               return -1;
+       return 0;
+}
+
 int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
 {
        DIR *sysfs_ubi;