[PATCH] cachefiles: Eliminate racy check in cachefiles_read_copier which causes page reference leaks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I had earlier reported we were seeing page reference leaks when using fscache + cachefiles + ext4 on a number of our machines.  Analysis of the vmscan path has shown that cachefile pages are getting pinned in memory due to an elevated reference count which never goes down due cachefiles_read_copier checking the pending work list in a racy manner and failing to enqueue the operation again when rescheduling.  The attached patch eliminates the racy check and the rescheduling as well.  The rationale for eliminating the rescheduling is the readahead code limits the number of pages in any one readpages() invocation so cachefile_read_copier's work list will not grow unbounded AFAICT.  Also, when the cpu is under constant load it can be a while before the extra page reference is dropped and such pages can wind up at the tail of the LRU which slows down vmscan.  Keeping pages pinned for longer than necessary seems less desirablethan stealing some cpu time
 from the user processes.  The patch is against 3.15.9.

Thanks,
Shantanu

diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index 25e745b..ad74a6a 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -151,7 +151,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
        struct cachefiles_one_read *monitor;
        struct cachefiles_object *object;
        struct fscache_retrieval *op;
-       int error, max;
+       int error;
 
        op = container_of(_op, struct fscache_retrieval, op);
        object = container_of(op->op.object,
@@ -159,7 +159,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
 
        _enter("{ino=%lu}", object->backer->d_inode->i_ino);
 
-       max = 8;
        spin_lock_irq(&object->work_lock);
 
        while (!list_empty(&op->to_do)) {
@@ -203,15 +202,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
                kfree(monitor);
 
        next:
-               /* let the thread pool have some air occasionally */
-               max--;
-               if (max < 0 || need_resched()) {
-                       if (!list_empty(&op->to_do))
-                               fscache_enqueue_retrieval(op);
-                       _leave(" [maxed out]");
-                       return;
-               }
-
                spin_lock_irq(&object->work_lock);
        }

--
Linux-cachefs mailing list
Linux-cachefs@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/linux-cachefs





[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]
  Powered by Linux