LCOV - code coverage report
Current view: top level - fs/fscache - cookie.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 36 292 12.3 %
Date: 2020-09-30 20:25:40 Functions: 3 19 15.8 %
Branches: 7 237 3.0 %

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

Generated by: LCOV version 1.14