[PATCH 5/5] flash_{lock, unlock}: fix off-by-one error for "entire device" length

Mike Frysinger vapier at gentoo.org
Mon Jun 6 00:09:14 EDT 2011

From: Steven Miao <realmz6 at gmail.com>

This basically reverts commit 43feb39f35a9ee0ed3 which changed the full
length calculation to be one less than one sector.  I don't understand
the logic in the commit message where it states that the length should
be one sector smaller as this results in misbehavior at runtime.

For example, with a mtd device with total size 0x400000 and erase block
size of 0x20000 (which gives us a total of 32 sectors), this new logic
results in:
	mtdLockInfo.start = 0;
	mtdLockInfo.length = 0x3e0000; /* (32 - 1) * 0x20000 */

Calling MEMLOCK/MEMUNLOCK on the device with this range leaves the last
sector unchanged which is certainly not what we want.  So drop this -1
part of the calculation.

To look at it another way, if we only attempt to lock one sector, this
calculation would end up with the .length set to 0.  Calling MEMLOCK
with a length of 0 does not lock the sector as this simple code shows:
	int main(int argc, char *argv[]) {
		erase_info_t e0 = { 0, 0 }, e1 = { 0, 0x20000 };
		int fd = open(argv[1], O_RDONLY);
		ioctl(fd, MEMUNLOCK, &e1);
		printf("%i\n", ioctl(fd, MEMISLOCKED, &e1));
		ioctl(fd, MEMLOCK, &e0);
		printf("%i\n", ioctl(fd, MEMISLOCKED, &e1));
MEMISLOCKED returns 0 both times.  If we change the argument to MEMLOCK
to e1, then MEMISLOCKED returns 1.

CC: Vimal Singh <vimal.newwork at gmail.com>
CC: Vimal Singh <vimalsingh at ti.com>
Signed-off-by: Steven Miao <realmz6 at gmail.com>
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
 flash_unlock.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/flash_unlock.c b/flash_unlock.c
index 3d7dd53..9fb089a 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -77,11 +77,11 @@ int main(int argc, char *argv[])
 	if (argc > 3) {
 		count = strtol(argv[3], NULL, 0);
 		if (count == -1)
-			mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+			mtdLockInfo.length = mtdInfo.size;
 			mtdLockInfo.length = mtdInfo.erasesize * count;
 	} else
-		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+		mtdLockInfo.length = mtdInfo.size;
 	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size)
 		errmsg_die("range is more than device supports: %#x + %#x > %#x",
 			mtdLockInfo.start, mtdLockInfo.length, mtdInfo.size);

More information about the linux-mtd mailing list