In afs_linux_write_begin, we call grab_cache_page_write_begin to get a
page to use for writing data when servicing a write into AFS. Under
low-memory conditions, this can return NULL if Linux cannot find a
free page to use. Currently, we always try to reference the page
returned, and so this causes a BUG.
To avoid this, check if grab_cache_page_write_begin returns NULL, and
just return -ENOMEM, like other callers of grab_cache_page_write_begin
do.
Linux's fault injection framework is useful for testing code paths
like these. The following settings made it possible to
somewhat-reliably exercise the relevant code path on a test RHEL7
system:
# grep ^ /sys/kernel/debug/fail_page_alloc/*
/sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem:Y
/sys/kernel/debug/fail_page_alloc/ignore-gfp-wait:N
/sys/kernel/debug/fail_page_alloc/interval:1
/sys/kernel/debug/fail_page_alloc/min-order:0
/sys/kernel/debug/fail_page_alloc/probability:100
/sys/kernel/debug/fail_page_alloc/space:90
/sys/kernel/debug/fail_page_alloc/task-filter:Y
/sys/kernel/debug/fail_page_alloc/times:-1
[...]
Change-Id: I00908658ae43aa3c8e12f2a0b956016d4441016c
Reviewed-on: https://gerrit.openafs.org/13242
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
int code;
page = grab_cache_page_write_begin(mapping, index, flags);
+ if (!page) {
+ return -ENOMEM;
+ }
+
*pagep = page;
code = afs_linux_prepare_write(file, page, from, from + len);