LCOV - code coverage report
Current view: top level - fs/jffs2 - write.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 293 0.0 %
Date: 2014-02-18 Functions: 0 7 0.0 %
Branches: 0 124 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/fs.h>
      16                 :            : #include <linux/crc32.h>
      17                 :            : #include <linux/pagemap.h>
      18                 :            : #include <linux/mtd/mtd.h>
      19                 :            : #include "nodelist.h"
      20                 :            : #include "compr.h"
      21                 :            : 
      22                 :            : 
      23                 :          0 : int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
      24                 :            :                        uint32_t mode, struct jffs2_raw_inode *ri)
      25                 :            : {
      26                 :            :         struct jffs2_inode_cache *ic;
      27                 :            : 
      28                 :          0 :         ic = jffs2_alloc_inode_cache();
      29         [ #  # ]:          0 :         if (!ic) {
      30                 :            :                 return -ENOMEM;
      31                 :            :         }
      32                 :            : 
      33                 :          0 :         memset(ic, 0, sizeof(*ic));
      34                 :            : 
      35                 :          0 :         f->inocache = ic;
      36                 :          0 :         f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
      37                 :          0 :         f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
      38                 :          0 :         f->inocache->state = INO_STATE_PRESENT;
      39                 :            : 
      40                 :          0 :         jffs2_add_ino_cache(c, f->inocache);
      41                 :            :         jffs2_dbg(1, "%s(): Assigned ino# %d\n", __func__, f->inocache->ino);
      42                 :          0 :         ri->ino = cpu_to_je32(f->inocache->ino);
      43                 :            : 
      44                 :          0 :         ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
      45                 :          0 :         ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
      46                 :          0 :         ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
      47                 :          0 :         ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
      48                 :          0 :         ri->mode = cpu_to_jemode(mode);
      49                 :            : 
      50                 :          0 :         f->highest_version = 1;
      51                 :          0 :         ri->version = cpu_to_je32(f->highest_version);
      52                 :            : 
      53                 :          0 :         return 0;
      54                 :            : }
      55                 :            : 
      56                 :            : /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
      57                 :            :    write it to the flash, link it into the existing inode/fragment list */
      58                 :            : 
      59                 :          0 : struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
      60                 :            :                                            struct jffs2_raw_inode *ri, const unsigned char *data,
      61                 :            :                                            uint32_t datalen, int alloc_mode)
      62                 :            : 
      63                 :            : {
      64                 :            :         struct jffs2_full_dnode *fn;
      65                 :            :         size_t retlen;
      66                 :            :         uint32_t flash_ofs;
      67                 :            :         struct kvec vecs[2];
      68                 :            :         int ret;
      69                 :            :         int retried = 0;
      70                 :            :         unsigned long cnt = 2;
      71                 :            : 
      72                 :            :         D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) {
      73                 :            :                 pr_crit("Eep. CRC not correct in jffs2_write_dnode()\n");
      74                 :            :                 BUG();
      75                 :            :         }
      76                 :            :            );
      77                 :          0 :         vecs[0].iov_base = ri;
      78                 :          0 :         vecs[0].iov_len = sizeof(*ri);
      79                 :          0 :         vecs[1].iov_base = (unsigned char *)data;
      80                 :          0 :         vecs[1].iov_len = datalen;
      81                 :            : 
      82         [ #  # ]:          0 :         if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
      83                 :          0 :                 pr_warn("%s(): ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n",
      84                 :            :                         __func__, je32_to_cpu(ri->totlen),
      85                 :            :                         sizeof(*ri), datalen);
      86                 :            :         }
      87                 :            : 
      88                 :          0 :         fn = jffs2_alloc_full_dnode();
      89         [ #  # ]:          0 :         if (!fn)
      90                 :            :                 return ERR_PTR(-ENOMEM);
      91                 :            : 
      92                 :            :         /* check number of valid vecs */
      93         [ #  # ]:          0 :         if (!datalen || !data)
      94                 :            :                 cnt = 1;
      95                 :            :  retry:
      96                 :          0 :         flash_ofs = write_ofs(c);
      97                 :            : 
      98                 :            :         jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
      99                 :            : 
     100 [ #  # ][ #  # ]:          0 :         if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
     101         [ #  # ]:          0 :                 BUG_ON(!retried);
     102                 :            :                 jffs2_dbg(1, "%s(): dnode_version %d, highest version %d -> updating dnode\n",
     103                 :            :                           __func__,
     104                 :            :                           je32_to_cpu(ri->version), f->highest_version);
     105                 :          0 :                 ri->version = cpu_to_je32(++f->highest_version);
     106                 :          0 :                 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
     107                 :            :         }
     108                 :            : 
     109         [ #  # ]:          0 :         ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen,
     110                 :          0 :                                  (alloc_mode==ALLOC_GC)?0:f->inocache->ino);
     111                 :            : 
     112 [ #  # ][ #  # ]:          0 :         if (ret || (retlen != sizeof(*ri) + datalen)) {
     113                 :          0 :                 pr_notice("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
     114                 :            :                           sizeof(*ri) + datalen, flash_ofs, ret, retlen);
     115                 :            : 
     116                 :            :                 /* Mark the space as dirtied */
     117         [ #  # ]:          0 :                 if (retlen) {
     118                 :            :                         /* Don't change raw->size to match retlen. We may have
     119                 :            :                            written the node header already, and only the data will
     120                 :            :                            seem corrupted, in which case the scan would skip over
     121                 :            :                            any node we write before the original intended end of
     122                 :            :                            this node */
     123                 :          0 :                         jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
     124                 :            :                 } else {
     125                 :          0 :                         pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n",
     126                 :            :                                   flash_ofs);
     127                 :            :                 }
     128         [ #  # ]:          0 :                 if (!retried && alloc_mode != ALLOC_NORETRY) {
     129                 :            :                         /* Try to reallocate space and retry */
     130                 :            :                         uint32_t dummy;
     131                 :          0 :                         struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
     132                 :            : 
     133                 :            :                         retried = 1;
     134                 :            : 
     135                 :            :                         jffs2_dbg(1, "Retrying failed write.\n");
     136                 :            : 
     137                 :          0 :                         jffs2_dbg_acct_sanity_check(c,jeb);
     138                 :            :                         jffs2_dbg_acct_paranoia_check(c, jeb);
     139                 :            : 
     140         [ #  # ]:          0 :                         if (alloc_mode == ALLOC_GC) {
     141                 :          0 :                                 ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy,
     142                 :            :                                                              JFFS2_SUMMARY_INODE_SIZE);
     143                 :            :                         } else {
     144                 :            :                                 /* Locking pain */
     145                 :          0 :                                 mutex_unlock(&f->sem);
     146                 :          0 :                                 jffs2_complete_reservation(c);
     147                 :            : 
     148                 :          0 :                                 ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
     149                 :            :                                                           alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
     150                 :          0 :                                 mutex_lock(&f->sem);
     151                 :            :                         }
     152                 :            : 
     153         [ #  # ]:          0 :                         if (!ret) {
     154                 :            :                                 flash_ofs = write_ofs(c);
     155                 :            :                                 jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write.\n",
     156                 :            :                                           flash_ofs);
     157                 :            : 
     158                 :          0 :                                 jffs2_dbg_acct_sanity_check(c,jeb);
     159                 :            :                                 jffs2_dbg_acct_paranoia_check(c, jeb);
     160                 :            : 
     161                 :          0 :                                 goto retry;
     162                 :            :                         }
     163                 :            :                         jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n",
     164                 :            :                                   ret);
     165                 :            :                 }
     166                 :            :                 /* Release the full_dnode which is now useless, and return */
     167                 :          0 :                 jffs2_free_full_dnode(fn);
     168         [ #  # ]:          0 :                 return ERR_PTR(ret?ret:-EIO);
     169                 :            :         }
     170                 :            :         /* Mark the space used */
     171                 :            :         /* If node covers at least a whole page, or if it starts at the
     172                 :            :            beginning of a page and runs to the end of the file, or if
     173                 :            :            it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
     174                 :            :         */
     175 [ #  # ][ #  # ]:          0 :         if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
     176         [ #  # ]:          0 :             ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
     177                 :          0 :               (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) ==  je32_to_cpu(ri->isize)))) {
     178                 :          0 :                 flash_ofs |= REF_PRISTINE;
     179                 :            :         } else {
     180                 :          0 :                 flash_ofs |= REF_NORMAL;
     181                 :            :         }
     182                 :          0 :         fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
     183         [ #  # ]:          0 :         if (IS_ERR(fn->raw)) {
     184                 :            :                 void *hold_err = fn->raw;
     185                 :            :                 /* Release the full_dnode which is now useless, and return */
     186                 :          0 :                 jffs2_free_full_dnode(fn);
     187                 :          0 :                 return ERR_CAST(hold_err);
     188                 :            :         }
     189                 :          0 :         fn->ofs = je32_to_cpu(ri->offset);
     190                 :          0 :         fn->size = je32_to_cpu(ri->dsize);
     191                 :          0 :         fn->frags = 0;
     192                 :            : 
     193                 :            :         jffs2_dbg(1, "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
     194                 :            :                   flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
     195                 :            :                   je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
     196                 :            :                   je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen));
     197                 :            : 
     198         [ #  # ]:          0 :         if (retried) {
     199                 :          0 :                 jffs2_dbg_acct_sanity_check(c,NULL);
     200                 :            :         }
     201                 :            : 
     202                 :          0 :         return fn;
     203                 :            : }
     204                 :            : 
     205                 :          0 : struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
     206                 :            :                                              struct jffs2_raw_dirent *rd, const unsigned char *name,
     207                 :            :                                              uint32_t namelen, int alloc_mode)
     208                 :            : {
     209                 :            :         struct jffs2_full_dirent *fd;
     210                 :            :         size_t retlen;
     211                 :            :         struct kvec vecs[2];
     212                 :            :         uint32_t flash_ofs;
     213                 :            :         int retried = 0;
     214                 :            :         int ret;
     215                 :            : 
     216                 :            :         jffs2_dbg(1, "%s(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n",
     217                 :            :                   __func__,
     218                 :            :                   je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
     219                 :            :                   je32_to_cpu(rd->name_crc));
     220                 :            : 
     221                 :            :         D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
     222                 :            :                 pr_crit("Eep. CRC not correct in jffs2_write_dirent()\n");
     223                 :            :                 BUG();
     224                 :            :            });
     225                 :            : 
     226         [ #  # ]:          0 :         if (strnlen(name, namelen) != namelen) {
     227                 :            :                 /* This should never happen, but seems to have done on at least one
     228                 :            :                    occasion: https://dev.laptop.org/ticket/4184 */
     229                 :          0 :                 pr_crit("Error in jffs2_write_dirent() -- name contains zero bytes!\n");
     230                 :          0 :                 pr_crit("Directory inode #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x\n",
     231                 :            :                         je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
     232                 :            :                         je32_to_cpu(rd->name_crc));
     233                 :          0 :                 WARN_ON(1);
     234                 :          0 :                 return ERR_PTR(-EIO);
     235                 :            :         }
     236                 :            : 
     237                 :          0 :         vecs[0].iov_base = rd;
     238                 :          0 :         vecs[0].iov_len = sizeof(*rd);
     239                 :          0 :         vecs[1].iov_base = (unsigned char *)name;
     240                 :          0 :         vecs[1].iov_len = namelen;
     241                 :            : 
     242                 :          0 :         fd = jffs2_alloc_full_dirent(namelen+1);
     243         [ #  # ]:          0 :         if (!fd)
     244                 :            :                 return ERR_PTR(-ENOMEM);
     245                 :            : 
     246                 :          0 :         fd->version = je32_to_cpu(rd->version);
     247                 :          0 :         fd->ino = je32_to_cpu(rd->ino);
     248                 :          0 :         fd->nhash = full_name_hash(name, namelen);
     249                 :          0 :         fd->type = rd->type;
     250                 :          0 :         memcpy(fd->name, name, namelen);
     251                 :          0 :         fd->name[namelen]=0;
     252                 :            : 
     253                 :            :  retry:
     254                 :          0 :         flash_ofs = write_ofs(c);
     255                 :            : 
     256                 :            :         jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
     257                 :            : 
     258 [ #  # ][ #  # ]:          0 :         if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
     259         [ #  # ]:          0 :                 BUG_ON(!retried);
     260                 :            :                 jffs2_dbg(1, "%s(): dirent_version %d, highest version %d -> updating dirent\n",
     261                 :            :                           __func__,
     262                 :            :                           je32_to_cpu(rd->version), f->highest_version);
     263                 :          0 :                 rd->version = cpu_to_je32(++f->highest_version);
     264                 :          0 :                 fd->version = je32_to_cpu(rd->version);
     265                 :          0 :                 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
     266                 :            :         }
     267                 :            : 
     268         [ #  # ]:          0 :         ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
     269                 :            :                                  (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));
     270 [ #  # ][ #  # ]:          0 :         if (ret || (retlen != sizeof(*rd) + namelen)) {
     271                 :          0 :                 pr_notice("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
     272                 :            :                           sizeof(*rd) + namelen, flash_ofs, ret, retlen);
     273                 :            :                 /* Mark the space as dirtied */
     274         [ #  # ]:          0 :                 if (retlen) {
     275                 :          0 :                         jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
     276                 :            :                 } else {
     277                 :          0 :                         pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n",
     278                 :            :                                   flash_ofs);
     279                 :            :                 }
     280         [ #  # ]:          0 :                 if (!retried) {
     281                 :            :                         /* Try to reallocate space and retry */
     282                 :            :                         uint32_t dummy;
     283                 :          0 :                         struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
     284                 :            : 
     285                 :            :                         retried = 1;
     286                 :            : 
     287                 :            :                         jffs2_dbg(1, "Retrying failed write.\n");
     288                 :            : 
     289                 :          0 :                         jffs2_dbg_acct_sanity_check(c,jeb);
     290                 :            :                         jffs2_dbg_acct_paranoia_check(c, jeb);
     291                 :            : 
     292         [ #  # ]:          0 :                         if (alloc_mode == ALLOC_GC) {
     293                 :          0 :                                 ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy,
     294                 :            :                                                              JFFS2_SUMMARY_DIRENT_SIZE(namelen));
     295                 :            :                         } else {
     296                 :            :                                 /* Locking pain */
     297                 :          0 :                                 mutex_unlock(&f->sem);
     298                 :          0 :                                 jffs2_complete_reservation(c);
     299                 :            : 
     300                 :          0 :                                 ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
     301                 :            :                                                           alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
     302                 :          0 :                                 mutex_lock(&f->sem);
     303                 :            :                         }
     304                 :            : 
     305         [ #  # ]:          0 :                         if (!ret) {
     306                 :            :                                 flash_ofs = write_ofs(c);
     307                 :            :                                 jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write\n",
     308                 :            :                                           flash_ofs);
     309                 :          0 :                                 jffs2_dbg_acct_sanity_check(c,jeb);
     310                 :            :                                 jffs2_dbg_acct_paranoia_check(c, jeb);
     311                 :          0 :                                 goto retry;
     312                 :            :                         }
     313                 :            :                         jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n",
     314                 :            :                                   ret);
     315                 :            :                 }
     316                 :            :                 /* Release the full_dnode which is now useless, and return */
     317                 :          0 :                 jffs2_free_full_dirent(fd);
     318         [ #  # ]:          0 :                 return ERR_PTR(ret?ret:-EIO);
     319                 :            :         }
     320                 :            :         /* Mark the space used */
     321         [ #  # ]:          0 :         fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | dirent_node_state(rd),
     322                 :          0 :                                               PAD(sizeof(*rd)+namelen), f->inocache);
     323         [ #  # ]:          0 :         if (IS_ERR(fd->raw)) {
     324                 :            :                 void *hold_err = fd->raw;
     325                 :            :                 /* Release the full_dirent which is now useless, and return */
     326                 :          0 :                 jffs2_free_full_dirent(fd);
     327                 :          0 :                 return ERR_CAST(hold_err);
     328                 :            :         }
     329                 :            : 
     330         [ #  # ]:          0 :         if (retried) {
     331                 :          0 :                 jffs2_dbg_acct_sanity_check(c,NULL);
     332                 :            :         }
     333                 :            : 
     334                 :          0 :         return fd;
     335                 :            : }
     336                 :            : 
     337                 :            : /* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that
     338                 :            :    we don't have to go digging in struct inode or its equivalent. It should set:
     339                 :            :    mode, uid, gid, (starting)isize, atime, ctime, mtime */
     340                 :          0 : int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
     341                 :            :                             struct jffs2_raw_inode *ri, unsigned char *buf,
     342                 :            :                             uint32_t offset, uint32_t writelen, uint32_t *retlen)
     343                 :            : {
     344                 :            :         int ret = 0;
     345                 :            :         uint32_t writtenlen = 0;
     346                 :            : 
     347                 :            :         jffs2_dbg(1, "%s(): Ino #%u, ofs 0x%x, len 0x%x\n",
     348                 :            :                   __func__, f->inocache->ino, offset, writelen);
     349                 :            : 
     350         [ #  # ]:          0 :         while(writelen) {
     351                 :            :                 struct jffs2_full_dnode *fn;
     352                 :          0 :                 unsigned char *comprbuf = NULL;
     353                 :            :                 uint16_t comprtype = JFFS2_COMPR_NONE;
     354                 :            :                 uint32_t alloclen;
     355                 :            :                 uint32_t datalen, cdatalen;
     356                 :            :                 int retried = 0;
     357                 :            : 
     358                 :            :         retry:
     359                 :            :                 jffs2_dbg(2, "jffs2_commit_write() loop: 0x%x to write to 0x%x\n",
     360                 :            :                           writelen, offset);
     361                 :            : 
     362                 :          0 :                 ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
     363                 :            :                                         &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
     364         [ #  # ]:          0 :                 if (ret) {
     365                 :            :                         jffs2_dbg(1, "jffs2_reserve_space returned %d\n", ret);
     366                 :          0 :                         break;
     367                 :            :                 }
     368                 :          0 :                 mutex_lock(&f->sem);
     369                 :          0 :                 datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
     370                 :          0 :                 cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
     371                 :            : 
     372                 :          0 :                 comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);
     373                 :            : 
     374                 :          0 :                 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
     375                 :          0 :                 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
     376                 :          0 :                 ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen);
     377                 :          0 :                 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
     378                 :            : 
     379                 :          0 :                 ri->ino = cpu_to_je32(f->inocache->ino);
     380                 :          0 :                 ri->version = cpu_to_je32(++f->highest_version);
     381                 :          0 :                 ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen));
     382                 :          0 :                 ri->offset = cpu_to_je32(offset);
     383                 :          0 :                 ri->csize = cpu_to_je32(cdatalen);
     384                 :          0 :                 ri->dsize = cpu_to_je32(datalen);
     385                 :          0 :                 ri->compr = comprtype & 0xff;
     386                 :          0 :                 ri->usercompr = (comprtype >> 8 ) & 0xff;
     387                 :          0 :                 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
     388                 :          0 :                 ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
     389                 :            : 
     390                 :          0 :                 fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
     391                 :            : 
     392                 :          0 :                 jffs2_free_comprbuf(comprbuf, buf);
     393                 :            : 
     394         [ #  # ]:          0 :                 if (IS_ERR(fn)) {
     395                 :            :                         ret = PTR_ERR(fn);
     396                 :          0 :                         mutex_unlock(&f->sem);
     397                 :          0 :                         jffs2_complete_reservation(c);
     398         [ #  # ]:          0 :                         if (!retried) {
     399                 :            :                                 /* Write error to be retried */
     400                 :            :                                 retried = 1;
     401                 :            :                                 jffs2_dbg(1, "Retrying node write in jffs2_write_inode_range()\n");
     402                 :            :                                 goto retry;
     403                 :            :                         }
     404                 :            :                         break;
     405                 :            :                 }
     406                 :          0 :                 ret = jffs2_add_full_dnode_to_inode(c, f, fn);
     407         [ #  # ]:          0 :                 if (f->metadata) {
     408                 :          0 :                         jffs2_mark_node_obsolete(c, f->metadata->raw);
     409                 :          0 :                         jffs2_free_full_dnode(f->metadata);
     410                 :          0 :                         f->metadata = NULL;
     411                 :            :                 }
     412         [ #  # ]:          0 :                 if (ret) {
     413                 :            :                         /* Eep */
     414                 :            :                         jffs2_dbg(1, "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n",
     415                 :            :                                   ret);
     416                 :          0 :                         jffs2_mark_node_obsolete(c, fn->raw);
     417                 :          0 :                         jffs2_free_full_dnode(fn);
     418                 :            : 
     419                 :          0 :                         mutex_unlock(&f->sem);
     420                 :          0 :                         jffs2_complete_reservation(c);
     421                 :          0 :                         break;
     422                 :            :                 }
     423                 :          0 :                 mutex_unlock(&f->sem);
     424                 :          0 :                 jffs2_complete_reservation(c);
     425         [ #  # ]:          0 :                 if (!datalen) {
     426                 :          0 :                         pr_warn("Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
     427                 :            :                         ret = -EIO;
     428                 :          0 :                         break;
     429                 :            :                 }
     430                 :            :                 jffs2_dbg(1, "increasing writtenlen by %d\n", datalen);
     431                 :          0 :                 writtenlen += datalen;
     432                 :          0 :                 offset += datalen;
     433                 :          0 :                 writelen -= datalen;
     434                 :          0 :                 buf += datalen;
     435                 :            :         }
     436                 :          0 :         *retlen = writtenlen;
     437                 :          0 :         return ret;
     438                 :            : }
     439                 :            : 
     440                 :          0 : int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
     441                 :            :                     struct jffs2_inode_info *f, struct jffs2_raw_inode *ri,
     442                 :            :                     const struct qstr *qstr)
     443                 :            : {
     444                 :            :         struct jffs2_raw_dirent *rd;
     445                 :            :         struct jffs2_full_dnode *fn;
     446                 :            :         struct jffs2_full_dirent *fd;
     447                 :            :         uint32_t alloclen;
     448                 :            :         int ret;
     449                 :            : 
     450                 :            :         /* Try to reserve enough space for both node and dirent.
     451                 :            :          * Just the node will do for now, though
     452                 :            :          */
     453                 :          0 :         ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
     454                 :            :                                 JFFS2_SUMMARY_INODE_SIZE);
     455                 :            :         jffs2_dbg(1, "%s(): reserved 0x%x bytes\n", __func__, alloclen);
     456         [ #  # ]:          0 :         if (ret)
     457                 :            :                 return ret;
     458                 :            : 
     459                 :          0 :         mutex_lock(&f->sem);
     460                 :            : 
     461                 :          0 :         ri->data_crc = cpu_to_je32(0);
     462                 :          0 :         ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
     463                 :            : 
     464                 :          0 :         fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
     465                 :            : 
     466                 :            :         jffs2_dbg(1, "jffs2_do_create created file with mode 0x%x\n",
     467                 :            :                   jemode_to_cpu(ri->mode));
     468                 :            : 
     469         [ #  # ]:          0 :         if (IS_ERR(fn)) {
     470                 :            :                 jffs2_dbg(1, "jffs2_write_dnode() failed\n");
     471                 :            :                 /* Eeek. Wave bye bye */
     472                 :          0 :                 mutex_unlock(&f->sem);
     473                 :          0 :                 jffs2_complete_reservation(c);
     474                 :          0 :                 return PTR_ERR(fn);
     475                 :            :         }
     476                 :            :         /* No data here. Only a metadata node, which will be
     477                 :            :            obsoleted by the first data write
     478                 :            :         */
     479                 :          0 :         f->metadata = fn;
     480                 :            : 
     481                 :          0 :         mutex_unlock(&f->sem);
     482                 :          0 :         jffs2_complete_reservation(c);
     483                 :            : 
     484                 :          0 :         ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);
     485         [ #  # ]:          0 :         if (ret)
     486                 :            :                 return ret;
     487                 :          0 :         ret = jffs2_init_acl_post(&f->vfs_inode);
     488         [ #  # ]:          0 :         if (ret)
     489                 :            :                 return ret;
     490                 :            : 
     491                 :          0 :         ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen,
     492                 :            :                                 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len));
     493                 :            : 
     494         [ #  # ]:          0 :         if (ret) {
     495                 :            :                 /* Eep. */
     496                 :            :                 jffs2_dbg(1, "jffs2_reserve_space() for dirent failed\n");
     497                 :            :                 return ret;
     498                 :            :         }
     499                 :            : 
     500                 :          0 :         rd = jffs2_alloc_raw_dirent();
     501         [ #  # ]:          0 :         if (!rd) {
     502                 :            :                 /* Argh. Now we treat it like a normal delete */
     503                 :          0 :                 jffs2_complete_reservation(c);
     504                 :          0 :                 return -ENOMEM;
     505                 :            :         }
     506                 :            : 
     507                 :          0 :         mutex_lock(&dir_f->sem);
     508                 :            : 
     509                 :          0 :         rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
     510                 :          0 :         rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
     511                 :          0 :         rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len);
     512                 :          0 :         rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
     513                 :            : 
     514                 :          0 :         rd->pino = cpu_to_je32(dir_f->inocache->ino);
     515                 :          0 :         rd->version = cpu_to_je32(++dir_f->highest_version);
     516                 :          0 :         rd->ino = ri->ino;
     517                 :          0 :         rd->mctime = ri->ctime;
     518                 :          0 :         rd->nsize = qstr->len;
     519                 :          0 :         rd->type = DT_REG;
     520                 :          0 :         rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
     521                 :          0 :         rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len));
     522                 :            : 
     523                 :          0 :         fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL);
     524                 :            : 
     525                 :          0 :         jffs2_free_raw_dirent(rd);
     526                 :            : 
     527         [ #  # ]:          0 :         if (IS_ERR(fd)) {
     528                 :            :                 /* dirent failed to write. Delete the inode normally
     529                 :            :                    as if it were the final unlink() */
     530                 :          0 :                 jffs2_complete_reservation(c);
     531                 :          0 :                 mutex_unlock(&dir_f->sem);
     532                 :          0 :                 return PTR_ERR(fd);
     533                 :            :         }
     534                 :            : 
     535                 :            :         /* Link the fd into the inode's list, obsoleting an old
     536                 :            :            one if necessary. */
     537                 :          0 :         jffs2_add_fd_to_list(c, fd, &dir_f->dents);
     538                 :            : 
     539                 :          0 :         jffs2_complete_reservation(c);
     540                 :          0 :         mutex_unlock(&dir_f->sem);
     541                 :            : 
     542                 :          0 :         return 0;
     543                 :            : }
     544                 :            : 
     545                 :            : 
     546                 :          0 : int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
     547                 :            :                     const char *name, int namelen, struct jffs2_inode_info *dead_f,
     548                 :            :                     uint32_t time)
     549                 :            : {
     550                 :            :         struct jffs2_raw_dirent *rd;
     551                 :            :         struct jffs2_full_dirent *fd;
     552                 :            :         uint32_t alloclen;
     553                 :            :         int ret;
     554                 :            : 
     555                 :            :         if (!jffs2_can_mark_obsolete(c)) {
     556                 :            :                 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
     557                 :            : 
     558                 :          0 :                 rd = jffs2_alloc_raw_dirent();
     559         [ #  # ]:          0 :                 if (!rd)
     560                 :            :                         return -ENOMEM;
     561                 :            : 
     562                 :          0 :                 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
     563                 :            :                                         ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
     564         [ #  # ]:          0 :                 if (ret) {
     565                 :          0 :                         jffs2_free_raw_dirent(rd);
     566                 :          0 :                         return ret;
     567                 :            :                 }
     568                 :            : 
     569                 :          0 :                 mutex_lock(&dir_f->sem);
     570                 :            : 
     571                 :            :                 /* Build a deletion node */
     572                 :          0 :                 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
     573                 :          0 :                 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
     574                 :          0 :                 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
     575                 :          0 :                 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
     576                 :            : 
     577                 :          0 :                 rd->pino = cpu_to_je32(dir_f->inocache->ino);
     578                 :          0 :                 rd->version = cpu_to_je32(++dir_f->highest_version);
     579                 :          0 :                 rd->ino = cpu_to_je32(0);
     580                 :          0 :                 rd->mctime = cpu_to_je32(time);
     581                 :          0 :                 rd->nsize = namelen;
     582                 :          0 :                 rd->type = DT_UNKNOWN;
     583                 :          0 :                 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
     584                 :          0 :                 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
     585                 :            : 
     586                 :          0 :                 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION);
     587                 :            : 
     588                 :          0 :                 jffs2_free_raw_dirent(rd);
     589                 :            : 
     590         [ #  # ]:          0 :                 if (IS_ERR(fd)) {
     591                 :          0 :                         jffs2_complete_reservation(c);
     592                 :          0 :                         mutex_unlock(&dir_f->sem);
     593                 :          0 :                         return PTR_ERR(fd);
     594                 :            :                 }
     595                 :            : 
     596                 :            :                 /* File it. This will mark the old one obsolete. */
     597                 :          0 :                 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
     598                 :          0 :                 mutex_unlock(&dir_f->sem);
     599                 :            :         } else {
     600                 :            :                 uint32_t nhash = full_name_hash(name, namelen);
     601                 :            : 
     602                 :            :                 fd = dir_f->dents;
     603                 :            :                 /* We don't actually want to reserve any space, but we do
     604                 :            :                    want to be holding the alloc_sem when we write to flash */
     605                 :            :                 mutex_lock(&c->alloc_sem);
     606                 :            :                 mutex_lock(&dir_f->sem);
     607                 :            : 
     608                 :            :                 for (fd = dir_f->dents; fd; fd = fd->next) {
     609                 :            :                         if (fd->nhash == nhash &&
     610                 :            :                             !memcmp(fd->name, name, namelen) &&
     611                 :            :                             !fd->name[namelen]) {
     612                 :            : 
     613                 :            :                                 jffs2_dbg(1, "Marking old dirent node (ino #%u) @%08x obsolete\n",
     614                 :            :                                           fd->ino, ref_offset(fd->raw));
     615                 :            :                                 jffs2_mark_node_obsolete(c, fd->raw);
     616                 :            :                                 /* We don't want to remove it from the list immediately,
     617                 :            :                                    because that screws up getdents()/seek() semantics even
     618                 :            :                                    more than they're screwed already. Turn it into a
     619                 :            :                                    node-less deletion dirent instead -- a placeholder */
     620                 :            :                                 fd->raw = NULL;
     621                 :            :                                 fd->ino = 0;
     622                 :            :                                 break;
     623                 :            :                         }
     624                 :            :                 }
     625                 :            :                 mutex_unlock(&dir_f->sem);
     626                 :            :         }
     627                 :            : 
     628                 :            :         /* dead_f is NULL if this was a rename not a real unlink */
     629                 :            :         /* Also catch the !f->inocache case, where there was a dirent
     630                 :            :            pointing to an inode which didn't exist. */
     631 [ #  # ][ #  # ]:          0 :         if (dead_f && dead_f->inocache) {
     632                 :            : 
     633                 :          0 :                 mutex_lock(&dead_f->sem);
     634                 :            : 
     635         [ #  # ]:          0 :                 if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
     636         [ #  # ]:          0 :                         while (dead_f->dents) {
     637                 :            :                                 /* There can be only deleted ones */
     638                 :            :                                 fd = dead_f->dents;
     639                 :            : 
     640                 :          0 :                                 dead_f->dents = fd->next;
     641                 :            : 
     642         [ #  # ]:          0 :                                 if (fd->ino) {
     643                 :          0 :                                         pr_warn("Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
     644                 :            :                                                 dead_f->inocache->ino,
     645                 :            :                                                 fd->name, fd->ino);
     646                 :            :                                 } else {
     647                 :            :                                         jffs2_dbg(1, "Removing deletion dirent for \"%s\" from dir ino #%u\n",
     648                 :            :                                                   fd->name,
     649                 :            :                                                   dead_f->inocache->ino);
     650                 :            :                                 }
     651         [ #  # ]:          0 :                                 if (fd->raw)
     652                 :          0 :                                         jffs2_mark_node_obsolete(c, fd->raw);
     653                 :          0 :                                 jffs2_free_full_dirent(fd);
     654                 :            :                         }
     655                 :          0 :                         dead_f->inocache->pino_nlink = 0;
     656                 :            :                 } else
     657                 :          0 :                         dead_f->inocache->pino_nlink--;
     658                 :            :                 /* NB: Caller must set inode nlink if appropriate */
     659                 :          0 :                 mutex_unlock(&dead_f->sem);
     660                 :            :         }
     661                 :            : 
     662                 :          0 :         jffs2_complete_reservation(c);
     663                 :            : 
     664                 :          0 :         return 0;
     665                 :            : }
     666                 :            : 
     667                 :            : 
     668                 :          0 : int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time)
     669                 :            : {
     670                 :            :         struct jffs2_raw_dirent *rd;
     671                 :            :         struct jffs2_full_dirent *fd;
     672                 :            :         uint32_t alloclen;
     673                 :            :         int ret;
     674                 :            : 
     675                 :          0 :         rd = jffs2_alloc_raw_dirent();
     676         [ #  # ]:          0 :         if (!rd)
     677                 :            :                 return -ENOMEM;
     678                 :            : 
     679                 :          0 :         ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
     680                 :            :                                 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
     681         [ #  # ]:          0 :         if (ret) {
     682                 :          0 :                 jffs2_free_raw_dirent(rd);
     683                 :          0 :                 return ret;
     684                 :            :         }
     685                 :            : 
     686                 :          0 :         mutex_lock(&dir_f->sem);
     687                 :            : 
     688                 :            :         /* Build a deletion node */
     689                 :          0 :         rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
     690                 :          0 :         rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
     691                 :          0 :         rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
     692                 :          0 :         rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
     693                 :            : 
     694                 :          0 :         rd->pino = cpu_to_je32(dir_f->inocache->ino);
     695                 :          0 :         rd->version = cpu_to_je32(++dir_f->highest_version);
     696                 :          0 :         rd->ino = cpu_to_je32(ino);
     697                 :          0 :         rd->mctime = cpu_to_je32(time);
     698                 :          0 :         rd->nsize = namelen;
     699                 :            : 
     700                 :          0 :         rd->type = type;
     701                 :            : 
     702                 :          0 :         rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
     703                 :          0 :         rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
     704                 :            : 
     705                 :          0 :         fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
     706                 :            : 
     707                 :          0 :         jffs2_free_raw_dirent(rd);
     708                 :            : 
     709         [ #  # ]:          0 :         if (IS_ERR(fd)) {
     710                 :          0 :                 jffs2_complete_reservation(c);
     711                 :          0 :                 mutex_unlock(&dir_f->sem);
     712                 :          0 :                 return PTR_ERR(fd);
     713                 :            :         }
     714                 :            : 
     715                 :            :         /* File it. This will mark the old one obsolete. */
     716                 :          0 :         jffs2_add_fd_to_list(c, fd, &dir_f->dents);
     717                 :            : 
     718                 :          0 :         jffs2_complete_reservation(c);
     719                 :          0 :         mutex_unlock(&dir_f->sem);
     720                 :            : 
     721                 :          0 :         return 0;
     722                 :            : }

Generated by: LCOV version 1.9