Skip to content

Commit 9a24ce5

Browse files
kiran-modukuridhowells
authored andcommitted
cachefiles: Fix page leak in cachefiles_read_backing_file while vmscan is active
[Description] In a heavily loaded system where the system pagecache is nearing memory limits and fscache is enabled, pages can be leaked by fscache while trying read pages from cachefiles backend. This can happen because two applications can be reading same page from a single mount, two threads can be trying to read the backing page at same time. This results in one of the threads finding that a page for the backing file or netfs file is already in the radix tree. During the error handling cachefiles does not clean up the reference on backing page, leading to page leak. [Fix] The fix is straightforward, to decrement the reference when error is encountered. [dhowells: Note that I've removed the clearance and put of newpage as they aren't attested in the commit message and don't appear to actually achieve anything since a new page is only allocated is newpage!=NULL and any residual new page is cleared before returning.] [Testing] I have tested the fix using following method for 12+ hrs. 1) mkdir -p /mnt/nfs ; mount -o vers=3,fsc <server_ip>:/export /mnt/nfs 2) create 10000 files of 2.8MB in a NFS mount. 3) start a thread to simulate heavy VM presssure (while true ; do echo 3 > /proc/sys/vm/drop_caches ; sleep 1 ; done)& 4) start multiple parallel reader for data set at same time find /mnt/nfs -type f | xargs -P 80 cat > /dev/null & find /mnt/nfs -type f | xargs -P 80 cat > /dev/null & find /mnt/nfs -type f | xargs -P 80 cat > /dev/null & .. .. find /mnt/nfs -type f | xargs -P 80 cat > /dev/null & find /mnt/nfs -type f | xargs -P 80 cat > /dev/null & 5) finally check using cat /proc/fs/fscache/stats | grep -i pages ; free -h , cat /proc/meminfo and page-types -r -b lru to ensure all pages are freed. Reviewed-by: Daniel Axtens <[email protected]> Signed-off-by: Shantanu Goel <[email protected]> Signed-off-by: Kiran Kumar Modukuri <[email protected]> [dja: forward ported to current upstream] Signed-off-by: Daniel Axtens <[email protected]> Signed-off-by: David Howells <[email protected]>
1 parent 3f2b7b9 commit 9a24ce5

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

fs/cachefiles/rdwr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
535535
netpage->index, cachefiles_gfp);
536536
if (ret < 0) {
537537
if (ret == -EEXIST) {
538+
put_page(backpage);
539+
backpage = NULL;
538540
put_page(netpage);
541+
netpage = NULL;
539542
fscache_retrieval_complete(op, 1);
540543
continue;
541544
}
@@ -608,7 +611,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
608611
netpage->index, cachefiles_gfp);
609612
if (ret < 0) {
610613
if (ret == -EEXIST) {
614+
put_page(backpage);
615+
backpage = NULL;
611616
put_page(netpage);
617+
netpage = NULL;
612618
fscache_retrieval_complete(op, 1);
613619
continue;
614620
}

0 commit comments

Comments
 (0)