The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/jffs/jffs_fm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * JFFS -- Journaling Flash File System, Linux implementation.
    3  *
    4  * Copyright (C) 1999, 2000  Axis Communications AB.
    5  *
    6  * Created by Finn Hakansson <finn@axis.com>.
    7  *
    8  * This is free software; you can redistribute it and/or modify it
    9  * under the terms of the GNU General Public License as published by
   10  * the Free Software Foundation; either version 2 of the License, or
   11  * (at your option) any later version.
   12  *
   13  * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
   14  *
   15  * Ported to Linux 2.3.x and MTD:
   16  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
   17  *
   18  */
   19 #define __NO_VERSION__
   20 #include <linux/slab.h>
   21 #include <linux/blkdev.h>
   22 #include <linux/jffs.h>
   23 #include "jffs_fm.h"
   24 
   25 #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
   26 static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
   27 #endif
   28 
   29 extern kmem_cache_t     *fm_cache;
   30 extern kmem_cache_t     *node_cache;
   31 
   32 /* This function creates a new shiny flash memory control structure.  */
   33 struct jffs_fmcontrol *
   34 jffs_build_begin(struct jffs_control *c, kdev_t dev)
   35 {
   36         struct jffs_fmcontrol *fmc;
   37         struct mtd_info *mtd;
   38         
   39         D3(printk("jffs_build_begin()\n"));
   40         fmc = (struct jffs_fmcontrol *)kmalloc(sizeof(struct jffs_fmcontrol),
   41                                                GFP_KERNEL);
   42         if (!fmc) {
   43                 D(printk("jffs_build_begin(): Allocation of "
   44                          "struct jffs_fmcontrol failed!\n"));
   45                 return (struct jffs_fmcontrol *)0;
   46         }
   47         DJM(no_jffs_fmcontrol++);
   48 
   49         mtd = get_mtd_device(NULL, MINOR(dev));
   50 
   51         if (!mtd) {
   52                 kfree(fmc);
   53                 DJM(no_jffs_fmcontrol--);
   54                 return NULL;
   55         }
   56         
   57         /* Retrieve the size of the flash memory.  */
   58         fmc->flash_size = mtd->size;
   59         D3(printk("  fmc->flash_size = %d bytes\n", fmc->flash_size));
   60 
   61         fmc->used_size = 0;
   62         fmc->dirty_size = 0;
   63         fmc->free_size = mtd->size;
   64         fmc->sector_size = mtd->erasesize;
   65         fmc->max_chunk_size = fmc->sector_size >> 1;
   66         /* min_free_size:
   67            1 sector, obviously.
   68            + 1 x max_chunk_size, for when a nodes overlaps the end of a sector
   69            + 1 x max_chunk_size again, which ought to be enough to handle 
   70                    the case where a rename causes a name to grow, and GC has
   71                    to write out larger nodes than the ones it's obsoleting.
   72                    We should fix it so it doesn't have to write the name
   73                    _every_ time. Later.
   74            + another 2 sectors because people keep getting GC stuck and
   75                    we don't know why. This scares me - I want formal proof
   76                    of correctness of whatever number we put here. dwmw2.
   77         */
   78         fmc->min_free_size = fmc->sector_size << 2;
   79         fmc->mtd = mtd;
   80         fmc->c = c;
   81         fmc->head = 0;
   82         fmc->tail = 0;
   83         fmc->head_extra = 0;
   84         fmc->tail_extra = 0;
   85         init_MUTEX(&fmc->biglock);
   86         return fmc;
   87 }
   88 
   89 
   90 /* When the flash memory scan has completed, this function should be called
   91    before use of the control structure.  */
   92 void
   93 jffs_build_end(struct jffs_fmcontrol *fmc)
   94 {
   95         D3(printk("jffs_build_end()\n"));
   96 
   97         if (!fmc->head) {
   98                 fmc->head = fmc->head_extra;
   99                 fmc->tail = fmc->tail_extra;
  100         }
  101         else if (fmc->head_extra) {
  102                 fmc->tail_extra->next = fmc->head;
  103                 fmc->head->prev = fmc->tail_extra;
  104                 fmc->head = fmc->head_extra;
  105         }
  106         fmc->head_extra = 0; /* These two instructions should be omitted.  */
  107         fmc->tail_extra = 0;
  108         D3(jffs_print_fmcontrol(fmc));
  109 }
  110 
  111 
  112 /* Call this function when the file system is unmounted.  This function
  113    frees all memory used by this module.  */
  114 void
  115 jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc)
  116 {
  117         if (fmc) {
  118                 struct jffs_fm *cur;
  119                 struct jffs_fm *next = fmc->head;
  120 
  121                 while ((cur = next)) {
  122                         next = next->next;
  123                         jffs_free_fm(cur);
  124                 }
  125                 put_mtd_device(fmc->mtd);
  126                 kfree(fmc);
  127                 DJM(no_jffs_fmcontrol--);
  128         }
  129 }
  130 
  131 
  132 /* This function returns the size of the first chunk of free space on the
  133    flash memory.  This function will return something nonzero if the flash
  134    memory contains any free space.  */
  135 __u32
  136 jffs_free_size1(struct jffs_fmcontrol *fmc)
  137 {
  138         __u32 head;
  139         __u32 tail;
  140         __u32 end = fmc->flash_size;
  141 
  142         if (!fmc->head) {
  143                 /* There is nothing on the flash.  */
  144                 return fmc->flash_size;
  145         }
  146 
  147         /* Compute the beginning and ending of the contents of the flash.  */
  148         head = fmc->head->offset;
  149         tail = fmc->tail->offset + fmc->tail->size;
  150         if (tail == end) {
  151                 tail = 0;
  152         }
  153         ASSERT(else if (tail > end) {
  154                 printk(KERN_WARNING "jffs_free_size1(): tail > end\n");
  155                 tail = 0;
  156         });
  157 
  158         if (head <= tail) {
  159                 return end - tail;
  160         }
  161         else {
  162                 return head - tail;
  163         }
  164 }
  165 
  166 /* This function will return something nonzero in case there are two free
  167    areas on the flash.  Like this:
  168 
  169      +----------------+------------------+----------------+
  170      |     FREE 1     |   USED / DIRTY   |     FREE 2     |
  171      +----------------+------------------+----------------+
  172        fmc->head -----^
  173        fmc->tail ------------------------^
  174 
  175    The value returned, will be the size of the first empty area on the
  176    flash, in this case marked "FREE 1".  */
  177 __u32
  178 jffs_free_size2(struct jffs_fmcontrol *fmc)
  179 {
  180         if (fmc->head) {
  181                 __u32 head = fmc->head->offset;
  182                 __u32 tail = fmc->tail->offset + fmc->tail->size;
  183                 if (tail == fmc->flash_size) {
  184                         tail = 0;
  185                 }
  186 
  187                 if (tail >= head) {
  188                         return head;
  189                 }
  190         }
  191         return 0;
  192 }
  193 
  194 
  195 /* Allocate a chunk of flash memory.  If there is enough space on the
  196    device, a reference to the associated node is stored in the jffs_fm
  197    struct.  */
  198 int
  199 jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
  200              struct jffs_fm **result)
  201 {
  202         struct jffs_fm *fm;
  203         __u32 free_chunk_size1;
  204         __u32 free_chunk_size2;
  205 
  206         D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, "
  207                   "node = 0x%p\n", fmc, size, node));
  208 
  209         *result = 0;
  210 
  211         if (!(fm = jffs_alloc_fm())) {
  212                 D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n"));
  213                 return -ENOMEM;
  214         }
  215 
  216         free_chunk_size1 = jffs_free_size1(fmc);
  217         free_chunk_size2 = jffs_free_size2(fmc);
  218         if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
  219                 printk(KERN_WARNING "Free size accounting screwed\n");
  220                 printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
  221         }
  222 
  223         D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
  224                   "free_chunk_size2 = %u\n",
  225                   free_chunk_size1, free_chunk_size2));
  226 
  227         if (size <= free_chunk_size1) {
  228                 if (!(fm->nodes = (struct jffs_node_ref *)
  229                                   kmalloc(sizeof(struct jffs_node_ref),
  230                                           GFP_KERNEL))) {
  231                         D(printk("jffs_fmalloc(): kmalloc() failed! "
  232                                  "(node_ref)\n"));
  233                         jffs_free_fm(fm);
  234                         return -ENOMEM;
  235                 }
  236                 DJM(no_jffs_node_ref++);
  237                 fm->nodes->node = node;
  238                 fm->nodes->next = 0;
  239                 if (fmc->tail) {
  240                         fm->offset = fmc->tail->offset + fmc->tail->size;
  241                         if (fm->offset == fmc->flash_size) {
  242                                 fm->offset = 0;
  243                         }
  244                         ASSERT(else if (fm->offset > fmc->flash_size) {
  245                                 printk(KERN_WARNING "jffs_fmalloc(): "
  246                                        "offset > flash_end\n");
  247                                 fm->offset = 0;
  248                         });
  249                 }
  250                 else {
  251                         /* There don't have to be files in the file
  252                            system yet.  */
  253                         fm->offset = 0;
  254                 }
  255                 fm->size = size;
  256                 fmc->free_size -= size;
  257                 fmc->used_size += size;
  258         }
  259         else if (size > free_chunk_size2) {
  260                 printk(KERN_WARNING "JFFS: Tried to allocate a too "
  261                        "large flash memory chunk. (size = %u)\n", size);
  262                 jffs_free_fm(fm);
  263                 return -ENOSPC;
  264         }
  265         else {
  266                 fm->offset = fmc->tail->offset + fmc->tail->size;
  267                 fm->size = free_chunk_size1;
  268                 fm->nodes = 0;
  269                 fmc->free_size -= fm->size;
  270                 fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a 
  271                                                 bug that caused infinite garbage collection.
  272                                                 It previously set fmc->dirty_size to size (which is the
  273                                                 size of the requested chunk).
  274                                              */
  275         }
  276 
  277         fm->next = 0;
  278         if (!fmc->head) {
  279                 fm->prev = 0;
  280                 fmc->head = fm;
  281                 fmc->tail = fm;
  282         }
  283         else {
  284                 fm->prev = fmc->tail;
  285                 fmc->tail->next = fm;
  286                 fmc->tail = fm;
  287         }
  288 
  289         D3(jffs_print_fmcontrol(fmc));
  290         D3(jffs_print_fm(fm));
  291         *result = fm;
  292         return 0;
  293 }
  294 
  295 
  296 /* The on-flash space is not needed anymore by the passed node.  Remove
  297    the reference to the node from the node list.  If the data chunk in
  298    the flash memory isn't used by any more nodes anymore (fm->nodes == 0),
  299    then mark that chunk as dirty.  */
  300 int
  301 jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node)
  302 {
  303         struct jffs_node_ref *ref;
  304         struct jffs_node_ref *prev;
  305         ASSERT(int del = 0);
  306 
  307         D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n",
  308                  node->ino, node->version));
  309 
  310         ASSERT(if (!fmc || !fm || !fm->nodes) {
  311                 printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, "
  312                        "fm->nodes: 0x%p\n",
  313                        fmc, fm, (fm ? fm->nodes : 0));
  314                 return -1;
  315         });
  316 
  317         /* Find the reference to the node that is going to be removed
  318            and remove it.  */
  319         for (ref = fm->nodes, prev = 0; ref; ref = ref->next) {
  320                 if (ref->node == node) {
  321                         if (prev) {
  322                                 prev->next = ref->next;
  323                         }
  324                         else {
  325                                 fm->nodes = ref->next;
  326                         }
  327                         kfree(ref);
  328                         DJM(no_jffs_node_ref--);
  329                         ASSERT(del = 1);
  330                         break;
  331                 }
  332                 prev = ref;
  333         }
  334 
  335         /* If the data chunk in the flash memory isn't used anymore
  336            just mark it as obsolete.  */
  337         if (!fm->nodes) {
  338                 /* No node uses this chunk so let's remove it.  */
  339                 fmc->used_size -= fm->size;
  340                 fmc->dirty_size += fm->size;
  341 #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
  342                 if (jffs_mark_obsolete(fmc, fm->offset) < 0) {
  343                         D1(printk("jffs_fmfree(): Failed to mark an on-flash "
  344                                   "node obsolete!\n"));
  345                         return -1;
  346                 }
  347 #endif
  348         }
  349 
  350         ASSERT(if (!del) {
  351                 printk(KERN_WARNING "***jffs_fmfree(): "
  352                        "Didn't delete any node reference!\n");
  353         });
  354 
  355         return 0;
  356 }
  357 
  358 
  359 /* This allocation function is used during the initialization of
  360    the file system.  */
  361 struct jffs_fm *
  362 jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
  363                struct jffs_node *node)
  364 {
  365         struct jffs_fm *fm;
  366 
  367         D3(printk("jffs_fmalloced()\n"));
  368 
  369         if (!(fm = jffs_alloc_fm())) {
  370                 D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n",
  371                          fmc, offset, size, node));
  372                 return 0;
  373         }
  374         fm->offset = offset;
  375         fm->size = size;
  376         fm->prev = 0;
  377         fm->next = 0;
  378         fm->nodes = 0;
  379         if (node) {
  380                 /* `node' exists and it should be associated with the
  381                     jffs_fm structure `fm'.  */
  382                 if (!(fm->nodes = (struct jffs_node_ref *)
  383                                   kmalloc(sizeof(struct jffs_node_ref),
  384                                           GFP_KERNEL))) {
  385                         D(printk("jffs_fmalloced(): !fm->nodes\n"));
  386                         jffs_free_fm(fm);
  387                         return 0;
  388                 }
  389                 DJM(no_jffs_node_ref++);
  390                 fm->nodes->node = node;
  391                 fm->nodes->next = 0;
  392                 fmc->used_size += size;
  393                 fmc->free_size -= size;
  394         }
  395         else {
  396                 /* If there is no node, then this is just a chunk of dirt.  */
  397                 fmc->dirty_size += size;
  398                 fmc->free_size -= size;
  399         }
  400 
  401         if (fmc->head_extra) {
  402                 fm->prev = fmc->tail_extra;
  403                 fmc->tail_extra->next = fm;
  404                 fmc->tail_extra = fm;
  405         }
  406         else if (!fmc->head) {
  407                 fmc->head = fm;
  408                 fmc->tail = fm;
  409         }
  410         else if (fmc->tail->offset + fmc->tail->size < offset) {
  411                 fmc->head_extra = fm;
  412                 fmc->tail_extra = fm;
  413         }
  414         else {
  415                 fm->prev = fmc->tail;
  416                 fmc->tail->next = fm;
  417                 fmc->tail = fm;
  418         }
  419         D3(jffs_print_fmcontrol(fmc));
  420         D3(jffs_print_fm(fm));
  421         return fm;
  422 }
  423 
  424 
  425 /* Add a new node to an already existing jffs_fm struct.  */
  426 int
  427 jffs_add_node(struct jffs_node *node)
  428 {
  429         struct jffs_node_ref *ref;
  430 
  431         D3(printk("jffs_add_node(): ino = %u\n", node->ino));
  432 
  433         ref = (struct jffs_node_ref *)kmalloc(sizeof(struct jffs_node_ref),
  434                                               GFP_KERNEL);
  435         if (!ref)
  436                 return -ENOMEM;
  437 
  438         DJM(no_jffs_node_ref++);
  439         ref->node = node;
  440         ref->next = node->fm->nodes;
  441         node->fm->nodes = ref;
  442         return 0;
  443 }
  444 
  445 
  446 /* Free a part of some allocated space.  */
  447 void
  448 jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size)
  449 {
  450         D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, "
  451                   "fm->nodes->node->ino = %u, size = %u\n",
  452                   fm, (fm ? fm->nodes : 0),
  453                   (!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size));
  454 
  455         if (fm->nodes) {
  456                 kfree(fm->nodes);
  457                 DJM(no_jffs_node_ref--);
  458                 fm->nodes = 0;
  459         }
  460         fmc->used_size -= fm->size;
  461         if (fm == fmc->tail) {
  462                 fm->size -= size;
  463                 fmc->free_size += size;
  464         }
  465         fmc->dirty_size += fm->size;
  466 }
  467 
  468 
  469 /* Find the jffs_fm struct that contains the end of the data chunk that
  470    begins at the logical beginning of the flash memory and spans `size'
  471    bytes.  If we want to erase a sector of the flash memory, we use this
  472    function to find where the sector limit cuts a chunk of data.  */
  473 struct jffs_fm *
  474 jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size)
  475 {
  476         struct jffs_fm *fm;
  477         __u32 pos = 0;
  478 
  479         if (size == 0) {
  480                 return 0;
  481         }
  482 
  483         ASSERT(if (!fmc) {
  484                 printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n");
  485                 return 0;
  486         });
  487 
  488         fm = fmc->head;
  489 
  490         while (fm) {
  491                 pos += fm->size;
  492                 if (pos < size) {
  493                         fm = fm->next;
  494                 }
  495                 else if (pos > size) {
  496                         break;
  497                 }
  498                 else {
  499                         fm = 0;
  500                         break;
  501                 }
  502         }
  503 
  504         return fm;
  505 }
  506 
  507 
  508 /* Move the head of the fmc structures and delete the obsolete parts.  */
  509 void
  510 jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
  511 {
  512         struct jffs_fm *fm;
  513         struct jffs_fm *del;
  514 
  515         ASSERT(if (!fmc) {
  516                 printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n");
  517                 return;
  518         });
  519 
  520         fmc->dirty_size -= erased_size;
  521         fmc->free_size += erased_size;
  522 
  523         for (fm = fmc->head; fm && (erased_size > 0);) {
  524                 if (erased_size >= fm->size) {
  525                         erased_size -= fm->size;
  526                         del = fm;
  527                         fm = fm->next;
  528                         fm->prev = 0;
  529                         fmc->head = fm;
  530                         jffs_free_fm(del);
  531                 }
  532                 else {
  533                         fm->size -= erased_size;
  534                         fm->offset += erased_size;
  535                         break;
  536                 }
  537         }
  538 }
  539 
  540 
  541 /* Return the oldest used node in the flash memory.  */
  542 struct jffs_node *
  543 jffs_get_oldest_node(struct jffs_fmcontrol *fmc)
  544 {
  545         struct jffs_fm *fm;
  546         struct jffs_node_ref *nref;
  547         struct jffs_node *node = 0;
  548 
  549         ASSERT(if (!fmc) {
  550                 printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n");
  551                 return 0;
  552         });
  553 
  554         for (fm = fmc->head; fm && !fm->nodes; fm = fm->next);
  555 
  556         if (!fm) {
  557                 return 0;
  558         }
  559 
  560         /* The oldest node is the last one in the reference list.  This list
  561            shouldn't be too long; just one or perhaps two elements.  */
  562         for (nref = fm->nodes; nref; nref = nref->next) {
  563                 node = nref->node;
  564         }
  565 
  566         D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n",
  567                   (node ? node->ino : 0), (node ? node->version : 0)));
  568 
  569         return node;
  570 }
  571 
  572 
  573 #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
  574 
  575 /* Mark an on-flash node as obsolete.
  576 
  577    Note that this is just an optimization that isn't necessary for the
  578    filesystem to work.  */
  579 
  580 static int
  581 jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
  582 {
  583         /* The `accurate_pos' holds the position of the accurate byte
  584            in the jffs_raw_inode structure that we are going to mark
  585            as obsolete.  */
  586         __u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET;
  587         unsigned char zero = 0x00;
  588         size_t len;
  589 
  590         D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos));
  591         ASSERT(if (!fmc) {
  592                 printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n");
  593                 return -1;
  594         });
  595 
  596         /* Write 0x00 to the raw inode's accurate member.  Don't care
  597            about the return value.  */
  598         MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero);
  599         return 0;
  600 }
  601 
  602 #endif /* JFFS_MARK_OBSOLETE  */
  603 
  604 /* check if it's possible to erase the wanted range, and if not, return
  605  * the range that IS erasable, or a negative error code.
  606  */
  607 long
  608 jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
  609 {
  610          u_long ssize;
  611 
  612         /* assume that sector size for a partition is constant even
  613          * if it spans more than one chip (you usually put the same
  614          * type of chips in a system)
  615          */
  616 
  617         ssize = mtd->erasesize;
  618 
  619         if (offset % ssize) {
  620                 printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
  621                 /* The offset is not sector size aligned.  */
  622                 return -1;
  623         }
  624         else if (offset > mtd->size) {
  625                 printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size);
  626                 return -2;
  627         }
  628         else if (offset + size > mtd->size) {
  629                 printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size);
  630                 return -3;
  631         }
  632 
  633         return (size / ssize) * ssize;
  634 }
  635 
  636 
  637 /* How much dirty flash memory is possible to erase at the moment?  */
  638 long
  639 jffs_erasable_size(struct jffs_fmcontrol *fmc)
  640 {
  641         struct jffs_fm *fm;
  642         __u32 size = 0;
  643         long ret;
  644 
  645         ASSERT(if (!fmc) {
  646                 printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n");
  647                 return -1;
  648         });
  649 
  650         if (!fmc->head) {
  651                 /* The flash memory is totally empty. No nodes. No dirt.
  652                    Just return.  */
  653                 return 0;
  654         }
  655 
  656         /* Calculate how much space that is dirty.  */
  657         for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) {
  658                 if (size && fm->offset == 0) {
  659                         /* We have reached the beginning of the flash.  */
  660                         break;
  661                 }
  662                 size += fm->size;
  663         }
  664 
  665         /* Someone's signature contained this:
  666            There's a fine line between fishing and just standing on
  667            the shore like an idiot...  */
  668         ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size);
  669 
  670         ASSERT(if (ret < 0) {
  671                 printk("jffs_erasable_size: flash_erasable_size() "
  672                        "returned something less than zero (%ld).\n", ret);
  673                 printk("jffs_erasable_size: offset = 0x%08x\n",
  674                        fmc->head->offset);
  675         });
  676 
  677         /* If there is dirt on the flash (which is the reason to why
  678            this function was called in the first place) but no space is
  679            possible to erase right now, the initial part of the list of
  680            jffs_fm structs, that hold place for dirty space, could perhaps
  681            be shortened.  The list's initial "dirty" elements are merged
  682            into just one large dirty jffs_fm struct.  This operation must
  683            only be performed if nothing is possible to erase.  Otherwise,
  684            jffs_clear_end_of_node() won't work as expected.  */
  685         if (ret == 0) {
  686                 struct jffs_fm *head = fmc->head;
  687                 struct jffs_fm *del;
  688                 /* While there are two dirty nodes beside each other.*/
  689                 while (head->nodes == 0
  690                        && head->next
  691                        && head->next->nodes == 0) {
  692                         del = head->next;
  693                         head->size += del->size;
  694                         head->next = del->next;
  695                         if (del->next) {
  696                                 del->next->prev = head;
  697                         }
  698                         jffs_free_fm(del);
  699                 }
  700         }
  701 
  702         return (ret >= 0 ? ret : 0);
  703 }
  704 
  705 struct jffs_fm *jffs_alloc_fm(void)
  706 {
  707         struct jffs_fm *fm;
  708 
  709         fm = kmem_cache_alloc(fm_cache,GFP_KERNEL);
  710         DJM(if (fm) no_jffs_fm++;);
  711         
  712         return fm;
  713 }
  714 
  715 void jffs_free_fm(struct jffs_fm *n)
  716 {
  717         kmem_cache_free(fm_cache,n);
  718         DJM(no_jffs_fm--);
  719 }
  720 
  721 
  722 
  723 struct jffs_node *jffs_alloc_node(void)
  724 {
  725         struct jffs_node *n;
  726 
  727         n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL);
  728         if(n != NULL)
  729                 no_jffs_node++;
  730         return n;
  731 }
  732 
  733 void jffs_free_node(struct jffs_node *n)
  734 {
  735         kmem_cache_free(node_cache,n);
  736         no_jffs_node--;
  737 }
  738 
  739 
  740 int jffs_get_node_inuse(void)
  741 {
  742         return no_jffs_node;
  743 }
  744 
  745 void
  746 jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
  747 {
  748         D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
  749         D(printk("{\n"));
  750         D(printk("        %u, /* flash_size  */\n", fmc->flash_size));
  751         D(printk("        %u, /* used_size  */\n", fmc->used_size));
  752         D(printk("        %u, /* dirty_size  */\n", fmc->dirty_size));
  753         D(printk("        %u, /* free_size  */\n", fmc->free_size));
  754         D(printk("        %u, /* sector_size  */\n", fmc->sector_size));
  755         D(printk("        %u, /* min_free_size  */\n", fmc->min_free_size));
  756         D(printk("        %u, /* max_chunk_size  */\n", fmc->max_chunk_size));
  757         D(printk("        0x%p, /* mtd  */\n", fmc->mtd));
  758         D(printk("        0x%p, /* head  */    "
  759                  "(head->offset = 0x%08x)\n",
  760                  fmc->head, (fmc->head ? fmc->head->offset : 0)));
  761         D(printk("        0x%p, /* tail  */    "
  762                  "(tail->offset + tail->size = 0x%08x)\n",
  763                  fmc->tail,
  764                  (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
  765         D(printk("        0x%p, /* head_extra  */\n", fmc->head_extra));
  766         D(printk("        0x%p, /* tail_extra  */\n", fmc->tail_extra));
  767         D(printk("}\n"));
  768 }
  769 
  770 void
  771 jffs_print_fm(struct jffs_fm *fm)
  772 {
  773         D(printk("struct jffs_fm: 0x%p\n", fm));
  774         D(printk("{\n"));
  775         D(printk("       0x%08x, /* offset  */\n", fm->offset));
  776         D(printk("       %u, /* size  */\n", fm->size));
  777         D(printk("       0x%p, /* prev  */\n", fm->prev));
  778         D(printk("       0x%p, /* next  */\n", fm->next));
  779         D(printk("       0x%p, /* nodes  */\n", fm->nodes));
  780         D(printk("}\n"));
  781 }
  782 
  783 void
  784 jffs_print_node_ref(struct jffs_node_ref *ref)
  785 {
  786         D(printk("struct jffs_node_ref: 0x%p\n", ref));
  787         D(printk("{\n"));
  788         D(printk("       0x%p, /* node  */\n", ref->node));
  789         D(printk("       0x%p, /* next  */\n", ref->next));
  790         D(printk("}\n"));
  791 }

Cache object: 225b4ec8b93bcf7d016ae589656d7081


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.