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
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100   2) /* netfs cookie management
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100   3)  *
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100   4)  * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100   5)  * Written by David Howells (dhowells@redhat.com)
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100   6)  *
efc930fa1d844 (Mauro Carvalho Chehab 2020-04-27 23:16:55 +0200   7)  * See Documentation/filesystems/caching/netfs-api.rst for more information on
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100   8)  * the netfs API.
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100   9)  */
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  10) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  11) #define FSCACHE_DEBUG_LEVEL COOKIE
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  12) #include <linux/module.h>
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  13) #include <linux/slab.h>
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  14) #include "internal.h"
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  15) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  16) struct kmem_cache *fscache_cookie_jar;
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100  17) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  18) static atomic_t fscache_object_debug_id = ATOMIC_INIT(0);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  19) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  20) #define fscache_cookie_hash_shift 15
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  21) static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift];
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  22) 
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100  23) static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie,
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100  24) 					    loff_t object_size);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  25) static int fscache_alloc_object(struct fscache_cache *cache,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  26) 				struct fscache_cookie *cookie);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  27) static int fscache_attach_object(struct fscache_cookie *cookie,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  28) 				 struct fscache_object *object);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100  29) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  30) static void fscache_print_cookie(struct fscache_cookie *cookie, char prefix)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  31) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  32) 	struct hlist_node *object;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  33) 	const u8 *k;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  34) 	unsigned loop;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  35) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  36) 	pr_err("%c-cookie c=%p [p=%p fl=%lx nc=%u na=%u]\n",
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  37) 	       prefix, cookie, cookie->parent, cookie->flags,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  38) 	       atomic_read(&cookie->n_children),
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  39) 	       atomic_read(&cookie->n_active));
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  40) 	pr_err("%c-cookie d=%p n=%p\n",
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  41) 	       prefix, cookie->def, cookie->netfs_data);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  42) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  43) 	object = READ_ONCE(cookie->backing_objects.first);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  44) 	if (object)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  45) 		pr_err("%c-cookie o=%p\n",
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  46) 		       prefix, hlist_entry(object, struct fscache_object, cookie_link));
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  47) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  48) 	pr_err("%c-key=[%u] '", prefix, cookie->key_len);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  49) 	k = (cookie->key_len <= sizeof(cookie->inline_key)) ?
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  50) 		cookie->inline_key : cookie->key;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  51) 	for (loop = 0; loop < cookie->key_len; loop++)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  52) 		pr_cont("%02x", k[loop]);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  53) 	pr_cont("'\n");
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  54) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  55) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  56) void fscache_free_cookie(struct fscache_cookie *cookie)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  57) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  58) 	if (cookie) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  59) 		BUG_ON(!hlist_empty(&cookie->backing_objects));
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  60) 		if (cookie->aux_len > sizeof(cookie->inline_aux))
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  61) 			kfree(cookie->aux);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  62) 		if (cookie->key_len > sizeof(cookie->inline_key))
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  63) 			kfree(cookie->key);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  64) 		kmem_cache_free(fscache_cookie_jar, cookie);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  65) 	}
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  66) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  67) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  68) /*
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100  69)  * Set the index key in a cookie.  The cookie struct has space for a 16-byte
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  70)  * key plus length and hash, but if that's not big enough, it's instead a
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  71)  * pointer to a buffer containing 3 bytes of hash, 1 byte of length and then
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  72)  * the key data.
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  73)  */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  74) static int fscache_set_key(struct fscache_cookie *cookie,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  75) 			   const void *index_key, size_t index_key_len)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  76) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  77) 	unsigned long long h;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  78) 	u32 *buf;
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100  79) 	int bufs;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  80) 	int i;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  81) 
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100  82) 	bufs = DIV_ROUND_UP(index_key_len, sizeof(*buf));
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100  83) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  84) 	if (index_key_len > sizeof(cookie->inline_key)) {
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100  85) 		buf = kcalloc(bufs, sizeof(*buf), GFP_KERNEL);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  86) 		if (!buf)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  87) 			return -ENOMEM;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  88) 		cookie->key = buf;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  89) 	} else {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  90) 		buf = (u32 *)cookie->inline_key;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  91) 	}
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  92) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  93) 	memcpy(buf, index_key, index_key_len);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  94) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  95) 	/* Calculate a hash and combine this with the length in the first word
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  96) 	 * or first half word
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  97) 	 */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  98) 	h = (unsigned long)cookie->parent;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100  99) 	h += index_key_len + cookie->type;
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100 100) 
fa520c47eaa15 (Eric Sandeen          2018-10-17 15:23:59 +0100 101) 	for (i = 0; i < bufs; i++)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 102) 		h += buf[i];
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 103) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 104) 	cookie->key_hash = h ^ (h >> 32);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 105) 	return 0;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 106) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 107) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 108) static long fscache_compare_cookie(const struct fscache_cookie *a,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 109) 				   const struct fscache_cookie *b)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 110) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 111) 	const void *ka, *kb;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 112) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 113) 	if (a->key_hash != b->key_hash)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 114) 		return (long)a->key_hash - (long)b->key_hash;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 115) 	if (a->parent != b->parent)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 116) 		return (long)a->parent - (long)b->parent;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 117) 	if (a->key_len != b->key_len)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 118) 		return (long)a->key_len - (long)b->key_len;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 119) 	if (a->type != b->type)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 120) 		return (long)a->type - (long)b->type;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 121) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 122) 	if (a->key_len <= sizeof(a->inline_key)) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 123) 		ka = &a->inline_key;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 124) 		kb = &b->inline_key;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 125) 	} else {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 126) 		ka = a->key;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 127) 		kb = b->key;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 128) 	}
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 129) 	return memcmp(ka, kb, a->key_len);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 130) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 131) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 132) /*
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 133)  * Allocate a cookie.
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 134)  */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 135) struct fscache_cookie *fscache_alloc_cookie(
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 136) 	struct fscache_cookie *parent,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 137) 	const struct fscache_cookie_def *def,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 138) 	const void *index_key, size_t index_key_len,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 139) 	const void *aux_data, size_t aux_data_len,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 140) 	void *netfs_data,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 141) 	loff_t object_size)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 142) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 143) 	struct fscache_cookie *cookie;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 144) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 145) 	/* allocate and initialise a cookie */
1ff22883b0b2f (David Howells         2018-10-17 15:23:45 +0100 146) 	cookie = kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 147) 	if (!cookie)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 148) 		return NULL;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 149) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 150) 	cookie->key_len = index_key_len;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 151) 	cookie->aux_len = aux_data_len;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 152) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 153) 	if (fscache_set_key(cookie, index_key, index_key_len) < 0)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 154) 		goto nomem;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 155) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 156) 	if (cookie->aux_len <= sizeof(cookie->inline_aux)) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 157) 		memcpy(cookie->inline_aux, aux_data, cookie->aux_len);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 158) 	} else {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 159) 		cookie->aux = kmemdup(aux_data, cookie->aux_len, GFP_KERNEL);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 160) 		if (!cookie->aux)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 161) 			goto nomem;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 162) 	}
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 163) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 164) 	atomic_set(&cookie->usage, 1);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 165) 	atomic_set(&cookie->n_children, 0);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 166) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 167) 	/* We keep the active count elevated until relinquishment to prevent an
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 168) 	 * attempt to wake up every time the object operations queue quiesces.
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 169) 	 */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 170) 	atomic_set(&cookie->n_active, 1);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 171) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 172) 	cookie->def		= def;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 173) 	cookie->parent		= parent;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 174) 	cookie->netfs_data	= netfs_data;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 175) 	cookie->flags		= (1 << FSCACHE_COOKIE_NO_DATA_YET);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 176) 	cookie->type		= def->type;
1ff22883b0b2f (David Howells         2018-10-17 15:23:45 +0100 177) 	spin_lock_init(&cookie->lock);
1ff22883b0b2f (David Howells         2018-10-17 15:23:45 +0100 178) 	spin_lock_init(&cookie->stores_lock);
1ff22883b0b2f (David Howells         2018-10-17 15:23:45 +0100 179) 	INIT_HLIST_HEAD(&cookie->backing_objects);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 180) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 181) 	/* radix tree insertion won't use the preallocation pool unless it's
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 182) 	 * told it may not wait */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 183) 	INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 184) 	return cookie;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 185) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 186) nomem:
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 187) 	fscache_free_cookie(cookie);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 188) 	return NULL;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 189) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 190) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 191) /*
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 192)  * Attempt to insert the new cookie into the hash.  If there's a collision, we
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 193)  * return the old cookie if it's not in use and an error otherwise.
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 194)  */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 195) struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 196) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 197) 	struct fscache_cookie *cursor;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 198) 	struct hlist_bl_head *h;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 199) 	struct hlist_bl_node *p;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 200) 	unsigned int bucket;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 201) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 202) 	bucket = candidate->key_hash & (ARRAY_SIZE(fscache_cookie_hash) - 1);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 203) 	h = &fscache_cookie_hash[bucket];
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 204) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 205) 	hlist_bl_lock(h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 206) 	hlist_bl_for_each_entry(cursor, p, h, hash_link) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 207) 		if (fscache_compare_cookie(candidate, cursor) == 0)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 208) 			goto collision;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 209) 	}
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 210) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 211) 	__set_bit(FSCACHE_COOKIE_ACQUIRED, &candidate->flags);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 212) 	fscache_cookie_get(candidate->parent, fscache_cookie_get_acquire_parent);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 213) 	atomic_inc(&candidate->parent->n_children);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 214) 	hlist_bl_add_head(&candidate->hash_link, h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 215) 	hlist_bl_unlock(h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 216) 	return candidate;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 217) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 218) collision:
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 219) 	if (test_and_set_bit(FSCACHE_COOKIE_ACQUIRED, &cursor->flags)) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 220) 		trace_fscache_cookie(cursor, fscache_cookie_collision,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 221) 				     atomic_read(&cursor->usage));
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 222) 		pr_err("Duplicate cookie detected\n");
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 223) 		fscache_print_cookie(cursor, 'O');
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 224) 		fscache_print_cookie(candidate, 'N');
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 225) 		hlist_bl_unlock(h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 226) 		return NULL;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 227) 	}
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 228) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 229) 	fscache_cookie_get(cursor, fscache_cookie_get_reacquire);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 230) 	hlist_bl_unlock(h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 231) 	return cursor;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 232) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 233) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 234) /*
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 235)  * request a cookie to represent an object (index, datafile, xattr, etc)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 236)  * - parent specifies the parent object
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 237)  *   - the top level index cookie for each netfs is stored in the fscache_netfs
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 238)  *     struct upon registration
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 239)  * - def points to the definition
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 240)  * - the netfs_data will be passed to the functions pointed to in *def
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 241)  * - all attached caches will be searched to see if they contain this object
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 242)  * - index objects aren't stored on disk until there's a dependent file that
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 243)  *   needs storing
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 244)  * - other objects are stored in a selected cache immediately, and all the
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 245)  *   indices forming the path to it are instantiated if necessary
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 246)  * - we never let on to the netfs about errors
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 247)  *   - we may set a negative cookie pointer, but that's okay
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 248)  */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 249) struct fscache_cookie *__fscache_acquire_cookie(
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 250) 	struct fscache_cookie *parent,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 251) 	const struct fscache_cookie_def *def,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 252) 	const void *index_key, size_t index_key_len,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 253) 	const void *aux_data, size_t aux_data_len,
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 254) 	void *netfs_data,
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 255) 	loff_t object_size,
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 256) 	bool enable)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 257) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 258) 	struct fscache_cookie *candidate, *cookie;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 259) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 260) 	BUG_ON(!def);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 261) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 262) 	_enter("{%s},{%s},%p,%u",
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 263) 	       parent ? (char *) parent->def->name : "<no-parent>",
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 264) 	       def->name, netfs_data, enable);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 265) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 266) 	if (!index_key || !index_key_len || index_key_len > 255 || aux_data_len > 255)
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 267) 		return NULL;
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 268) 	if (!aux_data || !aux_data_len) {
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 269) 		aux_data = NULL;
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 270) 		aux_data_len = 0;
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 271) 	}
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 272) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 273) 	fscache_stat(&fscache_n_acquires);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 274) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 275) 	/* if there's no parent cookie, then we don't create one here either */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 276) 	if (!parent) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 277) 		fscache_stat(&fscache_n_acquires_null);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 278) 		_leave(" [no parent]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 279) 		return NULL;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 280) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 281) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 282) 	/* validate the definition */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 283) 	BUG_ON(!def->name[0]);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 284) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 285) 	BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 286) 	       parent->type != FSCACHE_COOKIE_TYPE_INDEX);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 287) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 288) 	candidate = fscache_alloc_cookie(parent, def,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 289) 					 index_key, index_key_len,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 290) 					 aux_data, aux_data_len,
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 291) 					 netfs_data, object_size);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 292) 	if (!candidate) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 293) 		fscache_stat(&fscache_n_acquires_oom);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 294) 		_leave(" [ENOMEM]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 295) 		return NULL;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 296) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 297) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 298) 	cookie = fscache_hash_cookie(candidate);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 299) 	if (!cookie) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 300) 		trace_fscache_cookie(candidate, fscache_cookie_discard, 1);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 301) 		goto out;
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 302) 	}
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 303) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 304) 	if (cookie == candidate)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 305) 		candidate = NULL;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 306) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 307) 	switch (cookie->type) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 308) 	case FSCACHE_COOKIE_TYPE_INDEX:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 309) 		fscache_stat(&fscache_n_cookie_index);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 310) 		break;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 311) 	case FSCACHE_COOKIE_TYPE_DATAFILE:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 312) 		fscache_stat(&fscache_n_cookie_data);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 313) 		break;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 314) 	default:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 315) 		fscache_stat(&fscache_n_cookie_special);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 316) 		break;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 317) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 318) 
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 319) 	trace_fscache_acquire(cookie);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 320) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 321) 	if (enable) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 322) 		/* if the object is an index then we need do nothing more here
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 323) 		 * - we create indices on disk when we need them as an index
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 324) 		 * may exist in multiple caches */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 325) 		if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 326) 			if (fscache_acquire_non_index_cookie(cookie, object_size) == 0) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 327) 				set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 328) 			} else {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 329) 				atomic_dec(&parent->n_children);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 330) 				fscache_cookie_put(cookie,
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 331) 						   fscache_cookie_put_acquire_nobufs);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 332) 				fscache_stat(&fscache_n_acquires_nobufs);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 333) 				_leave(" = NULL");
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 334) 				return NULL;
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 335) 			}
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 336) 		} else {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 337) 			set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 338) 		}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 339) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 340) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 341) 	fscache_stat(&fscache_n_acquires_ok);
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 342) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 343) out:
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 344) 	fscache_free_cookie(candidate);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 345) 	return cookie;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 346) }
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 347) EXPORT_SYMBOL(__fscache_acquire_cookie);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 348) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 349) /*
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 350)  * Enable a cookie to permit it to accept new operations.
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 351)  */
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 352) void __fscache_enable_cookie(struct fscache_cookie *cookie,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 353) 			     const void *aux_data,
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 354) 			     loff_t object_size,
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 355) 			     bool (*can_enable)(void *data),
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 356) 			     void *data)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 357) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 358) 	_enter("%p", cookie);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 359) 
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 360) 	trace_fscache_enable(cookie);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 361) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 362) 	wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
743162013d40c (NeilBrown             2014-07-07 15:16:04 +1000 363) 			 TASK_UNINTERRUPTIBLE);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 364) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 365) 	fscache_update_aux(cookie, aux_data);
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 366) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 367) 	if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 368) 		goto out_unlock;
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 369) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 370) 	if (can_enable && !can_enable(data)) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 371) 		/* The netfs decided it didn't want to enable after all */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 372) 	} else if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 373) 		/* Wait for outstanding disablement to complete */
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 374) 		__fscache_wait_on_invalidate(cookie);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 375) 
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 376) 		if (fscache_acquire_non_index_cookie(cookie, object_size) == 0)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 377) 			set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 378) 	} else {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 379) 		set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 380) 	}
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 381) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 382) out_unlock:
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 383) 	clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 384) 	wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 385) }
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 386) EXPORT_SYMBOL(__fscache_enable_cookie);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 387) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 388) /*
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 389)  * acquire a non-index cookie
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 390)  * - this must make sure the index chain is instantiated and instantiate the
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 391)  *   object representation too
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 392)  */
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 393) static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie,
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 394) 					    loff_t object_size)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 395) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 396) 	struct fscache_object *object;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 397) 	struct fscache_cache *cache;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 398) 	int ret;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 399) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 400) 	_enter("");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 401) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 402) 	set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 403) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 404) 	/* now we need to see whether the backing objects for this cookie yet
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 405) 	 * exist, if not there'll be nothing to search */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 406) 	down_read(&fscache_addremove_sem);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 407) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 408) 	if (list_empty(&fscache_cache_list)) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 409) 		up_read(&fscache_addremove_sem);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 410) 		_leave(" = 0 [no caches]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 411) 		return 0;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 412) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 413) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 414) 	/* select a cache in which to store the object */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 415) 	cache = fscache_select_cache_for_object(cookie->parent);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 416) 	if (!cache) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 417) 		up_read(&fscache_addremove_sem);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 418) 		fscache_stat(&fscache_n_acquires_no_cache);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 419) 		_leave(" = -ENOMEDIUM [no cache]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 420) 		return -ENOMEDIUM;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 421) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 422) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 423) 	_debug("cache %s", cache->tag->name);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 424) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 425) 	set_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 426) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 427) 	/* ask the cache to allocate objects for this cookie and its parent
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 428) 	 * chain */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 429) 	ret = fscache_alloc_object(cache, cookie);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 430) 	if (ret < 0) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 431) 		up_read(&fscache_addremove_sem);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 432) 		_leave(" = %d", ret);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 433) 		return ret;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 434) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 435) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 436) 	spin_lock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 437) 	if (hlist_empty(&cookie->backing_objects)) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 438) 		spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 439) 		goto unavailable;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 440) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 441) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 442) 	object = hlist_entry(cookie->backing_objects.first,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 443) 			     struct fscache_object, cookie_link);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 444) 
ee1235a9a0681 (David Howells         2018-04-04 13:41:28 +0100 445) 	fscache_set_store_limit(object, object_size);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 446) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 447) 	/* initiate the process of looking up all the objects in the chain
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 448) 	 * (done by fscache_initialise_object()) */
caaef6900befb (David Howells         2013-05-10 19:50:26 +0100 449) 	fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 450) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 451) 	spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 452) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 453) 	/* we may be required to wait for lookup to complete at this point */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 454) 	if (!fscache_defer_lookup) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 455) 		_debug("non-deferred lookup %p", &cookie->flags);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 456) 		wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
743162013d40c (NeilBrown             2014-07-07 15:16:04 +1000 457) 			    TASK_UNINTERRUPTIBLE);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 458) 		_debug("complete");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 459) 		if (test_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags))
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 460) 			goto unavailable;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 461) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 462) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 463) 	up_read(&fscache_addremove_sem);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 464) 	_leave(" = 0 [deferred]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 465) 	return 0;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 466) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 467) unavailable:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 468) 	up_read(&fscache_addremove_sem);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 469) 	_leave(" = -ENOBUFS");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 470) 	return -ENOBUFS;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 471) }
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 472) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 473) /*
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 474)  * recursively allocate cache object records for a cookie/cache combination
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 475)  * - caller must be holding the addremove sem
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 476)  */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 477) static int fscache_alloc_object(struct fscache_cache *cache,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 478) 				struct fscache_cookie *cookie)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 479) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 480) 	struct fscache_object *object;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 481) 	int ret;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 482) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 483) 	_enter("%p,%p{%s}", cache, cookie, cookie->def->name);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 484) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 485) 	spin_lock(&cookie->lock);
b67bfe0d42cac (Sasha Levin           2013-02-27 17:06:00 -0800 486) 	hlist_for_each_entry(object, &cookie->backing_objects,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 487) 			     cookie_link) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 488) 		if (object->cache == cache)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 489) 			goto object_already_extant;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 490) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 491) 	spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 492) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 493) 	/* ask the cache to allocate an object (we may end up with duplicate
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 494) 	 * objects at this stage, but we sort that out later) */
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 495) 	fscache_stat(&fscache_n_cop_alloc_object);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 496) 	object = cache->ops->alloc_object(cache, cookie);
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 497) 	fscache_stat_d(&fscache_n_cop_alloc_object);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 498) 	if (IS_ERR(object)) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 499) 		fscache_stat(&fscache_n_object_no_alloc);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 500) 		ret = PTR_ERR(object);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 501) 		goto error;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 502) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 503) 
f29507ce66701 (Kiran Kumar Modukuri  2018-06-21 13:31:44 -0700 504) 	ASSERTCMP(object->cookie, ==, cookie);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 505) 	fscache_stat(&fscache_n_object_alloc);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 506) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 507) 	object->debug_id = atomic_inc_return(&fscache_object_debug_id);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 508) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 509) 	_debug("ALLOC OBJ%x: %s {%lx}",
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 510) 	       object->debug_id, cookie->def->name, object->events);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 511) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 512) 	ret = fscache_alloc_object(cache, cookie->parent);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 513) 	if (ret < 0)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 514) 		goto error_put;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 515) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 516) 	/* only attach if we managed to allocate all we needed, otherwise
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 517) 	 * discard the object we just allocated and instead use the one
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 518) 	 * attached to the cookie */
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 519) 	if (fscache_attach_object(cookie, object) < 0) {
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 520) 		fscache_stat(&fscache_n_cop_put_object);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 521) 		cache->ops->put_object(object, fscache_obj_put_attach_fail);
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 522) 		fscache_stat_d(&fscache_n_cop_put_object);
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 523) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 524) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 525) 	_leave(" = 0");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 526) 	return 0;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 527) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 528) object_already_extant:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 529) 	ret = -ENOBUFS;
87021526300f1 (David Howells         2015-02-24 10:52:51 +0000 530) 	if (fscache_object_is_dying(object) ||
87021526300f1 (David Howells         2015-02-24 10:52:51 +0000 531) 	    fscache_cache_is_broken(object)) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 532) 		spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 533) 		goto error;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 534) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 535) 	spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 536) 	_leave(" = 0 [found]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 537) 	return 0;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 538) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 539) error_put:
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 540) 	fscache_stat(&fscache_n_cop_put_object);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 541) 	cache->ops->put_object(object, fscache_obj_put_alloc_fail);
52bd75fdb135d (David Howells         2009-11-19 18:11:08 +0000 542) 	fscache_stat_d(&fscache_n_cop_put_object);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 543) error:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 544) 	_leave(" = %d", ret);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 545) 	return ret;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 546) }
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 547) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 548) /*
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 549)  * attach a cache object to a cookie
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 550)  */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 551) static int fscache_attach_object(struct fscache_cookie *cookie,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 552) 				 struct fscache_object *object)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 553) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 554) 	struct fscache_object *p;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 555) 	struct fscache_cache *cache = object->cache;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 556) 	int ret;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 557) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 558) 	_enter("{%s},{OBJ%x}", cookie->def->name, object->debug_id);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 559) 
f29507ce66701 (Kiran Kumar Modukuri  2018-06-21 13:31:44 -0700 560) 	ASSERTCMP(object->cookie, ==, cookie);
f29507ce66701 (Kiran Kumar Modukuri  2018-06-21 13:31:44 -0700 561) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 562) 	spin_lock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 563) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 564) 	/* there may be multiple initial creations of this object, but we only
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 565) 	 * want one */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 566) 	ret = -EEXIST;
b67bfe0d42cac (Sasha Levin           2013-02-27 17:06:00 -0800 567) 	hlist_for_each_entry(p, &cookie->backing_objects, cookie_link) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 568) 		if (p->cache == object->cache) {
493f7bc11457b (David Howells         2013-05-10 19:50:26 +0100 569) 			if (fscache_object_is_dying(p))
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 570) 				ret = -ENOBUFS;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 571) 			goto cant_attach_object;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 572) 		}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 573) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 574) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 575) 	/* pin the parent object */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 576) 	spin_lock_nested(&cookie->parent->lock, 1);
b67bfe0d42cac (Sasha Levin           2013-02-27 17:06:00 -0800 577) 	hlist_for_each_entry(p, &cookie->parent->backing_objects,
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 578) 			     cookie_link) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 579) 		if (p->cache == object->cache) {
493f7bc11457b (David Howells         2013-05-10 19:50:26 +0100 580) 			if (fscache_object_is_dying(p)) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 581) 				ret = -ENOBUFS;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 582) 				spin_unlock(&cookie->parent->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 583) 				goto cant_attach_object;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 584) 			}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 585) 			object->parent = p;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 586) 			spin_lock(&p->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 587) 			p->n_children++;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 588) 			spin_unlock(&p->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 589) 			break;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 590) 		}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 591) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 592) 	spin_unlock(&cookie->parent->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 593) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 594) 	/* attach to the cache's object list */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 595) 	if (list_empty(&object->cache_link)) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 596) 		spin_lock(&cache->object_list_lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 597) 		list_add(&object->cache_link, &cache->object_list);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 598) 		spin_unlock(&cache->object_list_lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 599) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 600) 
f29507ce66701 (Kiran Kumar Modukuri  2018-06-21 13:31:44 -0700 601) 	/* Attach to the cookie.  The object already has a ref on it. */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 602) 	hlist_add_head(&object->cookie_link, &cookie->backing_objects);
4fbf4291aa159 (David Howells         2009-11-19 18:11:04 +0000 603) 
4fbf4291aa159 (David Howells         2009-11-19 18:11:04 +0000 604) 	fscache_objlist_add(object);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 605) 	ret = 0;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 606) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 607) cant_attach_object:
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 608) 	spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 609) 	_leave(" = %d", ret);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 610) 	return ret;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 611) }
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 612) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 613) /*
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 614)  * Invalidate an object.  Callable with spinlocks held.
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 615)  */
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 616) void __fscache_invalidate(struct fscache_cookie *cookie)
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 617) {
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 618) 	struct fscache_object *object;
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 619) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 620) 	_enter("{%s}", cookie->def->name);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 621) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 622) 	fscache_stat(&fscache_n_invalidates);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 623) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 624) 	/* Only permit invalidation of data files.  Invalidating an index will
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 625) 	 * require the caller to release all its attachments to the tree rooted
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 626) 	 * there, and if it's doing that, it may as well just retire the
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 627) 	 * cookie.
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 628) 	 */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 629) 	ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 630) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 631) 	/* If there's an object, we tell the object state machine to handle the
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 632) 	 * invalidation on our behalf, otherwise there's nothing to do.
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 633) 	 */
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 634) 	if (!hlist_empty(&cookie->backing_objects)) {
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 635) 		spin_lock(&cookie->lock);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 636) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 637) 		if (fscache_cookie_enabled(cookie) &&
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 638) 		    !hlist_empty(&cookie->backing_objects) &&
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 639) 		    !test_and_set_bit(FSCACHE_COOKIE_INVALIDATING,
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 640) 				      &cookie->flags)) {
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 641) 			object = hlist_entry(cookie->backing_objects.first,
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 642) 					     struct fscache_object,
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 643) 					     cookie_link);
493f7bc11457b (David Howells         2013-05-10 19:50:26 +0100 644) 			if (fscache_object_is_live(object))
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 645) 				fscache_raise_event(
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 646) 					object, FSCACHE_OBJECT_EV_INVALIDATE);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 647) 		}
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 648) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 649) 		spin_unlock(&cookie->lock);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 650) 	}
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 651) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 652) 	_leave("");
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 653) }
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 654) EXPORT_SYMBOL(__fscache_invalidate);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 655) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 656) /*
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 657)  * Wait for object invalidation to complete.
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 658)  */
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 659) void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 660) {
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 661) 	_enter("%p", cookie);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 662) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 663) 	wait_on_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING,
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 664) 		    TASK_UNINTERRUPTIBLE);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 665) 
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 666) 	_leave("");
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 667) }
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 668) EXPORT_SYMBOL(__fscache_wait_on_invalidate);
ef778e7ae67cd (David Howells         2012-12-20 21:52:36 +0000 669) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 670) /*
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 671)  * update the index entries backing a cookie
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 672)  */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 673) void __fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 674) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 675) 	struct fscache_object *object;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 676) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 677) 	fscache_stat(&fscache_n_updates);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 678) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 679) 	if (!cookie) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 680) 		fscache_stat(&fscache_n_updates_null);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 681) 		_leave(" [no cookie]");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 682) 		return;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 683) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 684) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 685) 	_enter("{%s}", cookie->def->name);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 686) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 687) 	spin_lock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 688) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 689) 	fscache_update_aux(cookie, aux_data);
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 690) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 691) 	if (fscache_cookie_enabled(cookie)) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 692) 		/* update the index entry on disk in each cache backing this
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 693) 		 * cookie.
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 694) 		 */
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 695) 		hlist_for_each_entry(object,
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 696) 				     &cookie->backing_objects, cookie_link) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 697) 			fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 698) 		}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 699) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 700) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 701) 	spin_unlock(&cookie->lock);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 702) 	_leave("");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 703) }
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 704) EXPORT_SYMBOL(__fscache_update_cookie);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 705) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 706) /*
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 707)  * Disable a cookie to stop it from accepting new requests from the netfs.
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 708)  */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 709) void __fscache_disable_cookie(struct fscache_cookie *cookie,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 710) 			      const void *aux_data,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 711) 			      bool invalidate)
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 712) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 713) 	struct fscache_object *object;
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 714) 	bool awaken = false;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 715) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 716) 	_enter("%p,%u", cookie, invalidate);
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 717) 
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 718) 	trace_fscache_disable(cookie);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 719) 
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 720) 	ASSERTCMP(atomic_read(&cookie->n_active), >, 0);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 721) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 722) 	if (atomic_read(&cookie->n_children) != 0) {
36dfd116edd48 (Fabian Frederick      2014-06-04 16:05:38 -0700 723) 		pr_err("Cookie '%s' still has children\n",
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 724) 		       cookie->def->name);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 725) 		BUG();
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 726) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 727) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 728) 	wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
743162013d40c (NeilBrown             2014-07-07 15:16:04 +1000 729) 			 TASK_UNINTERRUPTIBLE);
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 730) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 731) 	fscache_update_aux(cookie, aux_data);
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 732) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 733) 	if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 734) 		goto out_unlock_enable;
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 735) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 736) 	/* If the cookie is being invalidated, wait for that to complete first
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 737) 	 * so that we can reuse the flag.
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 738) 	 */
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 739) 	__fscache_wait_on_invalidate(cookie);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 740) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 741) 	/* Dispose of the backing objects */
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 742) 	set_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 743) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 744) 	spin_lock(&cookie->lock);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 745) 	if (!hlist_empty(&cookie->backing_objects)) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 746) 		hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 747) 			if (invalidate)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 748) 				set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
6bdded59c8933 (David Howells         2017-01-18 14:29:25 +0000 749) 			clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 750) 			fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 751) 		}
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 752) 	} else {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 753) 		if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 754) 			awaken = true;
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 755) 	}
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 756) 	spin_unlock(&cookie->lock);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 757) 	if (awaken)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 758) 		wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 759) 
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 760) 	/* Wait for cessation of activity requiring access to the netfs (when
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 761) 	 * n_active reaches 0).  This makes sure outstanding reads and writes
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 762) 	 * have completed.
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 763) 	 */
dc5d4afbb0bf7 (Peter Zijlstra        2018-03-15 11:43:43 +0100 764) 	if (!atomic_dec_and_test(&cookie->n_active)) {
dc5d4afbb0bf7 (Peter Zijlstra        2018-03-15 11:43:43 +0100 765) 		wait_var_event(&cookie->n_active,
dc5d4afbb0bf7 (Peter Zijlstra        2018-03-15 11:43:43 +0100 766) 			       !atomic_read(&cookie->n_active));
dc5d4afbb0bf7 (Peter Zijlstra        2018-03-15 11:43:43 +0100 767) 	}
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 768) 
6bdded59c8933 (David Howells         2017-01-18 14:29:25 +0000 769) 	/* Make sure any pending writes are cancelled. */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 770) 	if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX)
6bdded59c8933 (David Howells         2017-01-18 14:29:25 +0000 771) 		fscache_invalidate_writes(cookie);
6bdded59c8933 (David Howells         2017-01-18 14:29:25 +0000 772) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 773) 	/* Reset the cookie state if it wasn't relinquished */
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 774) 	if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 775) 		atomic_inc(&cookie->n_active);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 776) 		set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 777) 	}
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 778) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 779) out_unlock_enable:
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 780) 	clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 781) 	wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 782) 	_leave("");
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 783) }
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 784) EXPORT_SYMBOL(__fscache_disable_cookie);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 785) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 786) /*
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 787)  * release a cookie back to the cache
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 788)  * - the object will be marked as recyclable on disk if retire is true
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 789)  * - all dependents of this cookie must have already been unregistered
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 790)  *   (indices/files/pages)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 791)  */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 792) void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 793) 				 const void *aux_data,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 794) 				 bool retire)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 795) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 796) 	fscache_stat(&fscache_n_relinquishes);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 797) 	if (retire)
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 798) 		fscache_stat(&fscache_n_relinquishes_retire);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 799) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 800) 	if (!cookie) {
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 801) 		fscache_stat(&fscache_n_relinquishes_null);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 802) 		_leave(" [no cookie]");
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 803) 		return;
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 804) 	}
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 805) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 806) 	_enter("%p{%s,%p,%d},%d",
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 807) 	       cookie, cookie->def->name, cookie->netfs_data,
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 808) 	       atomic_read(&cookie->n_active), retire);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 809) 
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 810) 	trace_fscache_relinquish(cookie, retire);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 811) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 812) 	/* No further netfs-accessing operations on this cookie permitted */
d0fb31ecda2c3 (David Howells         2018-04-04 13:41:26 +0100 813) 	if (test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags))
d0fb31ecda2c3 (David Howells         2018-04-04 13:41:26 +0100 814) 		BUG();
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 815) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 816) 	__fscache_disable_cookie(cookie, aux_data, retire);
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 817) 
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 818) 	/* Clear pointers back to the netfs */
7e311a207d596 (David Howells         2009-11-19 18:11:11 +0000 819) 	cookie->netfs_data	= NULL;
7e311a207d596 (David Howells         2009-11-19 18:11:11 +0000 820) 	cookie->def		= NULL;
e5a955419642e (Matthew Wilcox        2018-04-10 16:36:48 -0700 821) 	BUG_ON(!radix_tree_empty(&cookie->stores));
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 822) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 823) 	if (cookie->parent) {
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 824) 		ASSERTCMP(atomic_read(&cookie->parent->usage), >, 0);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 825) 		ASSERTCMP(atomic_read(&cookie->parent->n_children), >, 0);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 826) 		atomic_dec(&cookie->parent->n_children);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 827) 	}
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 828) 
1362729b169b7 (David Howells         2013-05-10 19:50:26 +0100 829) 	/* Dispose of the netfs's link to the cookie */
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 830) 	ASSERTCMP(atomic_read(&cookie->usage), >, 0);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 831) 	fscache_cookie_put(cookie, fscache_cookie_put_relinquish);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 832) 
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 833) 	_leave("");
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 834) }
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 835) EXPORT_SYMBOL(__fscache_relinquish_cookie);
ccc4fc3d11e91 (David Howells         2009-04-03 16:42:38 +0100 836) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 837) /*
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 838)  * Remove a cookie from the hash table.
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 839)  */
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 840) static void fscache_unhash_cookie(struct fscache_cookie *cookie)
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 841) {
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 842) 	struct hlist_bl_head *h;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 843) 	unsigned int bucket;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 844) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 845) 	bucket = cookie->key_hash & (ARRAY_SIZE(fscache_cookie_hash) - 1);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 846) 	h = &fscache_cookie_hash[bucket];
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 847) 
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 848) 	hlist_bl_lock(h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 849) 	hlist_bl_del(&cookie->hash_link);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 850) 	hlist_bl_unlock(h);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 851) }
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 852) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 853) /*
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 854)  * Drop a reference to a cookie.
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 855)  */
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 856) void fscache_cookie_put(struct fscache_cookie *cookie,
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 857) 			enum fscache_cookie_trace where)
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 858) {
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 859) 	struct fscache_cookie *parent;
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 860) 	int usage;
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 861) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 862) 	_enter("%p", cookie);
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 863) 
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 864) 	do {
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 865) 		usage = atomic_dec_return(&cookie->usage);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 866) 		trace_fscache_cookie(cookie, where, usage);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 867) 
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 868) 		if (usage > 0)
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 869) 			return;
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 870) 		BUG_ON(usage < 0);
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 871) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 872) 		parent = cookie->parent;
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 873) 		fscache_unhash_cookie(cookie);
ec0328e46d6e5 (David Howells         2018-04-04 13:41:28 +0100 874) 		fscache_free_cookie(cookie);
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 875) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 876) 		cookie = parent;
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 877) 		where = fscache_cookie_put_parent;
a18feb55769b7 (David Howells         2018-04-04 13:41:27 +0100 878) 	} while (cookie);
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 879) 
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 880) 	_leave("");
955d00917f0c0 (David Howells         2009-04-03 16:42:38 +0100 881) }
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 882) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 883) /*
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 884)  * check the consistency between the netfs inode and the backing cache
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 885)  *
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 886)  * NOTE: it only serves no-index type
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 887)  */
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 888) int __fscache_check_consistency(struct fscache_cookie *cookie,
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 889) 				const void *aux_data)
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 890) {
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 891) 	struct fscache_operation *op;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 892) 	struct fscache_object *object;
8fb883f3e3006 (David Howells         2013-09-21 00:09:31 +0100 893) 	bool wake_cookie = false;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 894) 	int ret;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 895) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 896) 	_enter("%p,", cookie);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 897) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 898) 	ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 899) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 900) 	if (fscache_wait_for_deferred_lookup(cookie) < 0)
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 901) 		return -ERESTARTSYS;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 902) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 903) 	if (hlist_empty(&cookie->backing_objects))
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 904) 		return 0;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 905) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 906) 	op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 907) 	if (!op)
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 908) 		return -ENOMEM;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 909) 
08c2e3d087840 (David Howells         2018-04-04 13:41:27 +0100 910) 	fscache_operation_init(cookie, op, NULL, NULL, NULL);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 911) 	op->flags = FSCACHE_OP_MYTHREAD |
9c89d62948c47 (Milosz Tanski         2013-09-09 14:28:57 -0400 912) 		(1 << FSCACHE_OP_WAITING) |
9c89d62948c47 (Milosz Tanski         2013-09-09 14:28:57 -0400 913) 		(1 << FSCACHE_OP_UNUSE_COOKIE);
08c2e3d087840 (David Howells         2018-04-04 13:41:27 +0100 914) 	trace_fscache_page_op(cookie, NULL, op, fscache_page_op_check_consistency);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 915) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 916) 	spin_lock(&cookie->lock);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 917) 
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 918) 	fscache_update_aux(cookie, aux_data);
402cb8dda949d (David Howells         2018-04-04 13:41:28 +0100 919) 
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 920) 	if (!fscache_cookie_enabled(cookie) ||
94d30ae90a00c (David Howells         2013-09-21 00:09:31 +0100 921) 	    hlist_empty(&cookie->backing_objects))
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 922) 		goto inconsistent;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 923) 	object = hlist_entry(cookie->backing_objects.first,
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 924) 			     struct fscache_object, cookie_link);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 925) 	if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 926) 		goto inconsistent;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 927) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 928) 	op->debug_id = atomic_inc_return(&fscache_op_debug_id);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 929) 
8fb883f3e3006 (David Howells         2013-09-21 00:09:31 +0100 930) 	__fscache_use_cookie(cookie);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 931) 	if (fscache_submit_op(object, op) < 0)
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 932) 		goto submit_failed;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 933) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 934) 	/* the work queue now carries its own ref on the object */
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 935) 	spin_unlock(&cookie->lock);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 936) 
d3b97ca4a99e4 (David Howells         2015-02-24 10:05:29 +0000 937) 	ret = fscache_wait_for_operation_activation(object, op, NULL, NULL);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 938) 	if (ret == 0) {
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 939) 		/* ask the cache to honour the operation */
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 940) 		ret = object->cache->ops->check_consistency(op);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 941) 		fscache_op_complete(op, false);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 942) 	} else if (ret == -ENOBUFS) {
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 943) 		ret = 0;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 944) 	}
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 945) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 946) 	fscache_put_operation(op);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 947) 	_leave(" = %d", ret);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 948) 	return ret;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 949) 
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 950) submit_failed:
8fb883f3e3006 (David Howells         2013-09-21 00:09:31 +0100 951) 	wake_cookie = __fscache_unuse_cookie(cookie);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 952) inconsistent:
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 953) 	spin_unlock(&cookie->lock);
8fb883f3e3006 (David Howells         2013-09-21 00:09:31 +0100 954) 	if (wake_cookie)
8fb883f3e3006 (David Howells         2013-09-21 00:09:31 +0100 955) 		__fscache_wake_unused_cookie(cookie);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 956) 	kfree(op);
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 957) 	_leave(" = -ESTALE");
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 958) 	return -ESTALE;
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 959) }
da9803bc8812f (David Howells         2013-08-21 17:29:38 -0400 960) EXPORT_SYMBOL(__fscache_check_consistency);