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/jffs2/readinode.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  * JFFS2 -- Journalling Flash File System, Version 2.
    3  *
    4  * Copyright (C) 2001 Red Hat, Inc.
    5  *
    6  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
    7  *
    8  * The original JFFS, from which the design for JFFS2 was derived,
    9  * was designed and implemented by Axis Communications AB.
   10  *
   11  * The contents of this file are subject to the Red Hat eCos Public
   12  * License Version 1.1 (the "Licence"); you may not use this file
   13  * except in compliance with the Licence.  You may obtain a copy of
   14  * the Licence at http://www.redhat.com/
   15  *
   16  * Software distributed under the Licence is distributed on an "AS IS"
   17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
   18  * See the Licence for the specific language governing rights and
   19  * limitations under the Licence.
   20  *
   21  * The Original Code is JFFS2 - Journalling Flash File System, version 2
   22  *
   23  * Alternatively, the contents of this file may be used under the
   24  * terms of the GNU General Public License version 2 (the "GPL"), in
   25  * which case the provisions of the GPL are applicable instead of the
   26  * above.  If you wish to allow the use of your version of this file
   27  * only under the terms of the GPL and not to allow others to use your
   28  * version of this file under the RHEPL, indicate your decision by
   29  * deleting the provisions above and replace them with the notice and
   30  * other provisions required by the GPL.  If you do not delete the
   31  * provisions above, a recipient may use your version of this file
   32  * under either the RHEPL or the GPL.
   33  *
   34  * $Id: readinode.c,v 1.58.2.6 2002/10/10 13:18:38 dwmw2 Exp $
   35  *
   36  */
   37 
   38 /* Given an inode, probably with existing list of fragments, add the new node
   39  * to the fragment list.
   40  */
   41 #include <linux/kernel.h>
   42 #include <linux/slab.h>
   43 #include <linux/fs.h>
   44 #include <linux/mtd/mtd.h>
   45 #include <linux/jffs2.h>
   46 #include "nodelist.h"
   47 #include <linux/crc32.h>
   48 
   49 
   50 D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)
   51 {
   52         struct jffs2_node_frag *this = f->fraglist;
   53 
   54         while(this) {
   55                 if (this->node)
   56                         printk(KERN_DEBUG "frag %04x-%04x: 0x%08x on flash (*%p->%p)\n", this->ofs, this->ofs+this->size, this->node->raw->flash_offset &~3, this, this->next);
   57                 else 
   58                         printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)\n", this->ofs, this->ofs+this->size, this, this->next);
   59                 this = this->next;
   60         }
   61         if (f->metadata) {
   62                 printk(KERN_DEBUG "metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3);
   63         }
   64 })
   65 
   66 
   67 int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
   68 {
   69         int ret;
   70         D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn));
   71 
   72         ret = jffs2_add_full_dnode_to_fraglist(c, &f->fraglist, fn);
   73 
   74         D2(jffs2_print_frag_list(f));
   75         return ret;
   76 }
   77 
   78 static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
   79 {
   80         if (this->node) {
   81                 this->node->frags--;
   82                 if (!this->node->frags) {
   83                         /* The node has no valid frags left. It's totally obsoleted */
   84                         D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",
   85                                   this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size));
   86                         jffs2_mark_node_obsolete(c, this->node->raw);
   87                         jffs2_free_full_dnode(this->node);
   88                 } else {
   89                         D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %d\n",
   90                                   this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size,
   91                                   this->node->frags));
   92                 }
   93                 
   94         }
   95         jffs2_free_node_frag(this);
   96 }
   97 
   98 /* Doesn't set inode->i_size */
   99 int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn)
  100 {
  101         
  102         struct jffs2_node_frag *this, **prev, *old;
  103         struct jffs2_node_frag *newfrag, *newfrag2;
  104         __u32 lastend = 0;
  105 
  106 
  107         newfrag = jffs2_alloc_node_frag();
  108         if (!newfrag) {
  109                 return -ENOMEM;
  110         }
  111 
  112         D2(if (fn->raw)
  113                 printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, fn->raw->flash_offset &~3, newfrag);
  114         else
  115                 printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag));
  116         
  117         prev = list;
  118         this = *list;
  119 
  120         if (!fn->size) {
  121                 jffs2_free_node_frag(newfrag);
  122                 return 0;
  123         }
  124 
  125         newfrag->ofs = fn->ofs;
  126         newfrag->size = fn->size;
  127         newfrag->node = fn;
  128         newfrag->node->frags = 1;
  129         newfrag->next = (void *)0xdeadbeef;
  130 
  131         /* Skip all the nodes which are completed before this one starts */
  132         while(this && fn->ofs >= this->ofs+this->size) {
  133                 lastend = this->ofs + this->size;
  134 
  135                 D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", 
  136                           this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next));
  137                 prev = &this->next;
  138                 this = this->next;
  139         }
  140 
  141         /* See if we ran off the end of the list */
  142         if (!this) {
  143                 /* We did */
  144                 if (lastend < fn->ofs) {
  145                         /* ... and we need to put a hole in before the new node */
  146                         struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();
  147                         if (!holefrag)
  148                                 return -ENOMEM;
  149                         holefrag->ofs = lastend;
  150                         holefrag->size = fn->ofs - lastend;
  151                         holefrag->next = NULL;
  152                         holefrag->node = NULL;
  153                         *prev = holefrag;
  154                         prev = &holefrag->next;
  155                 }
  156                 newfrag->next = NULL;
  157                 *prev = newfrag;
  158                 return 0;
  159         }
  160 
  161         D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n", 
  162                   this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next));
  163 
  164         /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes,
  165          * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs  
  166          */
  167         if (fn->ofs > this->ofs) {
  168                 /* This node isn't completely obsoleted. The start of it remains valid */
  169                 if (this->ofs + this->size > fn->ofs + fn->size) {
  170                         /* The new node splits 'this' frag into two */
  171                         newfrag2 = jffs2_alloc_node_frag();
  172                         if (!newfrag2) {
  173                                 jffs2_free_node_frag(newfrag);
  174                                 return -ENOMEM;
  175                         }
  176                         D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size);
  177                         if (this->node)
  178                                 printk("phys 0x%08x\n", this->node->raw->flash_offset &~3);
  179                         else 
  180                                 printk("hole\n");
  181                            )
  182                         newfrag2->ofs = fn->ofs + fn->size;
  183                         newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;
  184                         newfrag2->next = this->next;
  185                         newfrag2->node = this->node;
  186                         if (this->node)
  187                                 this->node->frags++;
  188                         newfrag->next = newfrag2;
  189                         this->next = newfrag;
  190                         this->size = newfrag->ofs - this->ofs;
  191                         return 0;
  192                 }
  193                 /* New node just reduces 'this' frag in size, doesn't split it */
  194                 this->size = fn->ofs - this->ofs;
  195                 newfrag->next = this->next;
  196                 this->next = newfrag;
  197                 this = newfrag->next;
  198         } else {
  199                 D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)\n", newfrag, this));
  200                 *prev = newfrag;
  201                 newfrag->next = this;
  202         }
  203         /* OK, now we have newfrag added in the correct place in the list, but
  204            newfrag->next points to a fragment which may be overlapping it
  205         */
  206         while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
  207                 /* 'this' frag is obsoleted. */
  208                 old = this;
  209                 this = old->next;
  210                 jffs2_obsolete_node_frag(c, old);
  211         }
  212         /* Now we're pointing at the first frag which isn't totally obsoleted by 
  213            the new frag */
  214         newfrag->next = this;
  215 
  216         if (!this || newfrag->ofs + newfrag->size == this->ofs) {
  217                 return 0;
  218         }
  219         /* Still some overlap */
  220         this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
  221         this->ofs = newfrag->ofs + newfrag->size;
  222         return 0;
  223 }
  224 
  225 void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size)
  226 {
  227         D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size));
  228 
  229         while (*list) {
  230                 if ((*list)->ofs >= size) {
  231                         struct jffs2_node_frag *this = *list;
  232                         *list = this->next;
  233                         D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", this->ofs, this->ofs+this->size));
  234                         jffs2_obsolete_node_frag(c, this);
  235                         continue;
  236                 } else if ((*list)->ofs + (*list)->size > size) {
  237                         D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", (*list)->ofs, (*list)->ofs + (*list)->size));
  238                         (*list)->size = size - (*list)->ofs;
  239                 }
  240                 list = &(*list)->next;
  241         }
  242 }
  243 
  244 /* Scan the list of all nodes present for this ino, build map of versions, etc. */
  245 
  246 void jffs2_read_inode (struct inode *inode)
  247 {
  248         struct jffs2_tmp_dnode_info *tn_list, *tn;
  249         struct jffs2_full_dirent *fd_list;
  250         struct jffs2_inode_info *f;
  251         struct jffs2_full_dnode *fn = NULL;
  252         struct jffs2_sb_info *c;
  253         struct jffs2_raw_inode latest_node;
  254         __u32 latest_mctime, mctime_ver;
  255         __u32 mdata_ver = 0;
  256         int ret;
  257         ssize_t retlen;
  258 
  259         D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
  260 
  261         f = JFFS2_INODE_INFO(inode);
  262         c = JFFS2_SB_INFO(inode->i_sb);
  263 
  264         memset(f, 0, sizeof(*f));
  265         D2(printk(KERN_DEBUG "getting inocache\n"));
  266         init_MUTEX(&f->sem);
  267         f->inocache = jffs2_get_ino_cache(c, inode->i_ino);
  268         D2(printk(KERN_DEBUG "jffs2_read_inode(): Got inocache at %p\n", f->inocache));
  269 
  270         if (!f->inocache && inode->i_ino == 1) {
  271                 /* Special case - no root inode on medium */
  272                 f->inocache = jffs2_alloc_inode_cache();
  273                 if (!f->inocache) {
  274                         printk(KERN_CRIT "jffs2_read_inode(): Cannot allocate inocache for root inode\n");
  275                         make_bad_inode(inode);
  276                         return;
  277                 }
  278                 D1(printk(KERN_DEBUG "jffs2_read_inode(): Creating inocache for root inode\n"));
  279                 memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
  280                 f->inocache->ino = f->inocache->nlink = 1;
  281                 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
  282                 jffs2_add_ino_cache(c, f->inocache);
  283         }
  284         if (!f->inocache) {
  285                 printk(KERN_WARNING "jffs2_read_inode() on nonexistent ino %lu\n", (unsigned long)inode->i_ino);
  286                 make_bad_inode(inode);
  287                 return;
  288         }
  289         D1(printk(KERN_DEBUG "jffs2_read_inode(): ino #%lu nlink is %d\n", (unsigned long)inode->i_ino, f->inocache->nlink));
  290         inode->i_nlink = f->inocache->nlink;
  291 
  292         /* Grab all nodes relevant to this ino */
  293         ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
  294 
  295         if (ret) {
  296                 printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %lu returned %d\n", inode->i_ino, ret);
  297                 make_bad_inode(inode);
  298                 return;
  299         }
  300         f->dents = fd_list;
  301 
  302         while (tn_list) {
  303                 tn = tn_list;
  304 
  305                 fn = tn->fn;
  306 
  307                 if (f->metadata && tn->version > mdata_ver) {
  308                         D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3));
  309                         jffs2_mark_node_obsolete(c, f->metadata->raw);
  310                         jffs2_free_full_dnode(f->metadata);
  311                         f->metadata = NULL;
  312                         
  313                         mdata_ver = 0;
  314                 }
  315 
  316                 if (fn->size) {
  317                         jffs2_add_full_dnode_to_inode(c, f, fn);
  318                 } else {
  319                         /* Zero-sized node at end of version list. Just a metadata update */
  320                         D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", fn->raw->flash_offset &~3, tn->version));
  321                         f->metadata = fn;
  322                         mdata_ver = tn->version;
  323                 }
  324                 tn_list = tn->next;
  325                 jffs2_free_tmp_dnode_info(tn);
  326         }
  327         if (!fn) {
  328                 /* No data nodes for this inode. */
  329                 if (inode->i_ino != 1) {
  330                         printk(KERN_WARNING "jffs2_read_inode(): No data nodes found for ino #%lu\n", inode->i_ino);
  331                         if (!fd_list) {
  332                                 make_bad_inode(inode);
  333                                 return;
  334                         }
  335                         printk(KERN_WARNING "jffs2_read_inode(): But it has children so we fake some modes for it\n");
  336                 }
  337                 inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
  338                 latest_node.version = 0;
  339                 inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  340                 inode->i_nlink = f->inocache->nlink;
  341                 inode->i_size = 0;
  342         } else {
  343                 __u32 crc;
  344 
  345                 ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(latest_node), &retlen, (void *)&latest_node);
  346                 if (ret || retlen != sizeof(latest_node)) {
  347                         printk(KERN_NOTICE "MTD read in jffs2_read_inode() failed: Returned %d, %ld of %d bytes read\n",
  348                                ret, (long)retlen, sizeof(latest_node));
  349                         jffs2_clear_inode(inode);
  350                         make_bad_inode(inode);
  351                         return;
  352                 }
  353 
  354                 crc = crc32(0, &latest_node, sizeof(latest_node)-8);
  355                 if (crc != latest_node.node_crc) {
  356                         printk(KERN_NOTICE "CRC failed for read_inode of inode %ld at physical location 0x%x\n", inode->i_ino, fn->raw->flash_offset & ~3);
  357                         jffs2_clear_inode(inode);
  358                         make_bad_inode(inode);
  359                         return;
  360                 }
  361 
  362                 inode->i_mode = latest_node.mode;
  363                 inode->i_uid = latest_node.uid;
  364                 inode->i_gid = latest_node.gid;
  365                 inode->i_size = latest_node.isize;
  366                 if (S_ISREG(inode->i_mode))
  367                         jffs2_truncate_fraglist(c, &f->fraglist, latest_node.isize);
  368                 inode->i_atime = latest_node.atime;
  369                 inode->i_mtime = latest_node.mtime;
  370                 inode->i_ctime = latest_node.ctime;
  371         }
  372 
  373         /* OK, now the special cases. Certain inode types should
  374            have only one data node, and it's kept as the metadata
  375            node */
  376         if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode) ||
  377             S_ISLNK(inode->i_mode)) {
  378                 if (f->metadata) {
  379                         printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had metadata node\n", inode->i_ino, inode->i_mode);
  380                         jffs2_clear_inode(inode);
  381                         make_bad_inode(inode);
  382                         return;
  383                 }
  384                 if (!f->fraglist) {
  385                         printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o has no fragments\n", inode->i_ino, inode->i_mode);
  386                         jffs2_clear_inode(inode);
  387                         make_bad_inode(inode);
  388                         return;
  389                 }
  390                 /* ASSERT: f->fraglist != NULL */
  391                 if (f->fraglist->next) {
  392                         printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had more than one node\n", inode->i_ino, inode->i_mode);
  393                         /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
  394                         jffs2_clear_inode(inode);
  395                         make_bad_inode(inode);
  396                         return;
  397                 }
  398                 /* OK. We're happy */
  399                 f->metadata = f->fraglist->node;
  400                 jffs2_free_node_frag(f->fraglist);
  401                 f->fraglist = NULL;
  402         }                       
  403             
  404         inode->i_blksize = PAGE_SIZE;
  405         inode->i_blocks = (inode->i_size + 511) >> 9;
  406         
  407         switch (inode->i_mode & S_IFMT) {
  408                 unsigned short rdev;
  409 
  410         case S_IFLNK:
  411                 inode->i_op = &jffs2_symlink_inode_operations;
  412                 /* Hack to work around broken isize in old symlink code.
  413                    Remove this when dwmw2 comes to his senses and stops
  414                    symlinks from being an entirely gratuitous special
  415                    case. */
  416                 if (!inode->i_size)
  417                         inode->i_size = latest_node.dsize;
  418                 break;
  419                 
  420         case S_IFDIR:
  421                 if (mctime_ver > latest_node.version) {
  422                         /* The times in the latest_node are actually older than
  423                            mctime in the latest dirent. Cheat. */
  424                         inode->i_mtime = inode->i_ctime = inode->i_atime = 
  425                                 latest_mctime;
  426                 }
  427                 inode->i_op = &jffs2_dir_inode_operations;
  428                 inode->i_fop = &jffs2_dir_operations;
  429                 break;
  430 
  431         case S_IFREG:
  432                 inode->i_op = &jffs2_file_inode_operations;
  433                 inode->i_fop = &jffs2_file_operations;
  434                 inode->i_mapping->a_ops = &jffs2_file_address_operations;
  435                 inode->i_mapping->nrpages = 0;
  436                 break;
  437 
  438         case S_IFBLK:
  439         case S_IFCHR:
  440                 /* Read the device numbers from the media */
  441                 D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
  442                 if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
  443                         /* Eep */
  444                         printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
  445                         jffs2_clear_inode(inode);
  446                         make_bad_inode(inode);
  447                         return;
  448                 }                       
  449 
  450         case S_IFSOCK:
  451         case S_IFIFO:
  452                 inode->i_op = &jffs2_file_inode_operations;
  453                 init_special_inode(inode, inode->i_mode, kdev_t_to_nr(MKDEV(rdev>>8, rdev&0xff)));
  454                 break;
  455 
  456         default:
  457                 printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu", inode->i_mode, (unsigned long)inode->i_ino);
  458         }
  459         D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
  460 }
  461 
  462 void jffs2_clear_inode (struct inode *inode)
  463 {
  464         /* We can forget about this inode for now - drop all 
  465          *  the nodelists associated with it, etc.
  466          */
  467         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
  468         struct jffs2_node_frag *frag, *frags;
  469         struct jffs2_full_dirent *fd, *fds;
  470         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
  471         /* I don't think we care about the potential race due to reading this
  472            without f->sem. It can never get undeleted. */
  473         int deleted = f->inocache && !f->inocache->nlink;
  474 
  475         D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
  476 
  477         /* If it's a deleted inode, grab the alloc_sem. This prevents
  478            jffs2_garbage_collect_pass() from deciding that it wants to
  479            garbage collect one of the nodes we're just about to mark 
  480            obsolete -- by the time we drop alloc_sem and return, all
  481            the nodes are marked obsolete, and jffs2_g_c_pass() won't
  482            call iget() for the inode in question.
  483         */
  484         if (deleted)
  485                 down(&c->alloc_sem);
  486 
  487         down(&f->sem);
  488 
  489         frags = f->fraglist;
  490         fds = f->dents;
  491         if (f->metadata) {
  492                 if (deleted)
  493                         jffs2_mark_node_obsolete(c, f->metadata->raw);
  494                 jffs2_free_full_dnode(f->metadata);
  495         }
  496 
  497         while (frags) {
  498                 frag = frags;
  499                 frags = frag->next;
  500                 D2(printk(KERN_DEBUG "jffs2_clear_inode: frag at 0x%x-0x%x: node %p, frags %d--\n", frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0));
  501 
  502                 if (frag->node && !(--frag->node->frags)) {
  503                         /* Not a hole, and it's the final remaining frag of this node. Free the node */
  504                         if (deleted)
  505                                 jffs2_mark_node_obsolete(c, frag->node->raw);
  506 
  507                         jffs2_free_full_dnode(frag->node);
  508                 }
  509                 jffs2_free_node_frag(frag);
  510         }
  511         while(fds) {
  512                 fd = fds;
  513                 fds = fd->next;
  514                 jffs2_free_full_dirent(fd);
  515         }
  516 
  517         up(&f->sem);
  518 
  519         if(deleted)
  520                 up(&c->alloc_sem);
  521 };
  522 

Cache object: 80db8c5fa33eccc9680bf787096fe640


[ 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.