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);