diff options
Diffstat (limited to 'fs/cachefiles/cache.c')
| -rw-r--r-- | fs/cachefiles/cache.c | 45 | 
1 files changed, 44 insertions, 1 deletions
diff --git a/fs/cachefiles/cache.c b/fs/cachefiles/cache.c index f449f7340aad..9fb06dc16520 100644 --- a/fs/cachefiles/cache.c +++ b/fs/cachefiles/cache.c @@ -8,6 +8,7 @@  #include <linux/slab.h>  #include <linux/statfs.h>  #include <linux/namei.h> +#include <trace/events/fscache.h>  #include "internal.h"  /* @@ -312,19 +313,59 @@ static void cachefiles_withdraw_objects(struct cachefiles_cache *cache)  }  /* - * Withdraw volumes. + * Withdraw fscache volumes. + */ +static void cachefiles_withdraw_fscache_volumes(struct cachefiles_cache *cache) +{ +	struct list_head *cur; +	struct cachefiles_volume *volume; +	struct fscache_volume *vcookie; + +	_enter(""); +retry: +	spin_lock(&cache->object_list_lock); +	list_for_each(cur, &cache->volumes) { +		volume = list_entry(cur, struct cachefiles_volume, cache_link); + +		if (atomic_read(&volume->vcookie->n_accesses) == 0) +			continue; + +		vcookie = fscache_try_get_volume(volume->vcookie, +						 fscache_volume_get_withdraw); +		if (vcookie) { +			spin_unlock(&cache->object_list_lock); +			fscache_withdraw_volume(vcookie); +			fscache_put_volume(vcookie, fscache_volume_put_withdraw); +			goto retry; +		} +	} +	spin_unlock(&cache->object_list_lock); + +	_leave(""); +} + +/* + * Withdraw cachefiles volumes.   */  static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)  {  	_enter("");  	for (;;) { +		struct fscache_volume *vcookie = NULL;  		struct cachefiles_volume *volume = NULL;  		spin_lock(&cache->object_list_lock);  		if (!list_empty(&cache->volumes)) {  			volume = list_first_entry(&cache->volumes,  						  struct cachefiles_volume, cache_link); +			vcookie = fscache_try_get_volume(volume->vcookie, +							 fscache_volume_get_withdraw); +			if (!vcookie) { +				spin_unlock(&cache->object_list_lock); +				cpu_relax(); +				continue; +			}  			list_del_init(&volume->cache_link);  		}  		spin_unlock(&cache->object_list_lock); @@ -332,6 +373,7 @@ static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)  			break;  		cachefiles_withdraw_volume(volume); +		fscache_put_volume(vcookie, fscache_volume_put_withdraw);  	}  	_leave(""); @@ -371,6 +413,7 @@ void cachefiles_withdraw_cache(struct cachefiles_cache *cache)  	pr_info("File cache on %s unregistering\n", fscache->name);  	fscache_withdraw_cache(fscache); +	cachefiles_withdraw_fscache_volumes(cache);  	/* we now have to destroy all the active objects pertaining to this  	 * cache - which we do by passing them off to thread pool to be  |