LCOV - code coverage report
Current view: top level - fs/jffs2 - nodemgmt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 208 0.0 %
Date: 2014-02-18 Functions: 0 10 0.0 %
Branches: 0 184 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/mtd/mtd.h>
      16                 :            : #include <linux/compiler.h>
      17                 :            : #include <linux/sched.h> /* For cond_resched() */
      18                 :            : #include "nodelist.h"
      19                 :            : #include "debug.h"
      20                 :            : 
      21                 :            : /*
      22                 :            :  * Check whether the user is allowed to write.
      23                 :            :  */
      24                 :          0 : static int jffs2_rp_can_write(struct jffs2_sb_info *c)
      25                 :            : {
      26                 :            :         uint32_t avail;
      27                 :            :         struct jffs2_mount_opts *opts = &c->mount_opts;
      28                 :            : 
      29                 :          0 :         avail = c->dirty_size + c->free_size + c->unchecked_size +
      30                 :          0 :                 c->erasing_size - c->resv_blocks_write * c->sector_size
      31                 :          0 :                 - c->nospc_dirty_size;
      32                 :            : 
      33                 :            :         if (avail < 2 * opts->rp_size)
      34                 :            :                 jffs2_dbg(1, "rpsize %u, dirty_size %u, free_size %u, "
      35                 :            :                           "erasing_size %u, unchecked_size %u, "
      36                 :            :                           "nr_erasing_blocks %u, avail %u, resrv %u\n",
      37                 :            :                           opts->rp_size, c->dirty_size, c->free_size,
      38                 :            :                           c->erasing_size, c->unchecked_size,
      39                 :            :                           c->nr_erasing_blocks, avail, c->nospc_dirty_size);
      40                 :            : 
      41         [ #  # ]:          0 :         if (avail > opts->rp_size)
      42                 :            :                 return 1;
      43                 :            : 
      44                 :            :         /* Always allow root */
      45         [ #  # ]:          0 :         if (capable(CAP_SYS_RESOURCE))
      46                 :            :                 return 1;
      47                 :            : 
      48                 :            :         jffs2_dbg(1, "forbid writing\n");
      49                 :          0 :         return 0;
      50                 :            : }
      51                 :            : 
      52                 :            : /**
      53                 :            :  *      jffs2_reserve_space - request physical space to write nodes to flash
      54                 :            :  *      @c: superblock info
      55                 :            :  *      @minsize: Minimum acceptable size of allocation
      56                 :            :  *      @len: Returned value of allocation length
      57                 :            :  *      @prio: Allocation type - ALLOC_{NORMAL,DELETION}
      58                 :            :  *
      59                 :            :  *      Requests a block of physical space on the flash. Returns zero for success
      60                 :            :  *      and puts 'len' into the appropriate place, or returns -ENOSPC or other 
      61                 :            :  *      error if appropriate. Doesn't return len since that's 
      62                 :            :  *
      63                 :            :  *      If it returns zero, jffs2_reserve_space() also downs the per-filesystem
      64                 :            :  *      allocation semaphore, to prevent more than one allocation from being
      65                 :            :  *      active at any time. The semaphore is later released by jffs2_commit_allocation()
      66                 :            :  *
      67                 :            :  *      jffs2_reserve_space() may trigger garbage collection in order to make room
      68                 :            :  *      for the requested allocation.
      69                 :            :  */
      70                 :            : 
      71                 :            : static int jffs2_do_reserve_space(struct jffs2_sb_info *c,  uint32_t minsize,
      72                 :            :                                   uint32_t *len, uint32_t sumsize);
      73                 :            : 
      74                 :          0 : int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
      75                 :            :                         uint32_t *len, int prio, uint32_t sumsize)
      76                 :            : {
      77                 :            :         int ret = -EAGAIN;
      78                 :          0 :         int blocksneeded = c->resv_blocks_write;
      79                 :            :         /* align it */
      80                 :          0 :         minsize = PAD(minsize);
      81                 :            : 
      82                 :            :         jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
      83                 :          0 :         mutex_lock(&c->alloc_sem);
      84                 :            : 
      85                 :            :         jffs2_dbg(1, "%s(): alloc sem got\n", __func__);
      86                 :            : 
      87                 :            :         spin_lock(&c->erase_completion_lock);
      88                 :            : 
      89                 :            :         /*
      90                 :            :          * Check if the free space is greater then size of the reserved pool.
      91                 :            :          * If not, only allow root to proceed with writing.
      92                 :            :          */
      93 [ #  # ][ #  # ]:          0 :         if (prio != ALLOC_DELETION && !jffs2_rp_can_write(c)) {
      94                 :            :                 ret = -ENOSPC;
      95                 :            :                 goto out;
      96                 :            :         }
      97                 :            : 
      98                 :            :         /* this needs a little more thought (true <tglx> :)) */
      99         [ #  # ]:          0 :         while(ret == -EAGAIN) {
     100         [ #  # ]:          0 :                 while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
     101                 :            :                         uint32_t dirty, avail;
     102                 :            : 
     103                 :            :                         /* calculate real dirty size
     104                 :            :                          * dirty_size contains blocks on erase_pending_list
     105                 :            :                          * those blocks are counted in c->nr_erasing_blocks.
     106                 :            :                          * If one block is actually erased, it is not longer counted as dirty_space
     107                 :            :                          * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
     108                 :            :                          * with c->nr_erasing_blocks * c->sector_size again.
     109                 :            :                          * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
     110                 :            :                          * This helps us to force gc and pick eventually a clean block to spread the load.
     111                 :            :                          * We add unchecked_size here, as we hopefully will find some space to use.
     112                 :            :                          * This will affect the sum only once, as gc first finishes checking
     113                 :            :                          * of nodes.
     114                 :            :                          */
     115                 :          0 :                         dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size;
     116         [ #  # ]:          0 :                         if (dirty < c->nospc_dirty_size) {
     117 [ #  # ][ #  # ]:          0 :                                 if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
     118                 :            :                                         jffs2_dbg(1, "%s(): Low on dirty space to GC, but it's a deletion. Allowing...\n",
     119                 :            :                                                   __func__);
     120                 :            :                                         break;
     121                 :            :                                 }
     122                 :            :                                 jffs2_dbg(1, "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n",
     123                 :            :                                           dirty, c->unchecked_size,
     124                 :            :                                           c->sector_size);
     125                 :            : 
     126                 :            :                                 spin_unlock(&c->erase_completion_lock);
     127                 :          0 :                                 mutex_unlock(&c->alloc_sem);
     128                 :          0 :                                 return -ENOSPC;
     129                 :            :                         }
     130                 :            : 
     131                 :            :                         /* Calc possibly available space. Possibly available means that we
     132                 :            :                          * don't know, if unchecked size contains obsoleted nodes, which could give us some
     133                 :            :                          * more usable space. This will affect the sum only once, as gc first finishes checking
     134                 :            :                          * of nodes.
     135                 :            :                          + Return -ENOSPC, if the maximum possibly available space is less or equal than
     136                 :            :                          * blocksneeded * sector_size.
     137                 :            :                          * This blocks endless gc looping on a filesystem, which is nearly full, even if
     138                 :            :                          * the check above passes.
     139                 :            :                          */
     140                 :          0 :                         avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size;
     141         [ #  # ]:          0 :                         if ( (avail / c->sector_size) <= blocksneeded) {
     142 [ #  # ][ #  # ]:          0 :                                 if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
     143                 :            :                                         jffs2_dbg(1, "%s(): Low on possibly available space, but it's a deletion. Allowing...\n",
     144                 :            :                                                   __func__);
     145                 :            :                                         break;
     146                 :            :                                 }
     147                 :            : 
     148                 :            :                                 jffs2_dbg(1, "max. available size 0x%08x  < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
     149                 :            :                                           avail, blocksneeded * c->sector_size);
     150                 :            :                                 spin_unlock(&c->erase_completion_lock);
     151                 :          0 :                                 mutex_unlock(&c->alloc_sem);
     152                 :          0 :                                 return -ENOSPC;
     153                 :            :                         }
     154                 :            : 
     155                 :          0 :                         mutex_unlock(&c->alloc_sem);
     156                 :            : 
     157                 :            :                         jffs2_dbg(1, "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
     158                 :            :                                   c->nr_free_blocks, c->nr_erasing_blocks,
     159                 :            :                                   c->free_size, c->dirty_size, c->wasted_size,
     160                 :            :                                   c->used_size, c->erasing_size, c->bad_size,
     161                 :            :                                   c->free_size + c->dirty_size +
     162                 :            :                                   c->wasted_size + c->used_size +
     163                 :            :                                   c->erasing_size + c->bad_size,
     164                 :            :                                   c->flash_size);
     165                 :            :                         spin_unlock(&c->erase_completion_lock);
     166                 :            : 
     167                 :          0 :                         ret = jffs2_garbage_collect_pass(c);
     168                 :            : 
     169         [ #  # ]:          0 :                         if (ret == -EAGAIN) {
     170                 :            :                                 spin_lock(&c->erase_completion_lock);
     171 [ #  # ][ #  # ]:          0 :                                 if (c->nr_erasing_blocks &&
     172         [ #  # ]:          0 :                                     list_empty(&c->erase_pending_list) &&
     173                 :          0 :                                     list_empty(&c->erase_complete_list)) {
     174                 :          0 :                                         DECLARE_WAITQUEUE(wait, current);
     175                 :          0 :                                         set_current_state(TASK_UNINTERRUPTIBLE);
     176                 :          0 :                                         add_wait_queue(&c->erase_wait, &wait);
     177                 :            :                                         jffs2_dbg(1, "%s waiting for erase to complete\n",
     178                 :            :                                                   __func__);
     179                 :            :                                         spin_unlock(&c->erase_completion_lock);
     180                 :            : 
     181                 :          0 :                                         schedule();
     182                 :            :                                 } else
     183                 :            :                                         spin_unlock(&c->erase_completion_lock);
     184         [ #  # ]:          0 :                         } else if (ret)
     185                 :            :                                 return ret;
     186                 :            : 
     187                 :          0 :                         cond_resched();
     188                 :            : 
     189         [ #  # ]:          0 :                         if (signal_pending(current))
     190                 :            :                                 return -EINTR;
     191                 :            : 
     192                 :          0 :                         mutex_lock(&c->alloc_sem);
     193                 :            :                         spin_lock(&c->erase_completion_lock);
     194                 :            :                 }
     195                 :            : 
     196                 :          0 :                 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
     197                 :            :                 if (ret) {
     198                 :            :                         jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret);
     199                 :            :                 }
     200                 :            :         }
     201                 :            : 
     202                 :            : out:
     203                 :            :         spin_unlock(&c->erase_completion_lock);
     204         [ #  # ]:          0 :         if (!ret)
     205                 :          0 :                 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
     206         [ #  # ]:          0 :         if (ret)
     207                 :          0 :                 mutex_unlock(&c->alloc_sem);
     208                 :          0 :         return ret;
     209                 :            : }
     210                 :            : 
     211                 :          0 : int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
     212                 :            :                            uint32_t *len, uint32_t sumsize)
     213                 :            : {
     214                 :            :         int ret = -EAGAIN;
     215                 :          0 :         minsize = PAD(minsize);
     216                 :            : 
     217                 :            :         jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize);
     218                 :            : 
     219                 :            :         spin_lock(&c->erase_completion_lock);
     220         [ #  # ]:          0 :         while(ret == -EAGAIN) {
     221                 :          0 :                 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
     222                 :            :                 if (ret) {
     223                 :            :                         jffs2_dbg(1, "%s(): looping, ret is %d\n",
     224                 :            :                                   __func__, ret);
     225                 :            :                 }
     226                 :            :         }
     227                 :            :         spin_unlock(&c->erase_completion_lock);
     228         [ #  # ]:          0 :         if (!ret)
     229                 :          0 :                 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
     230                 :            : 
     231                 :          0 :         return ret;
     232                 :            : }
     233                 :            : 
     234                 :            : 
     235                 :            : /* Classify nextblock (clean, dirty of verydirty) and force to select an other one */
     236                 :            : 
     237                 :          0 : static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
     238                 :            : {
     239                 :            : 
     240         [ #  # ]:          0 :         if (c->nextblock == NULL) {
     241                 :            :                 jffs2_dbg(1, "%s(): Erase block at 0x%08x has already been placed in a list\n",
     242                 :            :                           __func__, jeb->offset);
     243                 :          0 :                 return;
     244                 :            :         }
     245                 :            :         /* Check, if we have a dirty block now, or if it was dirty already */
     246         [ #  # ]:          0 :         if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
     247                 :          0 :                 c->dirty_size += jeb->wasted_size;
     248                 :          0 :                 c->wasted_size -= jeb->wasted_size;
     249                 :          0 :                 jeb->dirty_size += jeb->wasted_size;
     250                 :          0 :                 jeb->wasted_size = 0;
     251         [ #  # ]:          0 :                 if (VERYDIRTY(c, jeb->dirty_size)) {
     252                 :            :                         jffs2_dbg(1, "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
     253                 :            :                                   jeb->offset, jeb->free_size, jeb->dirty_size,
     254                 :            :                                   jeb->used_size);
     255                 :          0 :                         list_add_tail(&jeb->list, &c->very_dirty_list);
     256                 :            :                 } else {
     257                 :            :                         jffs2_dbg(1, "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
     258                 :            :                                   jeb->offset, jeb->free_size, jeb->dirty_size,
     259                 :            :                                   jeb->used_size);
     260                 :          0 :                         list_add_tail(&jeb->list, &c->dirty_list);
     261                 :            :                 }
     262                 :            :         } else {
     263                 :            :                 jffs2_dbg(1, "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
     264                 :            :                           jeb->offset, jeb->free_size, jeb->dirty_size,
     265                 :            :                           jeb->used_size);
     266                 :          0 :                 list_add_tail(&jeb->list, &c->clean_list);
     267                 :            :         }
     268                 :          0 :         c->nextblock = NULL;
     269                 :            : 
     270                 :            : }
     271                 :            : 
     272                 :            : /* Select a new jeb for nextblock */
     273                 :            : 
     274                 :          0 : static int jffs2_find_nextblock(struct jffs2_sb_info *c)
     275                 :            : {
     276                 :            :         struct list_head *next;
     277                 :            : 
     278                 :            :         /* Take the next block off the 'free' list */
     279                 :            : 
     280         [ #  # ]:          0 :         if (list_empty(&c->free_list)) {
     281                 :            : 
     282 [ #  # ][ #  # ]:          0 :                 if (!c->nr_erasing_blocks &&
     283                 :          0 :                         !list_empty(&c->erasable_list)) {
     284                 :            :                         struct jffs2_eraseblock *ejeb;
     285                 :            : 
     286                 :            :                         ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list);
     287                 :          0 :                         list_move_tail(&ejeb->list, &c->erase_pending_list);
     288                 :          0 :                         c->nr_erasing_blocks++;
     289                 :          0 :                         jffs2_garbage_collect_trigger(c);
     290                 :            :                         jffs2_dbg(1, "%s(): Triggering erase of erasable block at 0x%08x\n",
     291                 :            :                                   __func__, ejeb->offset);
     292                 :            :                 }
     293                 :            : 
     294 [ #  # ][ #  # ]:          0 :                 if (!c->nr_erasing_blocks &&
     295                 :          0 :                         !list_empty(&c->erasable_pending_wbuf_list)) {
     296                 :            :                         jffs2_dbg(1, "%s(): Flushing write buffer\n",
     297                 :            :                                   __func__);
     298                 :            :                         /* c->nextblock is NULL, no update to c->nextblock allowed */
     299                 :            :                         spin_unlock(&c->erase_completion_lock);
     300                 :          0 :                         jffs2_flush_wbuf_pad(c);
     301                 :            :                         spin_lock(&c->erase_completion_lock);
     302                 :            :                         /* Have another go. It'll be on the erasable_list now */
     303                 :          0 :                         return -EAGAIN;
     304                 :            :                 }
     305                 :            : 
     306         [ #  # ]:          0 :                 if (!c->nr_erasing_blocks) {
     307                 :            :                         /* Ouch. We're in GC, or we wouldn't have got here.
     308                 :            :                            And there's no space left. At all. */
     309 [ #  # ][ #  # ]:          0 :                         pr_crit("Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n",
                 [ #  # ]
     310                 :            :                                 c->nr_erasing_blocks, c->nr_free_blocks,
     311                 :            :                                 list_empty(&c->erasable_list) ? "yes" : "no",
     312                 :            :                                 list_empty(&c->erasing_list) ? "yes" : "no",
     313                 :            :                                 list_empty(&c->erase_pending_list) ? "yes" : "no");
     314                 :          0 :                         return -ENOSPC;
     315                 :            :                 }
     316                 :            : 
     317                 :            :                 spin_unlock(&c->erase_completion_lock);
     318                 :            :                 /* Don't wait for it; just erase one right now */
     319                 :          0 :                 jffs2_erase_pending_blocks(c, 1);
     320                 :            :                 spin_lock(&c->erase_completion_lock);
     321                 :            : 
     322                 :            :                 /* An erase may have failed, decreasing the
     323                 :            :                    amount of free space available. So we must
     324                 :            :                    restart from the beginning */
     325                 :          0 :                 return -EAGAIN;
     326                 :            :         }
     327                 :            : 
     328                 :            :         next = c->free_list.next;
     329                 :            :         list_del(next);
     330                 :          0 :         c->nextblock = list_entry(next, struct jffs2_eraseblock, list);
     331                 :          0 :         c->nr_free_blocks--;
     332                 :            : 
     333                 :          0 :         jffs2_sum_reset_collected(c->summary); /* reset collected summary */
     334                 :            : 
     335                 :            : #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
     336                 :            :         /* adjust write buffer offset, else we get a non contiguous write bug */
     337 [ #  # ][ #  # ]:          0 :         if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
     338                 :          0 :                 c->wbuf_ofs = 0xffffffff;
     339                 :            : #endif
     340                 :            : 
     341                 :            :         jffs2_dbg(1, "%s(): new nextblock = 0x%08x\n",
     342                 :            :                   __func__, c->nextblock->offset);
     343                 :            : 
     344                 :            :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :            : /* Called with alloc sem _and_ erase_completion_lock */
     348                 :          0 : static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
     349                 :            :                                   uint32_t *len, uint32_t sumsize)
     350                 :            : {
     351                 :          0 :         struct jffs2_eraseblock *jeb = c->nextblock;
     352                 :            :         uint32_t reserved_size;                         /* for summary information at the end of the jeb */
     353                 :            :         int ret;
     354                 :            : 
     355                 :            :  restart:
     356                 :            :         reserved_size = 0;
     357                 :            : 
     358         [ #  # ]:          0 :         if (jffs2_sum_active() && (sumsize != JFFS2_SUMMARY_NOSUM_SIZE)) {
     359                 :            :                                                         /* NOSUM_SIZE means not to generate summary */
     360                 :            : 
     361         [ #  # ]:          0 :                 if (jeb) {
     362                 :          0 :                         reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE);
     363                 :            :                         dbg_summary("minsize=%d , jeb->free=%d ,"
     364                 :            :                                                 "summary->size=%d , sumsize=%d\n",
     365                 :            :                                                 minsize, jeb->free_size,
     366                 :            :                                                 c->summary->sum_size, sumsize);
     367                 :            :                 }
     368                 :            : 
     369                 :            :                 /* Is there enough space for writing out the current node, or we have to
     370                 :            :                    write out summary information now, close this jeb and select new nextblock? */
     371 [ #  # ][ #  # ]:          0 :                 if (jeb && (PAD(minsize) + PAD(c->summary->sum_size + sumsize +
     372                 :          0 :                                         JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size)) {
     373                 :            : 
     374                 :            :                         /* Has summary been disabled for this jeb? */
     375         [ #  # ]:          0 :                         if (jffs2_sum_is_disabled(c->summary)) {
     376                 :            :                                 sumsize = JFFS2_SUMMARY_NOSUM_SIZE;
     377                 :            :                                 goto restart;
     378                 :            :                         }
     379                 :            : 
     380                 :            :                         /* Writing out the collected summary information */
     381                 :            :                         dbg_summary("generating summary for 0x%08x.\n", jeb->offset);
     382                 :          0 :                         ret = jffs2_sum_write_sumnode(c);
     383                 :            : 
     384         [ #  # ]:          0 :                         if (ret)
     385                 :            :                                 return ret;
     386                 :            : 
     387         [ #  # ]:          0 :                         if (jffs2_sum_is_disabled(c->summary)) {
     388                 :            :                                 /* jffs2_write_sumnode() couldn't write out the summary information
     389                 :            :                                    diabling summary for this jeb and free the collected information
     390                 :            :                                  */
     391                 :            :                                 sumsize = JFFS2_SUMMARY_NOSUM_SIZE;
     392                 :            :                                 goto restart;
     393                 :            :                         }
     394                 :            : 
     395                 :          0 :                         jffs2_close_nextblock(c, jeb);
     396                 :            :                         jeb = NULL;
     397                 :            :                         /* keep always valid value in reserved_size */
     398                 :          0 :                         reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE);
     399                 :            :                 }
     400                 :            :         } else {
     401 [ #  # ][ #  # ]:          0 :                 if (jeb && minsize > jeb->free_size) {
     402                 :            :                         uint32_t waste;
     403                 :            : 
     404                 :            :                         /* Skip the end of this block and file it as having some dirty space */
     405                 :            :                         /* If there's a pending write to it, flush now */
     406                 :            : 
     407         [ #  # ]:          0 :                         if (jffs2_wbuf_dirty(c)) {
     408                 :            :                                 spin_unlock(&c->erase_completion_lock);
     409                 :            :                                 jffs2_dbg(1, "%s(): Flushing write buffer\n",
     410                 :            :                                           __func__);
     411                 :          0 :                                 jffs2_flush_wbuf_pad(c);
     412                 :            :                                 spin_lock(&c->erase_completion_lock);
     413                 :          0 :                                 jeb = c->nextblock;
     414                 :          0 :                                 goto restart;
     415                 :            :                         }
     416                 :            : 
     417                 :            :                         spin_unlock(&c->erase_completion_lock);
     418                 :            : 
     419                 :          0 :                         ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
     420                 :            : 
     421                 :            :                         /* Just lock it again and continue. Nothing much can change because
     422                 :            :                            we hold c->alloc_sem anyway. In fact, it's not entirely clear why
     423                 :            :                            we hold c->erase_completion_lock in the majority of this function...
     424                 :            :                            but that's a question for another (more caffeine-rich) day. */
     425                 :            :                         spin_lock(&c->erase_completion_lock);
     426                 :            : 
     427         [ #  # ]:          0 :                         if (ret)
     428                 :            :                                 return ret;
     429                 :            : 
     430                 :          0 :                         waste = jeb->free_size;
     431                 :          0 :                         jffs2_link_node_ref(c, jeb,
     432                 :          0 :                                             (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
     433                 :            :                                             waste, NULL);
     434                 :            :                         /* FIXME: that made it count as dirty. Convert to wasted */
     435                 :          0 :                         jeb->dirty_size -= waste;
     436                 :          0 :                         c->dirty_size -= waste;
     437                 :          0 :                         jeb->wasted_size += waste;
     438                 :          0 :                         c->wasted_size += waste;
     439                 :            : 
     440                 :          0 :                         jffs2_close_nextblock(c, jeb);
     441                 :            :                         jeb = NULL;
     442                 :            :                 }
     443                 :            :         }
     444                 :            : 
     445         [ #  # ]:          0 :         if (!jeb) {
     446                 :            : 
     447                 :          0 :                 ret = jffs2_find_nextblock(c);
     448         [ #  # ]:          0 :                 if (ret)
     449                 :            :                         return ret;
     450                 :            : 
     451                 :          0 :                 jeb = c->nextblock;
     452                 :            : 
     453         [ #  # ]:          0 :                 if (jeb->free_size != c->sector_size - c->cleanmarker_size) {
     454                 :          0 :                         pr_warn("Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n",
     455                 :            :                                 jeb->offset, jeb->free_size);
     456                 :          0 :                         goto restart;
     457                 :            :                 }
     458                 :            :         }
     459                 :            :         /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
     460                 :            :            enough space */
     461                 :          0 :         *len = jeb->free_size - reserved_size;
     462                 :            : 
     463 [ #  # ][ #  # ]:          0 :         if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
                 [ #  # ]
     464                 :          0 :             !jeb->first_node->next_in_ino) {
     465                 :            :                 /* Only node in it beforehand was a CLEANMARKER node (we think).
     466                 :            :                    So mark it obsolete now that there's going to be another node
     467                 :            :                    in the block. This will reduce used_size to zero but We've
     468                 :            :                    already set c->nextblock so that jffs2_mark_node_obsolete()
     469                 :            :                    won't try to refile it to the dirty_list.
     470                 :            :                 */
     471                 :            :                 spin_unlock(&c->erase_completion_lock);
     472                 :          0 :                 jffs2_mark_node_obsolete(c, jeb->first_node);
     473                 :            :                 spin_lock(&c->erase_completion_lock);
     474                 :            :         }
     475                 :            : 
     476                 :            :         jffs2_dbg(1, "%s(): Giving 0x%x bytes at 0x%x\n",
     477                 :            :                   __func__,
     478                 :            :                   *len, jeb->offset + (c->sector_size - jeb->free_size));
     479                 :            :         return 0;
     480                 :            : }
     481                 :            : 
     482                 :            : /**
     483                 :            :  *      jffs2_add_physical_node_ref - add a physical node reference to the list
     484                 :            :  *      @c: superblock info
     485                 :            :  *      @new: new node reference to add
     486                 :            :  *      @len: length of this physical node
     487                 :            :  *
     488                 :            :  *      Should only be used to report nodes for which space has been allocated
     489                 :            :  *      by jffs2_reserve_space.
     490                 :            :  *
     491                 :            :  *      Must be called with the alloc_sem held.
     492                 :            :  */
     493                 :            : 
     494                 :          0 : struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
     495                 :            :                                                        uint32_t ofs, uint32_t len,
     496                 :            :                                                        struct jffs2_inode_cache *ic)
     497                 :            : {
     498                 :            :         struct jffs2_eraseblock *jeb;
     499                 :            :         struct jffs2_raw_node_ref *new;
     500                 :            : 
     501                 :          0 :         jeb = &c->blocks[ofs / c->sector_size];
     502                 :            : 
     503                 :            :         jffs2_dbg(1, "%s(): Node at 0x%x(%d), size 0x%x\n",
     504                 :            :                   __func__, ofs & ~3, ofs & 3, len);
     505                 :            : #if 1
     506                 :            :         /* Allow non-obsolete nodes only to be added at the end of c->nextblock, 
     507                 :            :            if c->nextblock is set. Note that wbuf.c will file obsolete nodes
     508                 :            :            even after refiling c->nextblock */
     509 [ #  # ][ #  # ]:          0 :         if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
     510 [ #  # ][ #  # ]:          0 :             && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
     511                 :          0 :                 pr_warn("argh. node added in wrong place at 0x%08x(%d)\n",
     512                 :            :                         ofs & ~3, ofs & 3);
     513         [ #  # ]:          0 :                 if (c->nextblock)
     514                 :          0 :                         pr_warn("nextblock 0x%08x", c->nextblock->offset);
     515                 :            :                 else
     516                 :          0 :                         pr_warn("No nextblock");
     517                 :          0 :                 pr_cont(", expected at %08x\n",
     518                 :            :                         jeb->offset + (c->sector_size - jeb->free_size));
     519                 :          0 :                 return ERR_PTR(-EINVAL);
     520                 :            :         }
     521                 :            : #endif
     522                 :            :         spin_lock(&c->erase_completion_lock);
     523                 :            : 
     524                 :          0 :         new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
     525                 :            : 
     526 [ #  # ][ #  # ]:          0 :         if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
                 [ #  # ]
     527                 :            :                 /* If it lives on the dirty_list, jffs2_reserve_space will put it there */
     528                 :            :                 jffs2_dbg(1, "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
     529                 :            :                           jeb->offset, jeb->free_size, jeb->dirty_size,
     530                 :            :                           jeb->used_size);
     531         [ #  # ]:          0 :                 if (jffs2_wbuf_dirty(c)) {
     532                 :            :                         /* Flush the last write in the block if it's outstanding */
     533                 :            :                         spin_unlock(&c->erase_completion_lock);
     534                 :          0 :                         jffs2_flush_wbuf_pad(c);
     535                 :            :                         spin_lock(&c->erase_completion_lock);
     536                 :            :                 }
     537                 :            : 
     538                 :          0 :                 list_add_tail(&jeb->list, &c->clean_list);
     539                 :          0 :                 c->nextblock = NULL;
     540                 :            :         }
     541                 :          0 :         jffs2_dbg_acct_sanity_check_nolock(c,jeb);
     542                 :            :         jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
     543                 :            : 
     544                 :            :         spin_unlock(&c->erase_completion_lock);
     545                 :            : 
     546                 :          0 :         return new;
     547                 :            : }
     548                 :            : 
     549                 :            : 
     550                 :          0 : void jffs2_complete_reservation(struct jffs2_sb_info *c)
     551                 :            : {
     552                 :            :         jffs2_dbg(1, "jffs2_complete_reservation()\n");
     553                 :            :         spin_lock(&c->erase_completion_lock);
     554                 :          0 :         jffs2_garbage_collect_trigger(c);
     555                 :            :         spin_unlock(&c->erase_completion_lock);
     556                 :          0 :         mutex_unlock(&c->alloc_sem);
     557                 :          0 : }
     558                 :            : 
     559                 :            : static inline int on_list(struct list_head *obj, struct list_head *head)
     560                 :            : {
     561                 :            :         struct list_head *this;
     562                 :            : 
     563         [ #  # ]:          0 :         list_for_each(this, head) {
     564         [ #  # ]:          0 :                 if (this == obj) {
     565                 :            :                         jffs2_dbg(1, "%p is on list at %p\n", obj, head);
     566                 :            :                         return 1;
     567                 :            : 
     568                 :            :                 }
     569                 :            :         }
     570                 :            :         return 0;
     571                 :            : }
     572                 :            : 
     573                 :          0 : void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
     574                 :            : {
     575                 :            :         struct jffs2_eraseblock *jeb;
     576                 :            :         int blocknr;
     577                 :            :         struct jffs2_unknown_node n;
     578                 :            :         int ret, addedsize;
     579                 :            :         size_t retlen;
     580                 :            :         uint32_t freed_len;
     581                 :            : 
     582         [ #  # ]:          0 :         if(unlikely(!ref)) {
     583                 :          0 :                 pr_notice("EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
     584                 :          0 :                 return;
     585                 :            :         }
     586         [ #  # ]:          0 :         if (ref_obsolete(ref)) {
     587                 :            :                 jffs2_dbg(1, "%s(): called with already obsolete node at 0x%08x\n",
     588                 :            :                           __func__, ref_offset(ref));
     589                 :            :                 return;
     590                 :            :         }
     591                 :          0 :         blocknr = ref->flash_offset / c->sector_size;
     592         [ #  # ]:          0 :         if (blocknr >= c->nr_blocks) {
     593                 :          0 :                 pr_notice("raw node at 0x%08x is off the end of device!\n",
     594                 :            :                           ref->flash_offset);
     595                 :          0 :                 BUG();
     596                 :            :         }
     597                 :          0 :         jeb = &c->blocks[blocknr];
     598                 :            : 
     599                 :            :         if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) &&
     600                 :            :             !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) {
     601                 :            :                 /* Hm. This may confuse static lock analysis. If any of the above
     602                 :            :                    three conditions is false, we're going to return from this
     603                 :            :                    function without actually obliterating any nodes or freeing
     604                 :            :                    any jffs2_raw_node_refs. So we don't need to stop erases from
     605                 :            :                    happening, or protect against people holding an obsolete
     606                 :            :                    jffs2_raw_node_ref without the erase_completion_lock. */
     607                 :            :                 mutex_lock(&c->erase_free_sem);
     608                 :            :         }
     609                 :            : 
     610                 :            :         spin_lock(&c->erase_completion_lock);
     611                 :            : 
     612                 :          0 :         freed_len = ref_totlen(c, jeb, ref);
     613                 :            : 
     614         [ #  # ]:          0 :         if (ref_flags(ref) == REF_UNCHECKED) {
     615                 :            :                 D1(if (unlikely(jeb->unchecked_size < freed_len)) {
     616                 :            :                                 pr_notice("raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
     617                 :            :                                           freed_len, blocknr,
     618                 :            :                                           ref->flash_offset, jeb->used_size);
     619                 :            :                         BUG();
     620                 :            :                 })
     621                 :            :                         jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n",
     622                 :            :                                   ref_offset(ref), freed_len);
     623                 :          0 :                 jeb->unchecked_size -= freed_len;
     624                 :          0 :                 c->unchecked_size -= freed_len;
     625                 :            :         } else {
     626                 :            :                 D1(if (unlikely(jeb->used_size < freed_len)) {
     627                 :            :                                 pr_notice("raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
     628                 :            :                                           freed_len, blocknr,
     629                 :            :                                           ref->flash_offset, jeb->used_size);
     630                 :            :                         BUG();
     631                 :            :                 })
     632                 :            :                         jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ",
     633                 :            :                                   ref_offset(ref), freed_len);
     634                 :          0 :                 jeb->used_size -= freed_len;
     635                 :          0 :                 c->used_size -= freed_len;
     636                 :            :         }
     637                 :            : 
     638                 :            :         // Take care, that wasted size is taken into concern
     639 [ #  # ][ #  # ]:          0 :         if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
                 [ #  # ]
     640                 :            :                 jffs2_dbg(1, "Dirtying\n");
     641                 :          0 :                 addedsize = freed_len;
     642                 :          0 :                 jeb->dirty_size += freed_len;
     643                 :          0 :                 c->dirty_size += freed_len;
     644                 :            : 
     645                 :            :                 /* Convert wasted space to dirty, if not a bad block */
     646         [ #  # ]:          0 :                 if (jeb->wasted_size) {
     647         [ #  # ]:          0 :                         if (on_list(&jeb->list, &c->bad_used_list)) {
     648                 :            :                                 jffs2_dbg(1, "Leaving block at %08x on the bad_used_list\n",
     649                 :            :                                           jeb->offset);
     650                 :            :                                 addedsize = 0; /* To fool the refiling code later */
     651                 :            :                         } else {
     652                 :            :                                 jffs2_dbg(1, "Converting %d bytes of wasted space to dirty in block at %08x\n",
     653                 :            :                                           jeb->wasted_size, jeb->offset);
     654                 :          0 :                                 addedsize += jeb->wasted_size;
     655                 :          0 :                                 jeb->dirty_size += jeb->wasted_size;
     656                 :          0 :                                 c->dirty_size += jeb->wasted_size;
     657                 :          0 :                                 c->wasted_size -= jeb->wasted_size;
     658                 :          0 :                                 jeb->wasted_size = 0;
     659                 :            :                         }
     660                 :            :                 }
     661                 :            :         } else {
     662                 :            :                 jffs2_dbg(1, "Wasting\n");
     663                 :            :                 addedsize = 0;
     664                 :          0 :                 jeb->wasted_size += freed_len;
     665                 :          0 :                 c->wasted_size += freed_len;
     666                 :            :         }
     667                 :          0 :         ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
     668                 :            : 
     669                 :          0 :         jffs2_dbg_acct_sanity_check_nolock(c, jeb);
     670                 :            :         jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
     671                 :            : 
     672         [ #  # ]:          0 :         if (c->flags & JFFS2_SB_FLAG_SCANNING) {
     673                 :            :                 /* Flash scanning is in progress. Don't muck about with the block
     674                 :            :                    lists because they're not ready yet, and don't actually
     675                 :            :                    obliterate nodes that look obsolete. If they weren't
     676                 :            :                    marked obsolete on the flash at the time they _became_
     677                 :            :                    obsolete, there was probably a reason for that. */
     678                 :            :                 spin_unlock(&c->erase_completion_lock);
     679                 :            :                 /* We didn't lock the erase_free_sem */
     680                 :            :                 return;
     681                 :            :         }
     682                 :            : 
     683         [ #  # ]:          0 :         if (jeb == c->nextblock) {
     684                 :            :                 jffs2_dbg(2, "Not moving nextblock 0x%08x to dirty/erase_pending list\n",
     685                 :            :                           jeb->offset);
     686 [ #  # ][ #  # ]:          0 :         } else if (!jeb->used_size && !jeb->unchecked_size) {
     687         [ #  # ]:          0 :                 if (jeb == c->gcblock) {
     688                 :            :                         jffs2_dbg(1, "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n",
     689                 :            :                                   jeb->offset);
     690                 :          0 :                         c->gcblock = NULL;
     691                 :            :                 } else {
     692                 :            :                         jffs2_dbg(1, "Eraseblock at 0x%08x completely dirtied. Removing from (dirty?) list...\n",
     693                 :            :                                   jeb->offset);
     694                 :            :                         list_del(&jeb->list);
     695                 :            :                 }
     696         [ #  # ]:          0 :                 if (jffs2_wbuf_dirty(c)) {
     697                 :            :                         jffs2_dbg(1, "...and adding to erasable_pending_wbuf_list\n");
     698                 :          0 :                         list_add_tail(&jeb->list, &c->erasable_pending_wbuf_list);
     699                 :            :                 } else {
     700         [ #  # ]:          0 :                         if (jiffies & 127) {
     701                 :            :                                 /* Most of the time, we just erase it immediately. Otherwise we
     702                 :            :                                    spend ages scanning it on mount, etc. */
     703                 :            :                                 jffs2_dbg(1, "...and adding to erase_pending_list\n");
     704                 :          0 :                                 list_add_tail(&jeb->list, &c->erase_pending_list);
     705                 :          0 :                                 c->nr_erasing_blocks++;
     706                 :          0 :                                 jffs2_garbage_collect_trigger(c);
     707                 :            :                         } else {
     708                 :            :                                 /* Sometimes, however, we leave it elsewhere so it doesn't get
     709                 :            :                                    immediately reused, and we spread the load a bit. */
     710                 :            :                                 jffs2_dbg(1, "...and adding to erasable_list\n");
     711                 :          0 :                                 list_add_tail(&jeb->list, &c->erasable_list);
     712                 :            :                         }
     713                 :            :                 }
     714                 :            :                 jffs2_dbg(1, "Done OK\n");
     715         [ #  # ]:          0 :         } else if (jeb == c->gcblock) {
     716                 :            :                 jffs2_dbg(2, "Not moving gcblock 0x%08x to dirty_list\n",
     717                 :            :                           jeb->offset);
     718 [ #  # ][ #  # ]:          0 :         } else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - addedsize)) {
     719                 :            :                 jffs2_dbg(1, "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n",
     720                 :            :                           jeb->offset);
     721                 :            :                 list_del(&jeb->list);
     722                 :            :                 jffs2_dbg(1, "...and adding to dirty_list\n");
     723                 :          0 :                 list_add_tail(&jeb->list, &c->dirty_list);
     724 [ #  # ][ #  # ]:          0 :         } else if (VERYDIRTY(c, jeb->dirty_size) &&
     725                 :          0 :                    !VERYDIRTY(c, jeb->dirty_size - addedsize)) {
     726                 :            :                 jffs2_dbg(1, "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n",
     727                 :            :                           jeb->offset);
     728                 :            :                 list_del(&jeb->list);
     729                 :            :                 jffs2_dbg(1, "...and adding to very_dirty_list\n");
     730                 :          0 :                 list_add_tail(&jeb->list, &c->very_dirty_list);
     731                 :            :         } else {
     732                 :            :                 jffs2_dbg(1, "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n",
     733                 :            :                           jeb->offset, jeb->free_size, jeb->dirty_size,
     734                 :            :                           jeb->used_size);
     735                 :            :         }
     736                 :            : 
     737                 :            :         spin_unlock(&c->erase_completion_lock);
     738                 :            : 
     739                 :            :         if (!jffs2_can_mark_obsolete(c) || jffs2_is_readonly(c) ||
     740                 :            :                 (c->flags & JFFS2_SB_FLAG_BUILDING)) {
     741                 :            :                 /* We didn't lock the erase_free_sem */
     742                 :            :                 return;
     743                 :            :         }
     744                 :            : 
     745                 :            :         /* The erase_free_sem is locked, and has been since before we marked the node obsolete
     746                 :            :            and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
     747                 :            :            the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
     748                 :            :            by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
     749                 :            : 
     750                 :            :         jffs2_dbg(1, "obliterating obsoleted node at 0x%08x\n",
     751                 :            :                   ref_offset(ref));
     752                 :            :         ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
     753                 :            :         if (ret) {
     754                 :            :                 pr_warn("Read error reading from obsoleted node at 0x%08x: %d\n",
     755                 :            :                         ref_offset(ref), ret);
     756                 :            :                 goto out_erase_sem;
     757                 :            :         }
     758                 :            :         if (retlen != sizeof(n)) {
     759                 :            :                 pr_warn("Short read from obsoleted node at 0x%08x: %zd\n",
     760                 :            :                         ref_offset(ref), retlen);
     761                 :            :                 goto out_erase_sem;
     762                 :            :         }
     763                 :            :         if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
     764                 :            :                 pr_warn("Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n",
     765                 :            :                         je32_to_cpu(n.totlen), freed_len);
     766                 :            :                 goto out_erase_sem;
     767                 :            :         }
     768                 :            :         if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
     769                 :            :                 jffs2_dbg(1, "Node at 0x%08x was already marked obsolete (nodetype 0x%04x)\n",
     770                 :            :                           ref_offset(ref), je16_to_cpu(n.nodetype));
     771                 :            :                 goto out_erase_sem;
     772                 :            :         }
     773                 :            :         /* XXX FIXME: This is ugly now */
     774                 :            :         n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE);
     775                 :            :         ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
     776                 :            :         if (ret) {
     777                 :            :                 pr_warn("Write error in obliterating obsoleted node at 0x%08x: %d\n",
     778                 :            :                         ref_offset(ref), ret);
     779                 :            :                 goto out_erase_sem;
     780                 :            :         }
     781                 :            :         if (retlen != sizeof(n)) {
     782                 :            :                 pr_warn("Short write in obliterating obsoleted node at 0x%08x: %zd\n",
     783                 :            :                         ref_offset(ref), retlen);
     784                 :            :                 goto out_erase_sem;
     785                 :            :         }
     786                 :            : 
     787                 :            :         /* Nodes which have been marked obsolete no longer need to be
     788                 :            :            associated with any inode. Remove them from the per-inode list.
     789                 :            : 
     790                 :            :            Note we can't do this for NAND at the moment because we need
     791                 :            :            obsolete dirent nodes to stay on the lists, because of the
     792                 :            :            horridness in jffs2_garbage_collect_deletion_dirent(). Also
     793                 :            :            because we delete the inocache, and on NAND we need that to
     794                 :            :            stay around until all the nodes are actually erased, in order
     795                 :            :            to stop us from giving the same inode number to another newly
     796                 :            :            created inode. */
     797                 :            :         if (ref->next_in_ino) {
     798                 :            :                 struct jffs2_inode_cache *ic;
     799                 :            :                 struct jffs2_raw_node_ref **p;
     800                 :            : 
     801                 :            :                 spin_lock(&c->erase_completion_lock);
     802                 :            : 
     803                 :            :                 ic = jffs2_raw_ref_to_ic(ref);
     804                 :            :                 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
     805                 :            :                         ;
     806                 :            : 
     807                 :            :                 *p = ref->next_in_ino;
     808                 :            :                 ref->next_in_ino = NULL;
     809                 :            : 
     810                 :            :                 switch (ic->class) {
     811                 :            : #ifdef CONFIG_JFFS2_FS_XATTR
     812                 :            :                         case RAWNODE_CLASS_XATTR_DATUM:
     813                 :            :                                 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
     814                 :            :                                 break;
     815                 :            :                         case RAWNODE_CLASS_XATTR_REF:
     816                 :            :                                 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
     817                 :            :                                 break;
     818                 :            : #endif
     819                 :            :                         default:
     820                 :            :                                 if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
     821                 :            :                                         jffs2_del_ino_cache(c, ic);
     822                 :            :                                 break;
     823                 :            :                 }
     824                 :            :                 spin_unlock(&c->erase_completion_lock);
     825                 :            :         }
     826                 :            : 
     827                 :            :  out_erase_sem:
     828                 :            :         mutex_unlock(&c->erase_free_sem);
     829                 :            : }
     830                 :            : 
     831                 :          0 : int jffs2_thread_should_wake(struct jffs2_sb_info *c)
     832                 :            : {
     833                 :            :         int ret = 0;
     834                 :            :         uint32_t dirty;
     835                 :            :         int nr_very_dirty = 0;
     836                 :            :         struct jffs2_eraseblock *jeb;
     837                 :            : 
     838 [ #  # ][ #  # ]:          0 :         if (!list_empty(&c->erase_complete_list) ||
     839                 :          0 :             !list_empty(&c->erase_pending_list))
     840                 :            :                 return 1;
     841                 :            : 
     842         [ #  # ]:          0 :         if (c->unchecked_size) {
     843                 :            :                 jffs2_dbg(1, "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n",
     844                 :            :                           c->unchecked_size, c->checked_ino);
     845                 :            :                 return 1;
     846                 :            :         }
     847                 :            : 
     848                 :            :         /* dirty_size contains blocks on erase_pending_list
     849                 :            :          * those blocks are counted in c->nr_erasing_blocks.
     850                 :            :          * If one block is actually erased, it is not longer counted as dirty_space
     851                 :            :          * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
     852                 :            :          * with c->nr_erasing_blocks * c->sector_size again.
     853                 :            :          * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
     854                 :            :          * This helps us to force gc and pick eventually a clean block to spread the load.
     855                 :            :          */
     856                 :          0 :         dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size;
     857                 :            : 
     858 [ #  # ][ #  # ]:          0 :         if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger &&
     859                 :          0 :                         (dirty > c->nospc_dirty_size))
     860                 :            :                 ret = 1;
     861                 :            : 
     862         [ #  # ]:          0 :         list_for_each_entry(jeb, &c->very_dirty_list, list) {
     863                 :          0 :                 nr_very_dirty++;
     864         [ #  # ]:          0 :                 if (nr_very_dirty == c->vdirty_blocks_gctrigger) {
     865                 :            :                         ret = 1;
     866                 :            :                         /* In debug mode, actually go through and count them all */
     867                 :            :                         D1(continue);
     868                 :            :                         break;
     869                 :            :                 }
     870                 :            :         }
     871                 :            : 
     872                 :            :         jffs2_dbg(1, "%s(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n",
     873                 :            :                   __func__, c->nr_free_blocks, c->nr_erasing_blocks,
     874                 :            :                   c->dirty_size, nr_very_dirty, ret ? "yes" : "no");
     875                 :            : 
     876                 :          0 :         return ret;
     877                 :            : }

Generated by: LCOV version 1.9