Skip to content
Commit 71c76e74 authored by Brian Norris's avatar Brian Norris Committed by Artem Bityutskiy
Browse files

libmtd: fix mtd_write() issues for large data-only writes



ioctl(MEMWRITE) is implemented with memdup_user(), and so it allocates
kernel memory in contiguous regions. This limits its usefulness for large
amounts of data, since contiguous kernel memory can become scarce. I have
experienced "out of memory" problems with ubiformat, for instance, which
writes in eraseblock-sized regions:

  ...
  ubiformat: flashing eraseblock 12 -- 72 % complete
  ubiformat: page allocation failure.
  order:8, mode:0xd0
  Call Trace:
  [<8043fa7c>] dump_stack+0x8/0x34
  [<8008c940>] __alloc_pages_nodemask+0x408/0x618
  [<800bd748>] cache_alloc_refill+0x400/0x730
  [<800bdbbc>] __kmalloc+0x144/0x154
  [<8009cae4>] memdup_user+0x24/0x94
  [<802d04e4>] mtd_ioctl+0xba8/0xbd0
  [<802d0544>] mtd_unlocked_ioctl+0x38/0x5c
  [<800d43c0>] do_vfs_ioctl+0xa4/0x6e4
  [<800d4a44>] sys_ioctl+0x44/0xa0
  [<8000f95c>] stack_done+0x20/0x40
  ...
  libmtd: error!: MEMWRITE ioctl failed for eraseblock 12 (mtd0)
          error 12 (Cannot allocate memory)
  ubiformat: error!: cannot write eraseblock 12
             error 12 (Cannot allocate memory)

This error can be mitigated for now by only using ioctl(MEMWRITE) when we
need to write OOB data, since we can only do this in small transactions
anyway. Then, data-only transactions (like those originating from
ubiformat) can be carried out with write() calls.

This issue can also be solved within the kernel ioctl(), but either way,
this patch is still useful, since write() is more straightforward (and
efficient?) than ioctl() for data-only writes.

Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
parent b989a29c
Loading
Loading
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment