VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
2874c5fd28426 (Thomas Gleixner       2019-05-27 08:55:01 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   2) /* FS-Cache cache handling
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   3)  *
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   4)  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   5)  * Written by David Howells (dhowells@redhat.com)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   6)  */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   7) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   8) #define FSCACHE_DEBUG_LEVEL CACHE
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100   9) #include <linux/module.h>
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  10) #include <linux/slab.h>
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  11) #include "internal.h"
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  12) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  13) LIST_HEAD(fscache_cache_list);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  14) DECLARE_RWSEM(fscache_addremove_sem);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100  15) DECLARE_WAIT_QUEUE_HEAD(fscache_cache_cleared_wq);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100  16) EXPORT_SYMBOL(fscache_cache_cleared_wq);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  17) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  18) static LIST_HEAD(fscache_cache_tag_list);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  19) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  20) /*
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  21)  * look up a cache tag
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  22)  */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  23) struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  24) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  25) 	struct fscache_cache_tag *tag, *xtag;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  26) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  27) 	/* firstly check for the existence of the tag under read lock */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  28) 	down_read(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  29) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  30) 	list_for_each_entry(tag, &fscache_cache_tag_list, link) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  31) 		if (strcmp(tag->name, name) == 0) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  32) 			atomic_inc(&tag->usage);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  33) 			up_read(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  34) 			return tag;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  35) 		}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  36) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  37) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  38) 	up_read(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  39) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  40) 	/* the tag does not exist - create a candidate */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  41) 	xtag = kzalloc(sizeof(*xtag) + strlen(name) + 1, GFP_KERNEL);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  42) 	if (!xtag)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  43) 		/* return a dummy tag if out of memory */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  44) 		return ERR_PTR(-ENOMEM);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  45) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  46) 	atomic_set(&xtag->usage, 1);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  47) 	strcpy(xtag->name, name);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  48) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  49) 	/* write lock, search again and add if still not present */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  50) 	down_write(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  51) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  52) 	list_for_each_entry(tag, &fscache_cache_tag_list, link) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  53) 		if (strcmp(tag->name, name) == 0) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  54) 			atomic_inc(&tag->usage);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  55) 			up_write(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  56) 			kfree(xtag);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  57) 			return tag;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  58) 		}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  59) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  60) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  61) 	list_add_tail(&xtag->link, &fscache_cache_tag_list);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  62) 	up_write(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  63) 	return xtag;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  64) }
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  65) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  66) /*
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  67)  * release a reference to a cache tag
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  68)  */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  69) void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  70) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  71) 	if (tag != ERR_PTR(-ENOMEM)) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  72) 		down_write(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  73) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  74) 		if (atomic_dec_and_test(&tag->usage))
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  75) 			list_del_init(&tag->link);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  76) 		else
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  77) 			tag = NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  78) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  79) 		up_write(&fscache_addremove_sem);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  80) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  81) 		kfree(tag);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  82) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  83) }
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  84) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  85) /*
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  86)  * select a cache in which to store an object
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  87)  * - the cache addremove semaphore must be at least read-locked by the caller
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  88)  * - the object will never be an index
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  89)  */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  90) struct fscache_cache *fscache_select_cache_for_object(
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  91) 	struct fscache_cookie *cookie)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  92) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  93) 	struct fscache_cache_tag *tag;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  94) 	struct fscache_object *object;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  95) 	struct fscache_cache *cache;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  96) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  97) 	_enter("");
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  98) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100  99) 	if (list_empty(&fscache_cache_list)) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 100) 		_leave(" = NULL [no cache]");
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 101) 		return NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 102) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 103) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 104) 	/* we check the parent to determine the cache to use */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 105) 	spin_lock(&cookie->lock);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 106) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 107) 	/* the first in the parent's backing list should be the preferred
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 108) 	 * cache */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 109) 	if (!hlist_empty(&cookie->backing_objects)) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 110) 		object = hlist_entry(cookie->backing_objects.first,
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 111) 				     struct fscache_object, cookie_link);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 112) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 113) 		cache = object->cache;
493f7bc11457b (David Howells         2013-05-10 19:50:26 +0100 114) 		if (fscache_object_is_dying(object) ||
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 115) 		    test_bit(FSCACHE_IOERROR, &cache->flags))
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 116) 			cache = NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 117) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 118) 		spin_unlock(&cookie->lock);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 119) 		_leave(" = %p [parent]", cache);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 120) 		return cache;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 121) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 122) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 123) 	/* the parent is unbacked */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 124) 	if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 125) 		/* cookie not an index and is unbacked */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 126) 		spin_unlock(&cookie->lock);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 127) 		_leave(" = NULL [cookie ub,ni]");
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 128) 		return NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 129) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 130) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 131) 	spin_unlock(&cookie->lock);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 132) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 133) 	if (!cookie->def->select_cache)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 134) 		goto no_preference;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 135) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 136) 	/* ask the netfs for its preference */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 137) 	tag = cookie->def->select_cache(cookie->parent->netfs_data,
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 138) 					cookie->netfs_data);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 139) 	if (!tag)
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 140) 		goto no_preference;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 141) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 142) 	if (tag == ERR_PTR(-ENOMEM)) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 143) 		_leave(" = NULL [nomem tag]");
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 144) 		return NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 145) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 146) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 147) 	if (!tag->cache) {
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 148) 		_leave(" = NULL [unbacked tag]");
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 149) 		return NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 150) 	}
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 151) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 152) 	if (test_bit(FSCACHE_IOERROR, &tag->cache->flags))
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 153) 		return NULL;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 154) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 155) 	_leave(" = %p [specific]", tag->cache);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 156) 	return tag->cache;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 157) 
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 158) no_preference:
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 159) 	/* netfs has no preference - just select first cache */
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 160) 	cache = list_entry(fscache_cache_list.next,
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 161) 			   struct fscache_cache, link);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 162) 	_leave(" = %p [first]", cache);
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 163) 	return cache;
0e04d4cefcf4d (David Howells         2009-04-03 16:42:37 +0100 164) }
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 165) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 166) /**
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 167)  * fscache_init_cache - Initialise a cache record
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 168)  * @cache: The cache record to be initialised
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 169)  * @ops: The cache operations to be installed in that record
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 170)  * @idfmt: Format string to define identifier
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 171)  * @...: sprintf-style arguments
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 172)  *
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 173)  * Initialise a record of a cache and fill in the name.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 174)  *
0e822145b5642 (Mauro Carvalho Chehab 2020-04-27 23:16:58 +0200 175)  * See Documentation/filesystems/caching/backend-api.rst for a complete
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 176)  * description.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 177)  */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 178) void fscache_init_cache(struct fscache_cache *cache,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 179) 			const struct fscache_cache_ops *ops,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 180) 			const char *idfmt,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 181) 			...)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 182) {
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 183) 	va_list va;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 184) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 185) 	memset(cache, 0, sizeof(*cache));
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 186) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 187) 	cache->ops = ops;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 188) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 189) 	va_start(va, idfmt);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 190) 	vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 191) 	va_end(va);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 192) 
952efe7b7840e (David Howells         2009-04-03 16:42:39 +0100 193) 	INIT_WORK(&cache->op_gc, fscache_operation_gc);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 194) 	INIT_LIST_HEAD(&cache->link);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 195) 	INIT_LIST_HEAD(&cache->object_list);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 196) 	INIT_LIST_HEAD(&cache->op_gc_list);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 197) 	spin_lock_init(&cache->object_list_lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 198) 	spin_lock_init(&cache->op_gc_list_lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 199) }
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 200) EXPORT_SYMBOL(fscache_init_cache);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 201) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 202) /**
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 203)  * fscache_add_cache - Declare a cache as being open for business
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 204)  * @cache: The record describing the cache
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 205)  * @ifsdef: The record of the cache object describing the top-level index
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 206)  * @tagname: The tag describing this cache
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 207)  *
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 208)  * Add a cache to the system, making it available for netfs's to use.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 209)  *
0e822145b5642 (Mauro Carvalho Chehab 2020-04-27 23:16:58 +0200 210)  * See Documentation/filesystems/caching/backend-api.rst for a complete
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 211)  * description.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 212)  */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 213) int fscache_add_cache(struct fscache_cache *cache,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 214) 		      struct fscache_object *ifsdef,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 215) 		      const char *tagname)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 216) {
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 217) 	struct fscache_cache_tag *tag;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 218) 
f29507ce66701 (Kiran Kumar Modukuri  2018-06-21 13:31:44 -0700 219) 	ASSERTCMP(ifsdef->cookie, ==, &fscache_fsdef_index);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 220) 	BUG_ON(!cache->ops);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 221) 	BUG_ON(!ifsdef);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 222) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 223) 	cache->flags = 0;
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 224) 	ifsdef->event_mask =
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 225) 		((1 << NR_FSCACHE_OBJECT_EVENTS) - 1) &
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 226) 		~(1 << FSCACHE_OBJECT_EV_CLEARED);
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 227) 	__set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &ifsdef->flags);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 228) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 229) 	if (!tagname)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 230) 		tagname = cache->identifier;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 231) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 232) 	BUG_ON(!tagname[0]);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 233) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 234) 	_enter("{%s.%s},,%s", cache->ops->name, cache->identifier, tagname);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 235) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 236) 	/* we use the cache tag to uniquely identify caches */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 237) 	tag = __fscache_lookup_cache_tag(tagname);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 238) 	if (IS_ERR(tag))
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 239) 		goto nomem;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 240) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 241) 	if (test_and_set_bit(FSCACHE_TAG_RESERVED, &tag->flags))
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 242) 		goto tag_in_use;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 243) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 244) 	cache->kobj = kobject_create_and_add(tagname, fscache_root);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 245) 	if (!cache->kobj)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 246) 		goto error;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 247) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 248) 	ifsdef->cache = cache;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 249) 	cache->fsdef = ifsdef;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 250) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 251) 	down_write(&fscache_addremove_sem);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 252) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 253) 	tag->cache = cache;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 254) 	cache->tag = tag;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 255) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 256) 	/* add the cache to the list */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 257) 	list_add(&cache->link, &fscache_cache_list);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 258) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 259) 	/* add the cache's netfs definition index object to the cache's
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 260) 	 * list */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 261) 	spin_lock(&cache->object_list_lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 262) 	list_add_tail(&ifsdef->cache_link, &cache->object_list);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 263) 	spin_unlock(&cache->object_list_lock);
4fbf4291aa159 (David Howells         2009-11-19 18:11:04 +0000 264) 	fscache_objlist_add(ifsdef);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 265) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 266) 	/* add the cache's netfs definition index object to the top level index
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 267) 	 * cookie as a known backing object */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 268) 	spin_lock(&fscache_fsdef_index.lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 269) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 270) 	hlist_add_head(&ifsdef->cookie_link,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 271) 		       &fscache_fsdef_index.backing_objects);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 272) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 273) 	atomic_inc(&fscache_fsdef_index.usage);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 274) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 275) 	/* done */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 276) 	spin_unlock(&fscache_fsdef_index.lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 277) 	up_write(&fscache_addremove_sem);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 278) 
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 279) 	pr_notice("Cache \"%s\" added (type %s)\n",
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 280) 		  cache->tag->name, cache->ops->name);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 281) 	kobject_uevent(cache->kobj, KOBJ_ADD);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 282) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 283) 	_leave(" = 0 [%s]", cache->identifier);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 284) 	return 0;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 285) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 286) tag_in_use:
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 287) 	pr_err("Cache tag '%s' already in use\n", tagname);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 288) 	__fscache_release_cache_tag(tag);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 289) 	_leave(" = -EXIST");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 290) 	return -EEXIST;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 291) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 292) error:
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 293) 	__fscache_release_cache_tag(tag);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 294) 	_leave(" = -EINVAL");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 295) 	return -EINVAL;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 296) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 297) nomem:
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 298) 	_leave(" = -ENOMEM");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 299) 	return -ENOMEM;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 300) }
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 301) EXPORT_SYMBOL(fscache_add_cache);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 302) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 303) /**
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 304)  * fscache_io_error - Note a cache I/O error
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 305)  * @cache: The record describing the cache
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 306)  *
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 307)  * Note that an I/O error occurred in a cache and that it should no longer be
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 308)  * used for anything.  This also reports the error into the kernel log.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 309)  *
0e822145b5642 (Mauro Carvalho Chehab 2020-04-27 23:16:58 +0200 310)  * See Documentation/filesystems/caching/backend-api.rst for a complete
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 311)  * description.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 312)  */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 313) void fscache_io_error(struct fscache_cache *cache)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 314) {
75bc411388f4a (David Howells         2012-12-05 13:34:48 +0000 315) 	if (!test_and_set_bit(FSCACHE_IOERROR, &cache->flags))
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 316) 		pr_err("Cache '%s' stopped due to I/O error\n",
75bc411388f4a (David Howells         2012-12-05 13:34:48 +0000 317) 		       cache->ops->name);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 318) }
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 319) EXPORT_SYMBOL(fscache_io_error);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 320) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 321) /*
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 322)  * request withdrawal of all the objects in a cache
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 323)  * - all the objects being withdrawn are moved onto the supplied list
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 324)  */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 325) static void fscache_withdraw_all_objects(struct fscache_cache *cache,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 326) 					 struct list_head *dying_objects)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 327) {
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 328) 	struct fscache_object *object;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 329) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 330) 	while (!list_empty(&cache->object_list)) {
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 331) 		spin_lock(&cache->object_list_lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 332) 
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 333) 		if (!list_empty(&cache->object_list)) {
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 334) 			object = list_entry(cache->object_list.next,
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 335) 					    struct fscache_object, cache_link);
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 336) 			list_move_tail(&object->cache_link, dying_objects);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 337) 
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 338) 			_debug("withdraw %p", object->cookie);
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 339) 
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 340) 			/* This must be done under object_list_lock to prevent
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 341) 			 * a race with fscache_drop_object().
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 342) 			 */
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 343) 			fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 344) 		}
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 345) 
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 346) 		spin_unlock(&cache->object_list_lock);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 347) 		cond_resched();
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 348) 	}
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 349) }
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 350) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 351) /**
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 352)  * fscache_withdraw_cache - Withdraw a cache from the active service
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 353)  * @cache: The record describing the cache
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 354)  *
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 355)  * Withdraw a cache from service, unbinding all its cache objects from the
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 356)  * netfs cookies they're currently representing.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 357)  *
0e822145b5642 (Mauro Carvalho Chehab 2020-04-27 23:16:58 +0200 358)  * See Documentation/filesystems/caching/backend-api.rst for a complete
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 359)  * description.
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 360)  */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 361) void fscache_withdraw_cache(struct fscache_cache *cache)
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 362) {
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 363) 	LIST_HEAD(dying_objects);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 364) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 365) 	_enter("");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 366) 
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 367) 	pr_notice("Withdrawing cache \"%s\"\n",
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 368) 		  cache->tag->name);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 369) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 370) 	/* make the cache unavailable for cookie acquisition */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 371) 	if (test_and_set_bit(FSCACHE_CACHE_WITHDRAWN, &cache->flags))
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 372) 		BUG();
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 373) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 374) 	down_write(&fscache_addremove_sem);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 375) 	list_del_init(&cache->link);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 376) 	cache->tag->cache = NULL;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 377) 	up_write(&fscache_addremove_sem);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 378) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 379) 	/* make sure all pages pinned by operations on behalf of the netfs are
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 380) 	 * written to disk */
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 381) 	fscache_stat(&fscache_n_cop_sync_cache);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 382) 	cache->ops->sync_cache(cache);
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 383) 	fscache_stat_d(&fscache_n_cop_sync_cache);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 384) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 385) 	/* dissociate all the netfs pages backed by this cache from the block
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 386) 	 * mappings in the cache */
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 387) 	fscache_stat(&fscache_n_cop_dissociate_pages);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 388) 	cache->ops->dissociate_pages(cache);
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 389) 	fscache_stat_d(&fscache_n_cop_dissociate_pages);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 390) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 391) 	/* we now have to destroy all the active objects pertaining to this
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 392) 	 * cache - which we do by passing them off to thread pool to be
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 393) 	 * disposed of */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 394) 	_debug("destroy");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 395) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 396) 	fscache_withdraw_all_objects(cache, &dying_objects);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 397) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 398) 	/* wait for all extant objects to finish their outstanding operations
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 399) 	 * and go away */
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 400) 	_debug("wait for finish");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 401) 	wait_event(fscache_cache_cleared_wq,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 402) 		   atomic_read(&cache->object_count) == 0);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 403) 	_debug("wait for clearance");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 404) 	wait_event(fscache_cache_cleared_wq,
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 405) 		   list_empty(&cache->object_list));
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 406) 	_debug("cleared");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 407) 	ASSERT(list_empty(&dying_objects));
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 408) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 409) 	kobject_put(cache->kobj);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 410) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 411) 	clear_bit(FSCACHE_TAG_RESERVED, &cache->tag->flags);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 412) 	fscache_release_cache_tag(cache->tag);
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 413) 	cache->tag = NULL;
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 414) 
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 415) 	_leave("");
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 416) }
4c515dd47ab41 (David Howells         2009-04-03 16:42:37 +0100 417) EXPORT_SYMBOL(fscache_withdraw_cache);