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