Temporary solution for camera crash on KitKat ROMs (might fix other issues).
I will start with the solution and then follow it up with a technical analysis of the problem.
To the KitKat ROM maintainers here, @jamal2367
, here please add the following to /system/etc/sysctl.conf:
To be clear this will set a low watermark of 32MB of free memory. The kernel will attempt to reclaim memory as soon as the system dips below 32MB of free memory.
Now on to the technical analysis. So it looks like all of the crashes I experience on the KitKat ROMs are triggered by the ION memory allocator.
<4>[ 78.327331] mediaserver: page allocation failure: order:0, mode:0xe0
<4>[ 78.327484] [<c02da24c>] (sg_alloc_table+0x1c/0x44) from [<c03a3704>] (ion_iommu_heap_allocate+0x1f4/0x54c)
<4>[ 78.327484] [<c03a3704>] (ion_iommu_heap_allocate+0x1f4/0x54c) from [<c03a02e8>] (ion_alloc+0xd4/0x354)
<4>[ 78.327514] [<c03a02e8>] (ion_alloc+0xd4/0x354) from [<c03a0af0>] (ion_ioctl+0x108/0x434)
<4>[ 84.951995] Binder_4: page allocation failure: order:0, mode:0xe0
<4>[ 84.952117] [<c02da24c>] (sg_alloc_table+0x1c/0x44) from [<c03a3704>] (ion_iommu_heap_allocate+0x1f4/0x54c)
<4>[ 84.952148] [<c03a3704>] (ion_iommu_heap_allocate+0x1f4/0x54c) from [<c03a02e8>] (ion_alloc+0xd4/0x354)
<4>[ 84.952148] [<c03a02e8>] (ion_alloc+0xd4/0x354) from [<c03a0af0>] (ion_ioctl+0x108/0x434)
The key here is the mode of allocation. Notice that it is 0xe0. The mode corresponds to the gfp_mask of the allocation. A reference of the GFP flags can be found in the Linux kernel source: /source/include/linux/gfp.h
So we see that 0xe0 = 0x20 | 0x40 | 0x80, translating that to the corresponding GFP flags we see that it is
0xe0 = ___GFP_HIGH | ___GFP_IO | ___GFP_FS
Notice that ___GFP_HIGH is set and not ___GFP_WAIT. This means that this type of allocation will not wait for reclaimable memory to be reclaimed. In particular this means that if most of the memory is occupied by cached pages or VFS cache the allocation will fail. One way around this problem is to simply increase the minimum amount of memory the kernel will attempt to keep available. That's what the above suggested fix does. It certainly seems to solve the problem as the free memory never dips below the point crashes begin to occur when starting the camera. However, a better solution might be to fix the kernel code leading up to the allocation. I believe if @faux123
adds the latest version of scatterlist.c to his kernel repo it may solve the problem as the lines modifying the GFP mask which is originally a standard GFP_KERNEL to the "non-waiting" kind is no longer present.
The problematic code in __sg_alloc_table is
int __sg_alloc_table(struct sg_table *table, unsigned int nents,
unsigned int max_ents, gfp_t gfp_mask,
gfp_mask &= ~__GFP_WAIT;
gfp_mask |= __GFP_HIGH;
Perhaps I'll fork the repo and try to apply the fix myself later.