This commit it intended to fix page allocation failures
in kernel due to ffs trying to allocate continuous memory
of length specified by userspace.
[ 2452.765000] sdbd: page allocation failure: order:6, mode:0x24040c0
[ 2452.770000] CPU: 2 PID: 6253 Comm: sdbd Not tainted 4.4.71-00002-g4b213b7 #130
[ 2452.780000] Hardware name: s5p4418
[ 2452.780000] [<
c001964c>] (unwind_backtrace) from [<
c0014ec8>] (show_stack+0x20/0x24)
[ 2452.790000] [<
c0014ec8>] (show_stack) from [<
c03516d8>] (dump_stack+0x80/0x94)
[ 2452.795000] [<
c03516d8>] (dump_stack) from [<
c0139738>] (warn_alloc_failed+0xf0/0x130)
[ 2452.805000] [<
c0139738>] (warn_alloc_failed) from [<
c013cef0>] (__alloc_pages_nodemask+0x8f8/0xa98)
[ 2452.810000] [<
c013cef0>] (__alloc_pages_nodemask) from [<
c013d2bc>] (alloc_kmem_pages+0x28/0xc0)
[ 2452.810000] [<
c013d2bc>] (alloc_kmem_pages) from [<
c01585d4>] (kmalloc_order+0x20/0x38)
[ 2452.810000] [<
c01585d4>] (kmalloc_order) from [<
c0158618>] (kmalloc_order_trace+0x2c/0x110)
[ 2452.810000] [<
c0158618>] (kmalloc_order_trace) from [<
c01783ac>] (__kmalloc+0x2f4/0x364)
[ 2452.810000] [<
c01783ac>] (__kmalloc) from [<
c052b868>] (ffs_epfile_io+0xb0/0x4a4)
[ 2452.810000] [<
c052b868>] (ffs_epfile_io) from [<
c052be44>] (ffs_epfile_read_iter+0xb4/0x170)
[ 2452.810000] [<
c052be44>] (ffs_epfile_read_iter) from [<
c018b7e4>] (__vfs_read+0xbc/0xe4)
[ 2452.810000] [<
c018b7e4>] (__vfs_read) from [<
c018bfbc>] (vfs_read+0x88/0x114)
[ 2452.810000] [<
c018bfbc>] (vfs_read) from [<
c018c8e4>] (SyS_read+0x4c/0xa0)
[ 2452.810000] [<
c018c8e4>] (SyS_read) from [<
c0010ef4>] (__sys_trace_return+0x0/0x10)
[ 2452.895000] Mem-Info:
[ 2452.895000] active_anon:22405 inactive_anon:183 isolated_anon:0
[ 2452.895000] active_file:12599 inactive_file:42754 isolated_file:4
[ 2452.895000] unevictable:3 dirty:29 writeback:0 unstable:0
[ 2452.895000] slab_reclaimable:3331 slab_unreclaimable:4106
[ 2452.895000] mapped:14507 shmem:325 pagetables:960 bounce:0
[ 2452.895000] free:30893 free_pcp:21 free_cma:30150
[ 2452.930000] DMA free:124524kB min:2360kB low:2948kB high:3540kB active_anon:89620kB inactive_anon:732kB active_file:50376kB inactive_file:169800kB unevictable:12kB isolated(anon):0kB isolated(file):16kB present:507904kB managed:488348kB mlocked:12kB dirty:116kB writeback:0kB mapped:58028kB shmem:1300kB slab_reclaimable:13324kB slab_unreclaimable:16424kB kernel_stack:2648kB pagetables:3840kB unstable:0kB bounce:0kB free_pcp:452kB local_pcp:0kB free_cma:120600kB writeback_tmp:0kB pages_scanned:428 all_unreclaimable? no
[ 2452.975000] lowmem_reserve[]: 0 0 0 0
[ 2452.980000] DMA: 389*4kB (UMC) 125*8kB (MEC) 84*16kB (UMEC) 52*32kB (UMC) 34*64kB (UC) 35*128kB (UC) 30*256kB (UC) 28*512kB (C) 20*1024kB (C) 14*2048kB (C) 10*4096kB (C) = 124348kB
[ 2452.995000] 55510 total pagecache pages
[ 2453.000000] 126976 pages RAM
[ 2453.005000] 0 pages HighMem/MovableOnly
[ 2453.005000] 4889 pages reserved
[ 2453.010000] 32768 pages cma reserved
Change-Id: I3cef431057ac9e22483f4960bc3265132f6c4b41
static const char ep1_path[] = USB_FUNCFS_SDB_PATH"/ep1";
static const char ep2_path[] = USB_FUNCFS_SDB_PATH"/ep2";
+/* Limit bulk read/write transfers to page size (usually 4096 bytes)
+ *
+ * This is the size individual transfer that sdbd will request to/from
+ * kernel (via read/write(endpoint, ...). While the buffer could be
+ * bigger (ffs allows that) this size is also the size of the
+ * _continuous memory_ buffer allocated in kernel. Continous memory
+ * is scarce resource and allocation of higher order can often fail in
+ * a system with fragmented memory (kernel message: "sdbd: page
+ * allocation failure: order:6, mode:0x24040c0").
+ *
+ * Only page-sized allocation are guaranteed to succeed and this is
+ * used as default below (ffs_usb_init() will update to system's page
+ * size, if possible).
+ */
+#define XFER_MAX_DEFAULT 4096
+static int xfer_max = XFER_MAX_DEFAULT;
/* A local struct to store state of application */
struct usb_handle
int ret;
do {
- ret = sdb_write(bulkin_fd, buf + count, length - count);
+ int xfer_len = length - count > xfer_max ? xfer_max : length - count;
+ ret = sdb_write(bulkin_fd, buf + count, xfer_len);
if (ret < 0) {
if (errno != EINTR)
return ret;
int ret;
do {
- ret = sdb_read(bulkout_fd, buf + count, length - count);
+ int xfer_len = length - count > xfer_max ? xfer_max : length - count;
+ ret = sdb_read(bulkout_fd, buf + count, xfer_len);
if (ret < 0) {
if (errno != EINTR) {
D("[ usb_init - using FunctionFS ]\n");
+ int pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize > 0)
+ xfer_max = pagesize;
+
h = calloc(1, sizeof(usb_handle));
if (h == NULL) {
perror("[ failed to allocate memory for usb FunctionFS bulk device ]\n");