LCOV - code coverage report
Current view: top level - fs/jffs2 - nodelist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 270 0.0 %
Date: 2014-02-18 Functions: 0 19 0.0 %
Branches: 0 196 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * JFFS2 -- Journalling Flash File System, Version 2.
       3                 :            :  *
       4                 :            :  * Copyright © 2001-2007 Red Hat, Inc.
       5                 :            :  *
       6                 :            :  * Created by David Woodhouse <dwmw2@infradead.org>
       7                 :            :  *
       8                 :            :  * For licensing information, see the file 'LICENCE' in this directory.
       9                 :            :  *
      10                 :            :  */
      11                 :            : 
      12                 :            : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      13                 :            : 
      14                 :            : #include <linux/kernel.h>
      15                 :            : #include <linux/sched.h>
      16                 :            : #include <linux/fs.h>
      17                 :            : #include <linux/mtd/mtd.h>
      18                 :            : #include <linux/rbtree.h>
      19                 :            : #include <linux/crc32.h>
      20                 :            : #include <linux/pagemap.h>
      21                 :            : #include "nodelist.h"
      22                 :            : 
      23                 :            : static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,
      24                 :            :                                      struct jffs2_node_frag *this);
      25                 :            : 
      26                 :          0 : void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list)
      27                 :            : {
      28                 :            :         struct jffs2_full_dirent **prev = list;
      29                 :            : 
      30                 :            :         dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino);
      31                 :            : 
      32 [ #  # ][ #  # ]:          0 :         while ((*prev) && (*prev)->nhash <= new->nhash) {
      33 [ #  # ][ #  # ]:          0 :                 if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) {
      34                 :            :                         /* Duplicate. Free one */
      35         [ #  # ]:          0 :                         if (new->version < (*prev)->version) {
      36                 :            :                                 dbg_dentlist("Eep! Marking new dirent node obsolete, old is \"%s\", ino #%u\n",
      37                 :            :                                         (*prev)->name, (*prev)->ino);
      38                 :          0 :                                 jffs2_mark_node_obsolete(c, new->raw);
      39                 :          0 :                                 jffs2_free_full_dirent(new);
      40                 :            :                         } else {
      41                 :            :                                 dbg_dentlist("marking old dirent \"%s\", ino #%u obsolete\n",
      42                 :            :                                         (*prev)->name, (*prev)->ino);
      43                 :          0 :                                 new->next = (*prev)->next;
      44                 :            :                                 /* It may have been a 'placeholder' deletion dirent, 
      45                 :            :                                    if jffs2_can_mark_obsolete() (see jffs2_do_unlink()) */
      46         [ #  # ]:          0 :                                 if ((*prev)->raw)
      47                 :          0 :                                         jffs2_mark_node_obsolete(c, ((*prev)->raw));
      48                 :          0 :                                 jffs2_free_full_dirent(*prev);
      49                 :          0 :                                 *prev = new;
      50                 :            :                         }
      51                 :          0 :                         return;
      52                 :            :                 }
      53                 :          0 :                 prev = &((*prev)->next);
      54                 :            :         }
      55                 :          0 :         new->next = *prev;
      56                 :          0 :         *prev = new;
      57                 :            : }
      58                 :            : 
      59                 :          0 : uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
      60                 :            : {
      61                 :          0 :         struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
      62                 :            : 
      63                 :            :         dbg_fragtree("truncating fragtree to 0x%08x bytes\n", size);
      64                 :            : 
      65                 :            :         /* We know frag->ofs <= size. That's what lookup does for us */
      66 [ #  # ][ #  # ]:          0 :         if (frag && frag->ofs != size) {
      67         [ #  # ]:          0 :                 if (frag->ofs+frag->size > size) {
      68                 :          0 :                         frag->size = size - frag->ofs;
      69                 :            :                 }
      70                 :          0 :                 frag = frag_next(frag);
      71                 :            :         }
      72 [ #  # ][ #  # ]:          0 :         while (frag && frag->ofs >= size) {
      73                 :          0 :                 struct jffs2_node_frag *next = frag_next(frag);
      74                 :            : 
      75                 :          0 :                 frag_erase(frag, list);
      76                 :          0 :                 jffs2_obsolete_node_frag(c, frag);
      77                 :            :                 frag = next;
      78                 :            :         }
      79                 :            : 
      80         [ #  # ]:          0 :         if (size == 0)
      81                 :            :                 return 0;
      82                 :            : 
      83                 :            :         frag = frag_last(list);
      84                 :            : 
      85                 :            :         /* Sanity check for truncation to longer than we started with... */
      86         [ #  # ]:          0 :         if (!frag)
      87                 :            :                 return 0;
      88         [ #  # ]:          0 :         if (frag->ofs + frag->size < size)
      89                 :            :                 return frag->ofs + frag->size;
      90                 :            : 
      91                 :            :         /* If the last fragment starts at the RAM page boundary, it is
      92                 :            :          * REF_PRISTINE irrespective of its size. */
      93 [ #  # ][ #  # ]:          0 :         if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) {
      94                 :            :                 dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n",
      95                 :            :                         frag->ofs, frag->ofs + frag->size);
      96                 :          0 :                 frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE;
      97                 :            :         }
      98                 :          0 :         return size;
      99                 :            : }
     100                 :            : 
     101                 :          0 : static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,
     102                 :            :                                      struct jffs2_node_frag *this)
     103                 :            : {
     104         [ #  # ]:          0 :         if (this->node) {
     105                 :          0 :                 this->node->frags--;
     106         [ #  # ]:          0 :                 if (!this->node->frags) {
     107                 :            :                         /* The node has no valid frags left. It's totally obsoleted */
     108                 :            :                         dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",
     109                 :            :                                 ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size);
     110                 :          0 :                         jffs2_mark_node_obsolete(c, this->node->raw);
     111                 :          0 :                         jffs2_free_full_dnode(this->node);
     112                 :            :                 } else {
     113                 :            :                         dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n",
     114                 :            :                                 ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags);
     115                 :          0 :                         mark_ref_normal(this->node->raw);
     116                 :            :                 }
     117                 :            : 
     118                 :            :         }
     119                 :          0 :         jffs2_free_node_frag(this);
     120                 :          0 : }
     121                 :            : 
     122                 :          0 : static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base)
     123                 :            : {
     124                 :          0 :         struct rb_node *parent = &base->rb;
     125                 :            :         struct rb_node **link = &parent;
     126                 :            : 
     127                 :            :         dbg_fragtree2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size);
     128                 :            : 
     129         [ #  # ]:          0 :         while (*link) {
     130                 :          0 :                 parent = *link;
     131                 :            :                 base = rb_entry(parent, struct jffs2_node_frag, rb);
     132                 :            : 
     133         [ #  # ]:          0 :                 if (newfrag->ofs > base->ofs)
     134                 :          0 :                         link = &base->rb.rb_right;
     135         [ #  # ]:          0 :                 else if (newfrag->ofs < base->ofs)
     136                 :          0 :                         link = &base->rb.rb_left;
     137                 :            :                 else {
     138                 :          0 :                         JFFS2_ERROR("duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base);
     139                 :          0 :                         BUG();
     140                 :            :                 }
     141                 :            :         }
     142                 :            : 
     143                 :          0 :         rb_link_node(&newfrag->rb, &base->rb, link);
     144                 :          0 : }
     145                 :            : 
     146                 :            : /*
     147                 :            :  * Allocate and initializes a new fragment.
     148                 :            :  */
     149                 :          0 : static struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size)
     150                 :            : {
     151                 :            :         struct jffs2_node_frag *newfrag;
     152                 :            : 
     153                 :          0 :         newfrag = jffs2_alloc_node_frag();
     154         [ #  # ]:          0 :         if (likely(newfrag)) {
     155                 :          0 :                 newfrag->ofs = ofs;
     156                 :          0 :                 newfrag->size = size;
     157                 :          0 :                 newfrag->node = fn;
     158                 :            :         } else {
     159                 :          0 :                 JFFS2_ERROR("cannot allocate a jffs2_node_frag object\n");
     160                 :            :         }
     161                 :            : 
     162                 :          0 :         return newfrag;
     163                 :            : }
     164                 :            : 
     165                 :            : /*
     166                 :            :  * Called when there is no overlapping fragment exist. Inserts a hole before the new
     167                 :            :  * fragment and inserts the new fragment to the fragtree.
     168                 :            :  */
     169                 :          0 : static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root,
     170                 :            :                                struct jffs2_node_frag *newfrag,
     171                 :            :                                struct jffs2_node_frag *this, uint32_t lastend)
     172                 :            : {
     173         [ #  # ]:          0 :         if (lastend < newfrag->node->ofs) {
     174                 :            :                 /* put a hole in before the new fragment */
     175                 :            :                 struct jffs2_node_frag *holefrag;
     176                 :            : 
     177                 :          0 :                 holefrag= new_fragment(NULL, lastend, newfrag->node->ofs - lastend);
     178         [ #  # ]:          0 :                 if (unlikely(!holefrag)) {
     179                 :          0 :                         jffs2_free_node_frag(newfrag);
     180                 :            :                         return -ENOMEM;
     181                 :            :                 }
     182                 :            : 
     183         [ #  # ]:          0 :                 if (this) {
     184                 :            :                         /* By definition, the 'this' node has no right-hand child,
     185                 :            :                            because there are no frags with offset greater than it.
     186                 :            :                            So that's where we want to put the hole */
     187                 :            :                         dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n",
     188                 :            :                                 holefrag->ofs, holefrag->ofs + holefrag->size);
     189                 :          0 :                         rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right);
     190                 :            :                 } else {
     191                 :            :                         dbg_fragtree2("Add hole frag %#04x-%#04x to the root of the tree.\n",
     192                 :            :                                 holefrag->ofs, holefrag->ofs + holefrag->size);
     193                 :          0 :                         rb_link_node(&holefrag->rb, NULL, &root->rb_node);
     194                 :            :                 }
     195                 :          0 :                 rb_insert_color(&holefrag->rb, root);
     196                 :            :                 this = holefrag;
     197                 :            :         }
     198                 :            : 
     199         [ #  # ]:          0 :         if (this) {
     200                 :            :                 /* By definition, the 'this' node has no right-hand child,
     201                 :            :                    because there are no frags with offset greater than it.
     202                 :            :                    So that's where we want to put new fragment */
     203                 :            :                 dbg_fragtree2("add the new node at the right\n");
     204                 :          0 :                 rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);
     205                 :            :         } else {
     206                 :            :                 dbg_fragtree2("insert the new node at the root of the tree\n");
     207                 :          0 :                 rb_link_node(&newfrag->rb, NULL, &root->rb_node);
     208                 :            :         }
     209                 :          0 :         rb_insert_color(&newfrag->rb, root);
     210                 :            : 
     211                 :            :         return 0;
     212                 :            : }
     213                 :            : 
     214                 :            : /* Doesn't set inode->i_size */
     215                 :          0 : static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *root, struct jffs2_node_frag *newfrag)
     216                 :            : {
     217                 :            :         struct jffs2_node_frag *this;
     218                 :            :         uint32_t lastend;
     219                 :            : 
     220                 :            :         /* Skip all the nodes which are completed before this one starts */
     221                 :          0 :         this = jffs2_lookup_node_frag(root, newfrag->node->ofs);
     222                 :            : 
     223         [ #  # ]:          0 :         if (this) {
     224                 :            :                 dbg_fragtree2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
     225                 :            :                           this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this);
     226                 :          0 :                 lastend = this->ofs + this->size;
     227                 :            :         } else {
     228                 :            :                 dbg_fragtree2("lookup gave no frag\n");
     229                 :            :                 lastend = 0;
     230                 :            :         }
     231                 :            : 
     232                 :            :         /* See if we ran off the end of the fragtree */
     233         [ #  # ]:          0 :         if (lastend <= newfrag->ofs) {
     234                 :            :                 /* We did */
     235                 :            : 
     236                 :            :                 /* Check if 'this' node was on the same page as the new node.
     237                 :            :                    If so, both 'this' and the new node get marked REF_NORMAL so
     238                 :            :                    the GC can take a look.
     239                 :            :                 */
     240 [ #  # ][ #  # ]:          0 :                 if (lastend && (lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) {
     241         [ #  # ]:          0 :                         if (this->node)
     242                 :          0 :                                 mark_ref_normal(this->node->raw);
     243                 :          0 :                         mark_ref_normal(newfrag->node->raw);
     244                 :            :                 }
     245                 :            : 
     246                 :          0 :                 return no_overlapping_node(c, root, newfrag, this, lastend);
     247                 :            :         }
     248                 :            : 
     249                 :            :         if (this->node)
     250                 :            :                 dbg_fragtree2("dealing with frag %u-%u, phys %#08x(%d).\n",
     251                 :            :                 this->ofs, this->ofs + this->size,
     252                 :            :                 ref_offset(this->node->raw), ref_flags(this->node->raw));
     253                 :            :         else
     254                 :            :                 dbg_fragtree2("dealing with hole frag %u-%u.\n",
     255                 :            :                 this->ofs, this->ofs + this->size);
     256                 :            : 
     257                 :            :         /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes,
     258                 :            :          * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs
     259                 :            :          */
     260         [ #  # ]:          0 :         if (newfrag->ofs > this->ofs) {
     261                 :            :                 /* This node isn't completely obsoleted. The start of it remains valid */
     262                 :            : 
     263                 :            :                 /* Mark the new node and the partially covered node REF_NORMAL -- let
     264                 :            :                    the GC take a look at them */
     265                 :          0 :                 mark_ref_normal(newfrag->node->raw);
     266         [ #  # ]:          0 :                 if (this->node)
     267                 :          0 :                         mark_ref_normal(this->node->raw);
     268                 :            : 
     269         [ #  # ]:          0 :                 if (this->ofs + this->size > newfrag->ofs + newfrag->size) {
     270                 :            :                         /* The new node splits 'this' frag into two */
     271                 :            :                         struct jffs2_node_frag *newfrag2;
     272                 :            : 
     273                 :            :                         if (this->node)
     274                 :            :                                 dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n",
     275                 :            :                                         this->ofs, this->ofs+this->size, ref_offset(this->node->raw));
     276                 :            :                         else
     277                 :            :                                 dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n",
     278                 :            :                                         this->ofs, this->ofs+this->size);
     279                 :            : 
     280                 :            :                         /* New second frag pointing to this's node */
     281                 :          0 :                         newfrag2 = new_fragment(this->node, newfrag->ofs + newfrag->size,
     282                 :          0 :                                                 this->ofs + this->size - newfrag->ofs - newfrag->size);
     283         [ #  # ]:          0 :                         if (unlikely(!newfrag2))
     284                 :            :                                 return -ENOMEM;
     285         [ #  # ]:          0 :                         if (this->node)
     286                 :          0 :                                 this->node->frags++;
     287                 :            : 
     288                 :            :                         /* Adjust size of original 'this' */
     289                 :          0 :                         this->size = newfrag->ofs - this->ofs;
     290                 :            : 
     291                 :            :                         /* Now, we know there's no node with offset
     292                 :            :                            greater than this->ofs but smaller than
     293                 :            :                            newfrag2->ofs or newfrag->ofs, for obvious
     294                 :            :                            reasons. So we can do a tree insert from
     295                 :            :                            'this' to insert newfrag, and a tree insert
     296                 :            :                            from newfrag to insert newfrag2. */
     297                 :          0 :                         jffs2_fragtree_insert(newfrag, this);
     298                 :          0 :                         rb_insert_color(&newfrag->rb, root);
     299                 :            : 
     300                 :          0 :                         jffs2_fragtree_insert(newfrag2, newfrag);
     301                 :          0 :                         rb_insert_color(&newfrag2->rb, root);
     302                 :            : 
     303                 :          0 :                         return 0;
     304                 :            :                 }
     305                 :            :                 /* New node just reduces 'this' frag in size, doesn't split it */
     306                 :          0 :                 this->size = newfrag->ofs - this->ofs;
     307                 :            : 
     308                 :            :                 /* Again, we know it lives down here in the tree */
     309                 :          0 :                 jffs2_fragtree_insert(newfrag, this);
     310                 :          0 :                 rb_insert_color(&newfrag->rb, root);
     311                 :            :         } else {
     312                 :            :                 /* New frag starts at the same point as 'this' used to. Replace
     313                 :            :                    it in the tree without doing a delete and insertion */
     314                 :            :                 dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n",
     315                 :            :                           newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size);
     316                 :            : 
     317                 :          0 :                 rb_replace_node(&this->rb, &newfrag->rb, root);
     318                 :            : 
     319         [ #  # ]:          0 :                 if (newfrag->ofs + newfrag->size >= this->ofs+this->size) {
     320                 :            :                         dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size);
     321                 :          0 :                         jffs2_obsolete_node_frag(c, this);
     322                 :            :                 } else {
     323                 :          0 :                         this->ofs += newfrag->size;
     324                 :          0 :                         this->size -= newfrag->size;
     325                 :            : 
     326                 :          0 :                         jffs2_fragtree_insert(this, newfrag);
     327                 :          0 :                         rb_insert_color(&this->rb, root);
     328                 :          0 :                         return 0;
     329                 :            :                 }
     330                 :            :         }
     331                 :            :         /* OK, now we have newfrag added in the correct place in the tree, but
     332                 :            :            frag_next(newfrag) may be a fragment which is overlapped by it
     333                 :            :         */
     334 [ #  # ][ #  # ]:          0 :         while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
     335                 :            :                 /* 'this' frag is obsoleted completely. */
     336                 :            :                 dbg_fragtree2("obsoleting node frag %p (%x-%x) and removing from tree\n",
     337                 :            :                         this, this->ofs, this->ofs+this->size);
     338                 :          0 :                 rb_erase(&this->rb, root);
     339                 :          0 :                 jffs2_obsolete_node_frag(c, this);
     340                 :            :         }
     341                 :            :         /* Now we're pointing at the first frag which isn't totally obsoleted by
     342                 :            :            the new frag */
     343                 :            : 
     344 [ #  # ][ #  # ]:          0 :         if (!this || newfrag->ofs + newfrag->size == this->ofs)
     345                 :            :                 return 0;
     346                 :            : 
     347                 :            :         /* Still some overlap but we don't need to move it in the tree */
     348                 :          0 :         this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
     349                 :          0 :         this->ofs = newfrag->ofs + newfrag->size;
     350                 :            : 
     351                 :            :         /* And mark them REF_NORMAL so the GC takes a look at them */
     352         [ #  # ]:          0 :         if (this->node)
     353                 :          0 :                 mark_ref_normal(this->node->raw);
     354                 :          0 :         mark_ref_normal(newfrag->node->raw);
     355                 :            : 
     356                 :          0 :         return 0;
     357                 :            : }
     358                 :            : 
     359                 :            : /*
     360                 :            :  * Given an inode, probably with existing tree of fragments, add the new node
     361                 :            :  * to the fragment tree.
     362                 :            :  */
     363                 :          0 : int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
     364                 :            : {
     365                 :            :         int ret;
     366                 :            :         struct jffs2_node_frag *newfrag;
     367                 :            : 
     368         [ #  # ]:          0 :         if (unlikely(!fn->size))
     369                 :            :                 return 0;
     370                 :            : 
     371                 :          0 :         newfrag = new_fragment(fn, fn->ofs, fn->size);
     372         [ #  # ]:          0 :         if (unlikely(!newfrag))
     373                 :            :                 return -ENOMEM;
     374                 :          0 :         newfrag->node->frags = 1;
     375                 :            : 
     376                 :            :         dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n",
     377                 :            :                   fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag);
     378                 :            : 
     379                 :          0 :         ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag);
     380         [ #  # ]:          0 :         if (unlikely(ret))
     381                 :            :                 return ret;
     382                 :            : 
     383                 :            :         /* If we now share a page with other nodes, mark either previous
     384                 :            :            or next node REF_NORMAL, as appropriate.  */
     385         [ #  # ]:          0 :         if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) {
     386                 :          0 :                 struct jffs2_node_frag *prev = frag_prev(newfrag);
     387                 :            : 
     388                 :          0 :                 mark_ref_normal(fn->raw);
     389                 :            :                 /* If we don't start at zero there's _always_ a previous */
     390         [ #  # ]:          0 :                 if (prev->node)
     391                 :          0 :                         mark_ref_normal(prev->node->raw);
     392                 :            :         }
     393                 :            : 
     394         [ #  # ]:          0 :         if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) {
     395                 :          0 :                 struct jffs2_node_frag *next = frag_next(newfrag);
     396                 :            : 
     397         [ #  # ]:          0 :                 if (next) {
     398                 :          0 :                         mark_ref_normal(fn->raw);
     399         [ #  # ]:          0 :                         if (next->node)
     400                 :          0 :                                 mark_ref_normal(next->node->raw);
     401                 :            :                 }
     402                 :            :         }
     403                 :            :         jffs2_dbg_fragtree_paranoia_check_nolock(f);
     404                 :            : 
     405                 :            :         return 0;
     406                 :            : }
     407                 :            : 
     408                 :          0 : void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state)
     409                 :            : {
     410                 :            :         spin_lock(&c->inocache_lock);
     411                 :          0 :         ic->state = state;
     412                 :          0 :         wake_up(&c->inocache_wq);
     413                 :            :         spin_unlock(&c->inocache_lock);
     414                 :          0 : }
     415                 :            : 
     416                 :            : /* During mount, this needs no locking. During normal operation, its
     417                 :            :    callers want to do other stuff while still holding the inocache_lock.
     418                 :            :    Rather than introducing special case get_ino_cache functions or
     419                 :            :    callbacks, we just let the caller do the locking itself. */
     420                 :            : 
     421                 :          0 : struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino)
     422                 :            : {
     423                 :            :         struct jffs2_inode_cache *ret;
     424                 :            : 
     425                 :          0 :         ret = c->inocache_list[ino % c->inocache_hashsize];
     426 [ #  # ][ #  # ]:          0 :         while (ret && ret->ino < ino) {
     427                 :          0 :                 ret = ret->next;
     428                 :            :         }
     429                 :            : 
     430 [ #  # ][ #  # ]:          0 :         if (ret && ret->ino != ino)
     431                 :            :                 ret = NULL;
     432                 :            : 
     433                 :          0 :         return ret;
     434                 :            : }
     435                 :            : 
     436                 :          0 : void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new)
     437                 :            : {
     438                 :            :         struct jffs2_inode_cache **prev;
     439                 :            : 
     440                 :            :         spin_lock(&c->inocache_lock);
     441         [ #  # ]:          0 :         if (!new->ino)
     442                 :          0 :                 new->ino = ++c->highest_ino;
     443                 :            : 
     444                 :            :         dbg_inocache("add %p (ino #%u)\n", new, new->ino);
     445                 :            : 
     446                 :          0 :         prev = &c->inocache_list[new->ino % c->inocache_hashsize];
     447                 :            : 
     448 [ #  # ][ #  # ]:          0 :         while ((*prev) && (*prev)->ino < new->ino) {
     449                 :          0 :                 prev = &(*prev)->next;
     450                 :            :         }
     451                 :          0 :         new->next = *prev;
     452                 :          0 :         *prev = new;
     453                 :            : 
     454                 :            :         spin_unlock(&c->inocache_lock);
     455                 :          0 : }
     456                 :            : 
     457                 :          0 : void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
     458                 :            : {
     459                 :            :         struct jffs2_inode_cache **prev;
     460                 :            : 
     461                 :            : #ifdef CONFIG_JFFS2_FS_XATTR
     462         [ #  # ]:          0 :         BUG_ON(old->xref);
     463                 :            : #endif
     464                 :            :         dbg_inocache("del %p (ino #%u)\n", old, old->ino);
     465                 :            :         spin_lock(&c->inocache_lock);
     466                 :            : 
     467                 :          0 :         prev = &c->inocache_list[old->ino % c->inocache_hashsize];
     468                 :            : 
     469 [ #  # ][ #  # ]:          0 :         while ((*prev) && (*prev)->ino < old->ino) {
     470                 :          0 :                 prev = &(*prev)->next;
     471                 :            :         }
     472         [ #  # ]:          0 :         if ((*prev) == old) {
     473                 :          0 :                 *prev = old->next;
     474                 :            :         }
     475                 :            : 
     476                 :            :         /* Free it now unless it's in READING or CLEARING state, which
     477                 :            :            are the transitions upon read_inode() and clear_inode(). The
     478                 :            :            rest of the time we know nobody else is looking at it, and
     479                 :            :            if it's held by read_inode() or clear_inode() they'll free it
     480                 :            :            for themselves. */
     481         [ #  # ]:          0 :         if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)
     482                 :          0 :                 jffs2_free_inode_cache(old);
     483                 :            : 
     484                 :            :         spin_unlock(&c->inocache_lock);
     485                 :          0 : }
     486                 :            : 
     487                 :          0 : void jffs2_free_ino_caches(struct jffs2_sb_info *c)
     488                 :            : {
     489                 :            :         int i;
     490                 :            :         struct jffs2_inode_cache *this, *next;
     491                 :            : 
     492         [ #  # ]:          0 :         for (i=0; i < c->inocache_hashsize; i++) {
     493                 :          0 :                 this = c->inocache_list[i];
     494         [ #  # ]:          0 :                 while (this) {
     495                 :          0 :                         next = this->next;
     496                 :          0 :                         jffs2_xattr_free_inode(c, this);
     497                 :          0 :                         jffs2_free_inode_cache(this);
     498                 :            :                         this = next;
     499                 :            :                 }
     500                 :          0 :                 c->inocache_list[i] = NULL;
     501                 :            :         }
     502                 :          0 : }
     503                 :            : 
     504                 :          0 : void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
     505                 :            : {
     506                 :            :         int i;
     507                 :            :         struct jffs2_raw_node_ref *this, *next;
     508                 :            : 
     509         [ #  # ]:          0 :         for (i=0; i<c->nr_blocks; i++) {
     510                 :          0 :                 this = c->blocks[i].first_node;
     511         [ #  # ]:          0 :                 while (this) {
     512         [ #  # ]:          0 :                         if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
     513                 :          0 :                                 next = this[REFS_PER_BLOCK].next_in_ino;
     514                 :            :                         else
     515                 :            :                                 next = NULL;
     516                 :            : 
     517                 :          0 :                         jffs2_free_refblock(this);
     518                 :            :                         this = next;
     519                 :            :                 }
     520                 :          0 :                 c->blocks[i].first_node = c->blocks[i].last_node = NULL;
     521                 :            :         }
     522                 :          0 : }
     523                 :            : 
     524                 :          0 : struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset)
     525                 :            : {
     526                 :            :         /* The common case in lookup is that there will be a node
     527                 :            :            which precisely matches. So we go looking for that first */
     528                 :            :         struct rb_node *next;
     529                 :            :         struct jffs2_node_frag *prev = NULL;
     530                 :            :         struct jffs2_node_frag *frag = NULL;
     531                 :            : 
     532                 :            :         dbg_fragtree2("root %p, offset %d\n", fragtree, offset);
     533                 :            : 
     534                 :          0 :         next = fragtree->rb_node;
     535                 :            : 
     536         [ #  # ]:          0 :         while(next) {
     537                 :            :                 frag = rb_entry(next, struct jffs2_node_frag, rb);
     538                 :            : 
     539         [ #  # ]:          0 :                 if (frag->ofs + frag->size <= offset) {
     540                 :            :                         /* Remember the closest smaller match on the way down */
     541 [ #  # ][ #  # ]:          0 :                         if (!prev || frag->ofs > prev->ofs)
     542                 :            :                                 prev = frag;
     543                 :          0 :                         next = frag->rb.rb_right;
     544         [ #  # ]:          0 :                 } else if (frag->ofs > offset) {
     545                 :          0 :                         next = frag->rb.rb_left;
     546                 :            :                 } else {
     547                 :            :                         return frag;
     548                 :            :                 }
     549                 :            :         }
     550                 :            : 
     551                 :            :         /* Exact match not found. Go back up looking at each parent,
     552                 :            :            and return the closest smaller one */
     553                 :            : 
     554                 :            :         if (prev)
     555                 :            :                 dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n",
     556                 :            :                           prev->ofs, prev->ofs+prev->size);
     557                 :            :         else
     558                 :            :                 dbg_fragtree2("returning NULL, empty fragtree\n");
     559                 :            : 
     560                 :            :         return prev;
     561                 :            : }
     562                 :            : 
     563                 :            : /* Pass 'c' argument to indicate that nodes should be marked obsolete as
     564                 :            :    they're killed. */
     565                 :          0 : void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
     566                 :            : {
     567                 :            :         struct jffs2_node_frag *frag;
     568                 :            :         struct jffs2_node_frag *parent;
     569                 :            : 
     570         [ #  # ]:          0 :         if (!root->rb_node)
     571                 :          0 :                 return;
     572                 :            : 
     573                 :            :         dbg_fragtree("killing\n");
     574                 :            : 
     575                 :            :         frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb));
     576         [ #  # ]:          0 :         while(frag) {
     577         [ #  # ]:          0 :                 if (frag->rb.rb_left) {
     578                 :            :                         frag = frag_left(frag);
     579                 :          0 :                         continue;
     580                 :            :                 }
     581         [ #  # ]:          0 :                 if (frag->rb.rb_right) {
     582                 :            :                         frag = frag_right(frag);
     583                 :          0 :                         continue;
     584                 :            :                 }
     585                 :            : 
     586 [ #  # ][ #  # ]:          0 :                 if (frag->node && !(--frag->node->frags)) {
     587                 :            :                         /* Not a hole, and it's the final remaining frag
     588                 :            :                            of this node. Free the node */
     589         [ #  # ]:          0 :                         if (c)
     590                 :          0 :                                 jffs2_mark_node_obsolete(c, frag->node->raw);
     591                 :            : 
     592                 :          0 :                         jffs2_free_full_dnode(frag->node);
     593                 :            :                 }
     594                 :          0 :                 parent = frag_parent(frag);
     595         [ #  # ]:          0 :                 if (parent) {
     596         [ #  # ]:          0 :                         if (frag_left(parent) == frag)
     597                 :          0 :                                 parent->rb.rb_left = NULL;
     598                 :            :                         else
     599                 :          0 :                                 parent->rb.rb_right = NULL;
     600                 :            :                 }
     601                 :            : 
     602                 :          0 :                 jffs2_free_node_frag(frag);
     603                 :            :                 frag = parent;
     604                 :            : 
     605                 :          0 :                 cond_resched();
     606                 :            :         }
     607                 :            : }
     608                 :            : 
     609                 :          0 : struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
     610                 :            :                                                struct jffs2_eraseblock *jeb,
     611                 :            :                                                uint32_t ofs, uint32_t len,
     612                 :            :                                                struct jffs2_inode_cache *ic)
     613                 :            : {
     614                 :            :         struct jffs2_raw_node_ref *ref;
     615                 :            : 
     616         [ #  # ]:          0 :         BUG_ON(!jeb->allocated_refs);
     617                 :          0 :         jeb->allocated_refs--;
     618                 :            : 
     619                 :          0 :         ref = jeb->last_node;
     620                 :            : 
     621                 :            :         dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
     622                 :            :                     ref->next_in_ino);
     623                 :            : 
     624         [ #  # ]:          0 :         while (ref->flash_offset != REF_EMPTY_NODE) {
     625         [ #  # ]:          0 :                 if (ref->flash_offset == REF_LINK_NODE)
     626                 :          0 :                         ref = ref->next_in_ino;
     627                 :            :                 else
     628                 :          0 :                         ref++;
     629                 :            :         }
     630                 :            : 
     631                 :            :         dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref, 
     632                 :            :                     ref->flash_offset, ofs, ref->next_in_ino, len);
     633                 :            : 
     634                 :          0 :         ref->flash_offset = ofs;
     635                 :            : 
     636         [ #  # ]:          0 :         if (!jeb->first_node) {
     637                 :          0 :                 jeb->first_node = ref;
     638         [ #  # ]:          0 :                 BUG_ON(ref_offset(ref) != jeb->offset);
     639         [ #  # ]:          0 :         } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
     640                 :          0 :                 uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
     641                 :            : 
     642                 :          0 :                 JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
     643                 :            :                             ref, ref_offset(ref), ref_offset(ref)+len,
     644                 :            :                             ref_offset(jeb->last_node), 
     645                 :            :                             ref_offset(jeb->last_node)+last_len);
     646                 :          0 :                 BUG();
     647                 :            :         }
     648                 :          0 :         jeb->last_node = ref;
     649                 :            : 
     650         [ #  # ]:          0 :         if (ic) {
     651                 :          0 :                 ref->next_in_ino = ic->nodes;
     652                 :          0 :                 ic->nodes = ref;
     653                 :            :         } else {
     654                 :          0 :                 ref->next_in_ino = NULL;
     655                 :            :         }
     656                 :            : 
     657   [ #  #  #  # ]:          0 :         switch(ref_flags(ref)) {
     658                 :            :         case REF_UNCHECKED:
     659                 :          0 :                 c->unchecked_size += len;
     660                 :          0 :                 jeb->unchecked_size += len;
     661                 :          0 :                 break;
     662                 :            : 
     663                 :            :         case REF_NORMAL:
     664                 :            :         case REF_PRISTINE:
     665                 :          0 :                 c->used_size += len;
     666                 :          0 :                 jeb->used_size += len;
     667                 :          0 :                 break;
     668                 :            : 
     669                 :            :         case REF_OBSOLETE:
     670                 :          0 :                 c->dirty_size += len;
     671                 :          0 :                 jeb->dirty_size += len;
     672                 :          0 :                 break;
     673                 :            :         }
     674                 :          0 :         c->free_size -= len;
     675                 :          0 :         jeb->free_size -= len;
     676                 :            : 
     677                 :            : #ifdef TEST_TOTLEN
     678                 :            :         /* Set (and test) __totlen field... for now */
     679                 :            :         ref->__totlen = len;
     680                 :            :         ref_totlen(c, jeb, ref);
     681                 :            : #endif
     682                 :          0 :         return ref;
     683                 :            : }
     684                 :            : 
     685                 :            : /* No locking, no reservation of 'ref'. Do not use on a live file system */
     686                 :          0 : int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
     687                 :            :                            uint32_t size)
     688                 :            : {
     689         [ #  # ]:          0 :         if (!size)
     690                 :            :                 return 0;
     691         [ #  # ]:          0 :         if (unlikely(size > jeb->free_size)) {
     692                 :          0 :                 pr_crit("Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
     693                 :            :                         size, jeb->free_size, jeb->wasted_size);
     694                 :          0 :                 BUG();
     695                 :            :         }
     696                 :            :         /* REF_EMPTY_NODE is !obsolete, so that works OK */
     697 [ #  # ][ #  # ]:          0 :         if (jeb->last_node && ref_obsolete(jeb->last_node)) {
     698                 :            : #ifdef TEST_TOTLEN
     699                 :            :                 jeb->last_node->__totlen += size;
     700                 :            : #endif
     701                 :          0 :                 c->dirty_size += size;
     702                 :          0 :                 c->free_size -= size;
     703                 :          0 :                 jeb->dirty_size += size;
     704                 :          0 :                 jeb->free_size -= size;
     705                 :            :         } else {
     706                 :          0 :                 uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
     707                 :          0 :                 ofs |= REF_OBSOLETE;
     708                 :            : 
     709                 :          0 :                 jffs2_link_node_ref(c, jeb, ofs, size, NULL);
     710                 :            :         }
     711                 :            : 
     712                 :            :         return 0;
     713                 :            : }
     714                 :            : 
     715                 :            : /* Calculate totlen from surrounding nodes or eraseblock */
     716                 :            : static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
     717                 :            :                                     struct jffs2_eraseblock *jeb,
     718                 :            :                                     struct jffs2_raw_node_ref *ref)
     719                 :            : {
     720                 :            :         uint32_t ref_end;
     721                 :            :         struct jffs2_raw_node_ref *next_ref = ref_next(ref);
     722                 :            : 
     723         [ #  # ]:          0 :         if (next_ref)
     724                 :          0 :                 ref_end = ref_offset(next_ref);
     725                 :            :         else {
     726         [ #  # ]:          0 :                 if (!jeb)
     727                 :          0 :                         jeb = &c->blocks[ref->flash_offset / c->sector_size];
     728                 :            : 
     729                 :            :                 /* Last node in block. Use free_space */
     730         [ #  # ]:          0 :                 if (unlikely(ref != jeb->last_node)) {
     731         [ #  # ]:          0 :                         pr_crit("ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
     732                 :            :                                 ref, ref_offset(ref), jeb->last_node,
     733                 :            :                                 jeb->last_node ?
     734                 :            :                                 ref_offset(jeb->last_node) : 0);
     735                 :          0 :                         BUG();
     736                 :            :                 }
     737                 :          0 :                 ref_end = jeb->offset + c->sector_size - jeb->free_size;
     738                 :            :         }
     739                 :          0 :         return ref_end - ref_offset(ref);
     740                 :            : }
     741                 :            : 
     742                 :          0 : uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
     743                 :            :                             struct jffs2_raw_node_ref *ref)
     744                 :            : {
     745                 :            :         uint32_t ret;
     746                 :            : 
     747                 :            :         ret = __ref_totlen(c, jeb, ref);
     748                 :            : 
     749                 :            : #ifdef TEST_TOTLEN
     750                 :            :         if (unlikely(ret != ref->__totlen)) {
     751                 :            :                 if (!jeb)
     752                 :            :                         jeb = &c->blocks[ref->flash_offset / c->sector_size];
     753                 :            : 
     754                 :            :                 pr_crit("Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
     755                 :            :                         ref, ref_offset(ref), ref_offset(ref) + ref->__totlen,
     756                 :            :                         ret, ref->__totlen);
     757                 :            :                 if (ref_next(ref)) {
     758                 :            :                         pr_crit("next %p (0x%08x-0x%08x)\n",
     759                 :            :                                 ref_next(ref), ref_offset(ref_next(ref)),
     760                 :            :                                 ref_offset(ref_next(ref)) + ref->__totlen);
     761                 :            :                 } else 
     762                 :            :                         pr_crit("No next ref. jeb->last_node is %p\n",
     763                 :            :                                 jeb->last_node);
     764                 :            : 
     765                 :            :                 pr_crit("jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n",
     766                 :            :                         jeb->wasted_size, jeb->dirty_size, jeb->used_size,
     767                 :            :                         jeb->free_size);
     768                 :            : 
     769                 :            : #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
     770                 :            :                 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
     771                 :            : #endif
     772                 :            : 
     773                 :            :                 WARN_ON(1);
     774                 :            : 
     775                 :            :                 ret = ref->__totlen;
     776                 :            :         }
     777                 :            : #endif /* TEST_TOTLEN */
     778                 :          0 :         return ret;
     779                 :            : }

Generated by: LCOV version 1.9