0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015
0016 #include <linux/kernel.h>
0017 #include <linux/slab.h>
0018 #include <linux/mtd/mtd.h>
0019 #include <linux/pagemap.h>
0020 #include <linux/crc32.h>
0021 #include <linux/compiler.h>
0022 #include <linux/vmalloc.h>
0023 #include "nodelist.h"
0024 #include "debug.h"
0025
0026 int jffs2_sum_init(struct jffs2_sb_info *c)
0027 {
0028 uint32_t sum_size = min_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE);
0029
0030 c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
0031
0032 if (!c->summary) {
0033 JFFS2_WARNING("Can't allocate memory for summary information!\n");
0034 return -ENOMEM;
0035 }
0036
0037 c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL);
0038
0039 if (!c->summary->sum_buf) {
0040 JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n");
0041 kfree(c->summary);
0042 return -ENOMEM;
0043 }
0044
0045 dbg_summary("returned successfully\n");
0046
0047 return 0;
0048 }
0049
0050 void jffs2_sum_exit(struct jffs2_sb_info *c)
0051 {
0052 dbg_summary("called\n");
0053
0054 jffs2_sum_disable_collecting(c->summary);
0055
0056 kfree(c->summary->sum_buf);
0057 c->summary->sum_buf = NULL;
0058
0059 kfree(c->summary);
0060 c->summary = NULL;
0061 }
0062
0063 static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
0064 {
0065 if (!s->sum_list_head)
0066 s->sum_list_head = (union jffs2_sum_mem *) item;
0067 if (s->sum_list_tail)
0068 s->sum_list_tail->u.next = (union jffs2_sum_mem *) item;
0069 s->sum_list_tail = (union jffs2_sum_mem *) item;
0070
0071 switch (je16_to_cpu(item->u.nodetype)) {
0072 case JFFS2_NODETYPE_INODE:
0073 s->sum_size += JFFS2_SUMMARY_INODE_SIZE;
0074 s->sum_num++;
0075 dbg_summary("inode (%u) added to summary\n",
0076 je32_to_cpu(item->i.inode));
0077 break;
0078 case JFFS2_NODETYPE_DIRENT:
0079 s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize);
0080 s->sum_num++;
0081 dbg_summary("dirent (%u) added to summary\n",
0082 je32_to_cpu(item->d.ino));
0083 break;
0084 #ifdef CONFIG_JFFS2_FS_XATTR
0085 case JFFS2_NODETYPE_XATTR:
0086 s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
0087 s->sum_num++;
0088 dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
0089 je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
0090 break;
0091 case JFFS2_NODETYPE_XREF:
0092 s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
0093 s->sum_num++;
0094 dbg_summary("xref added to summary\n");
0095 break;
0096 #endif
0097 default:
0098 JFFS2_WARNING("UNKNOWN node type %u\n",
0099 je16_to_cpu(item->u.nodetype));
0100 return 1;
0101 }
0102 return 0;
0103 }
0104
0105
0106
0107
0108 int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size)
0109 {
0110 dbg_summary("called with %u\n", size);
0111 s->sum_padded += size;
0112 return 0;
0113 }
0114
0115 int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri,
0116 uint32_t ofs)
0117 {
0118 struct jffs2_sum_inode_mem *temp = kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
0119
0120 if (!temp)
0121 return -ENOMEM;
0122
0123 temp->nodetype = ri->nodetype;
0124 temp->inode = ri->ino;
0125 temp->version = ri->version;
0126 temp->offset = cpu_to_je32(ofs);
0127 temp->totlen = ri->totlen;
0128 temp->next = NULL;
0129
0130 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
0131 }
0132
0133 int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd,
0134 uint32_t ofs)
0135 {
0136 struct jffs2_sum_dirent_mem *temp =
0137 kmalloc(sizeof(struct jffs2_sum_dirent_mem) + rd->nsize, GFP_KERNEL);
0138
0139 if (!temp)
0140 return -ENOMEM;
0141
0142 temp->nodetype = rd->nodetype;
0143 temp->totlen = rd->totlen;
0144 temp->offset = cpu_to_je32(ofs);
0145 temp->pino = rd->pino;
0146 temp->version = rd->version;
0147 temp->ino = rd->ino;
0148 temp->nsize = rd->nsize;
0149 temp->type = rd->type;
0150 temp->next = NULL;
0151
0152 memcpy(temp->name, rd->name, rd->nsize);
0153
0154 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
0155 }
0156
0157 #ifdef CONFIG_JFFS2_FS_XATTR
0158 int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
0159 {
0160 struct jffs2_sum_xattr_mem *temp;
0161
0162 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
0163 if (!temp)
0164 return -ENOMEM;
0165
0166 temp->nodetype = rx->nodetype;
0167 temp->xid = rx->xid;
0168 temp->version = rx->version;
0169 temp->offset = cpu_to_je32(ofs);
0170 temp->totlen = rx->totlen;
0171 temp->next = NULL;
0172
0173 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
0174 }
0175
0176 int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
0177 {
0178 struct jffs2_sum_xref_mem *temp;
0179
0180 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
0181 if (!temp)
0182 return -ENOMEM;
0183
0184 temp->nodetype = rr->nodetype;
0185 temp->offset = cpu_to_je32(ofs);
0186 temp->next = NULL;
0187
0188 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
0189 }
0190 #endif
0191
0192
0193 static void jffs2_sum_clean_collected(struct jffs2_summary *s)
0194 {
0195 union jffs2_sum_mem *temp;
0196
0197 if (!s->sum_list_head) {
0198 dbg_summary("already empty\n");
0199 }
0200 while (s->sum_list_head) {
0201 temp = s->sum_list_head;
0202 s->sum_list_head = s->sum_list_head->u.next;
0203 kfree(temp);
0204 }
0205 s->sum_list_tail = NULL;
0206 s->sum_padded = 0;
0207 s->sum_num = 0;
0208 }
0209
0210 void jffs2_sum_reset_collected(struct jffs2_summary *s)
0211 {
0212 dbg_summary("called\n");
0213 jffs2_sum_clean_collected(s);
0214 s->sum_size = 0;
0215 }
0216
0217 void jffs2_sum_disable_collecting(struct jffs2_summary *s)
0218 {
0219 dbg_summary("called\n");
0220 jffs2_sum_clean_collected(s);
0221 s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
0222 }
0223
0224 int jffs2_sum_is_disabled(struct jffs2_summary *s)
0225 {
0226 return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE);
0227 }
0228
0229
0230
0231 void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s)
0232 {
0233 dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n",
0234 c->summary->sum_size, c->summary->sum_num,
0235 s->sum_size, s->sum_num);
0236
0237 c->summary->sum_size = s->sum_size;
0238 c->summary->sum_num = s->sum_num;
0239 c->summary->sum_padded = s->sum_padded;
0240 c->summary->sum_list_head = s->sum_list_head;
0241 c->summary->sum_list_tail = s->sum_list_tail;
0242
0243 s->sum_list_head = s->sum_list_tail = NULL;
0244 }
0245
0246
0247
0248 int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
0249 unsigned long count, uint32_t ofs)
0250 {
0251 union jffs2_node_union *node;
0252 struct jffs2_eraseblock *jeb;
0253
0254 if (c->summary->sum_size == JFFS2_SUMMARY_NOSUM_SIZE) {
0255 dbg_summary("Summary is disabled for this jeb! Skipping summary info!\n");
0256 return 0;
0257 }
0258
0259 node = invecs[0].iov_base;
0260 jeb = &c->blocks[ofs / c->sector_size];
0261 ofs -= jeb->offset;
0262
0263 switch (je16_to_cpu(node->u.nodetype)) {
0264 case JFFS2_NODETYPE_INODE: {
0265 struct jffs2_sum_inode_mem *temp =
0266 kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
0267
0268 if (!temp)
0269 goto no_mem;
0270
0271 temp->nodetype = node->i.nodetype;
0272 temp->inode = node->i.ino;
0273 temp->version = node->i.version;
0274 temp->offset = cpu_to_je32(ofs);
0275 temp->totlen = node->i.totlen;
0276 temp->next = NULL;
0277
0278 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
0279 }
0280
0281 case JFFS2_NODETYPE_DIRENT: {
0282 struct jffs2_sum_dirent_mem *temp =
0283 kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL);
0284
0285 if (!temp)
0286 goto no_mem;
0287
0288 temp->nodetype = node->d.nodetype;
0289 temp->totlen = node->d.totlen;
0290 temp->offset = cpu_to_je32(ofs);
0291 temp->pino = node->d.pino;
0292 temp->version = node->d.version;
0293 temp->ino = node->d.ino;
0294 temp->nsize = node->d.nsize;
0295 temp->type = node->d.type;
0296 temp->next = NULL;
0297
0298 switch (count) {
0299 case 1:
0300 memcpy(temp->name,node->d.name,node->d.nsize);
0301 break;
0302
0303 case 2:
0304 memcpy(temp->name,invecs[1].iov_base,node->d.nsize);
0305 break;
0306
0307 default:
0308 BUG();
0309 break;
0310 }
0311
0312 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
0313 }
0314 #ifdef CONFIG_JFFS2_FS_XATTR
0315 case JFFS2_NODETYPE_XATTR: {
0316 struct jffs2_sum_xattr_mem *temp;
0317 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
0318 if (!temp)
0319 goto no_mem;
0320
0321 temp->nodetype = node->x.nodetype;
0322 temp->xid = node->x.xid;
0323 temp->version = node->x.version;
0324 temp->totlen = node->x.totlen;
0325 temp->offset = cpu_to_je32(ofs);
0326 temp->next = NULL;
0327
0328 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
0329 }
0330 case JFFS2_NODETYPE_XREF: {
0331 struct jffs2_sum_xref_mem *temp;
0332 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
0333 if (!temp)
0334 goto no_mem;
0335 temp->nodetype = node->r.nodetype;
0336 temp->offset = cpu_to_je32(ofs);
0337 temp->next = NULL;
0338
0339 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
0340 }
0341 #endif
0342 case JFFS2_NODETYPE_PADDING:
0343 dbg_summary("node PADDING\n");
0344 c->summary->sum_padded += je32_to_cpu(node->u.totlen);
0345 break;
0346
0347 case JFFS2_NODETYPE_CLEANMARKER:
0348 dbg_summary("node CLEANMARKER\n");
0349 break;
0350
0351 case JFFS2_NODETYPE_SUMMARY:
0352 dbg_summary("node SUMMARY\n");
0353 break;
0354
0355 default:
0356
0357
0358
0359 BUG();
0360 break;
0361 }
0362
0363 return 0;
0364
0365 no_mem:
0366 JFFS2_WARNING("MEMORY ALLOCATION ERROR!");
0367 return -ENOMEM;
0368 }
0369
0370 static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
0371 struct jffs2_eraseblock *jeb,
0372 uint32_t ofs, uint32_t len,
0373 struct jffs2_inode_cache *ic)
0374 {
0375
0376 if ((ofs & ~3) > c->sector_size - jeb->free_size) {
0377
0378 jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
0379 }
0380
0381 return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
0382 }
0383
0384
0385
0386 static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
0387 struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
0388 {
0389 struct jffs2_inode_cache *ic;
0390 struct jffs2_full_dirent *fd;
0391 void *sp;
0392 int i, ino;
0393 int err;
0394
0395 sp = summary->sum;
0396
0397 for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
0398 dbg_summary("processing summary index %d\n", i);
0399
0400 cond_resched();
0401
0402
0403 err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
0404 if (err)
0405 return err;
0406
0407 switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
0408 case JFFS2_NODETYPE_INODE: {
0409 struct jffs2_sum_inode_flash *spi;
0410 spi = sp;
0411
0412 ino = je32_to_cpu(spi->inode);
0413
0414 dbg_summary("Inode at 0x%08x-0x%08x\n",
0415 jeb->offset + je32_to_cpu(spi->offset),
0416 jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
0417
0418 ic = jffs2_scan_make_ino_cache(c, ino);
0419 if (!ic) {
0420 JFFS2_NOTICE("scan_make_ino_cache failed\n");
0421 return -ENOMEM;
0422 }
0423
0424 sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
0425 PAD(je32_to_cpu(spi->totlen)), ic);
0426
0427 *pseudo_random += je32_to_cpu(spi->version);
0428
0429 sp += JFFS2_SUMMARY_INODE_SIZE;
0430
0431 break;
0432 }
0433
0434 case JFFS2_NODETYPE_DIRENT: {
0435 struct jffs2_sum_dirent_flash *spd;
0436 int checkedlen;
0437 spd = sp;
0438
0439 dbg_summary("Dirent at 0x%08x-0x%08x\n",
0440 jeb->offset + je32_to_cpu(spd->offset),
0441 jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
0442
0443
0444
0445 checkedlen = strnlen(spd->name, spd->nsize);
0446 if (!checkedlen) {
0447 pr_err("Dirent at %08x has zero at start of name. Aborting mount.\n",
0448 jeb->offset +
0449 je32_to_cpu(spd->offset));
0450 return -EIO;
0451 }
0452 if (checkedlen < spd->nsize) {
0453 pr_err("Dirent at %08x has zeroes in name. Truncating to %d chars\n",
0454 jeb->offset +
0455 je32_to_cpu(spd->offset),
0456 checkedlen);
0457 }
0458
0459
0460 fd = jffs2_alloc_full_dirent(checkedlen+1);
0461 if (!fd)
0462 return -ENOMEM;
0463
0464 memcpy(&fd->name, spd->name, checkedlen);
0465 fd->name[checkedlen] = 0;
0466
0467 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
0468 if (!ic) {
0469 jffs2_free_full_dirent(fd);
0470 return -ENOMEM;
0471 }
0472
0473 fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_UNCHECKED,
0474 PAD(je32_to_cpu(spd->totlen)), ic);
0475
0476 fd->next = NULL;
0477 fd->version = je32_to_cpu(spd->version);
0478 fd->ino = je32_to_cpu(spd->ino);
0479 fd->nhash = full_name_hash(NULL, fd->name, checkedlen);
0480 fd->type = spd->type;
0481
0482 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
0483
0484 *pseudo_random += je32_to_cpu(spd->version);
0485
0486 sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
0487
0488 break;
0489 }
0490 #ifdef CONFIG_JFFS2_FS_XATTR
0491 case JFFS2_NODETYPE_XATTR: {
0492 struct jffs2_xattr_datum *xd;
0493 struct jffs2_sum_xattr_flash *spx;
0494
0495 spx = (struct jffs2_sum_xattr_flash *)sp;
0496 dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n",
0497 jeb->offset + je32_to_cpu(spx->offset),
0498 jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
0499 je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
0500
0501 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
0502 je32_to_cpu(spx->version));
0503 if (IS_ERR(xd))
0504 return PTR_ERR(xd);
0505 if (xd->version > je32_to_cpu(spx->version)) {
0506
0507 struct jffs2_raw_node_ref *raw
0508 = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
0509 PAD(je32_to_cpu(spx->totlen)), NULL);
0510 raw->next_in_ino = xd->node->next_in_ino;
0511 xd->node->next_in_ino = raw;
0512 } else {
0513 xd->version = je32_to_cpu(spx->version);
0514 sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
0515 PAD(je32_to_cpu(spx->totlen)), (void *)xd);
0516 }
0517 *pseudo_random += je32_to_cpu(spx->xid);
0518 sp += JFFS2_SUMMARY_XATTR_SIZE;
0519
0520 break;
0521 }
0522 case JFFS2_NODETYPE_XREF: {
0523 struct jffs2_xattr_ref *ref;
0524 struct jffs2_sum_xref_flash *spr;
0525
0526 spr = (struct jffs2_sum_xref_flash *)sp;
0527 dbg_summary("xref at %#08x-%#08x\n",
0528 jeb->offset + je32_to_cpu(spr->offset),
0529 jeb->offset + je32_to_cpu(spr->offset) +
0530 (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
0531
0532 ref = jffs2_alloc_xattr_ref();
0533 if (!ref) {
0534 JFFS2_NOTICE("allocation of xattr_datum failed\n");
0535 return -ENOMEM;
0536 }
0537 ref->next = c->xref_temp;
0538 c->xref_temp = ref;
0539
0540 sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
0541 PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
0542
0543 *pseudo_random += ref->node->flash_offset;
0544 sp += JFFS2_SUMMARY_XREF_SIZE;
0545
0546 break;
0547 }
0548 #endif
0549 default : {
0550 uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
0551 JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
0552 if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
0553 return -EIO;
0554
0555
0556 c->wasted_size -= jeb->wasted_size;
0557 c->free_size += c->sector_size - jeb->free_size;
0558 c->used_size -= jeb->used_size;
0559 c->dirty_size -= jeb->dirty_size;
0560 jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
0561 jeb->free_size = c->sector_size;
0562
0563 jffs2_free_jeb_node_refs(c, jeb);
0564 return -ENOTRECOVERABLE;
0565 }
0566 }
0567 }
0568 return 0;
0569 }
0570
0571
0572 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
0573 struct jffs2_raw_summary *summary, uint32_t sumsize,
0574 uint32_t *pseudo_random)
0575 {
0576 struct jffs2_unknown_node crcnode;
0577 int ret, ofs;
0578 uint32_t crc;
0579
0580 ofs = c->sector_size - sumsize;
0581
0582 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
0583 jeb->offset, jeb->offset + ofs, sumsize);
0584
0585
0586 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
0587 crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY);
0588 crcnode.totlen = summary->totlen;
0589 crc = crc32(0, &crcnode, sizeof(crcnode)-4);
0590
0591 if (je32_to_cpu(summary->hdr_crc) != crc) {
0592 dbg_summary("Summary node header is corrupt (bad CRC or "
0593 "no summary at all)\n");
0594 goto crc_err;
0595 }
0596
0597 if (je32_to_cpu(summary->totlen) != sumsize) {
0598 dbg_summary("Summary node is corrupt (wrong erasesize?)\n");
0599 goto crc_err;
0600 }
0601
0602 crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8);
0603
0604 if (je32_to_cpu(summary->node_crc) != crc) {
0605 dbg_summary("Summary node is corrupt (bad CRC)\n");
0606 goto crc_err;
0607 }
0608
0609 crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary));
0610
0611 if (je32_to_cpu(summary->sum_crc) != crc) {
0612 dbg_summary("Summary node data is corrupt (bad CRC)\n");
0613 goto crc_err;
0614 }
0615
0616 if ( je32_to_cpu(summary->cln_mkr) ) {
0617
0618 dbg_summary("Summary : CLEANMARKER node \n");
0619
0620 ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
0621 if (ret)
0622 return ret;
0623
0624 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
0625 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
0626 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
0627 if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
0628 return ret;
0629 } else if (jeb->first_node) {
0630 dbg_summary("CLEANMARKER node not first node in block "
0631 "(0x%08x)\n", jeb->offset);
0632 if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
0633 return ret;
0634 } else {
0635 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
0636 je32_to_cpu(summary->cln_mkr), NULL);
0637 }
0638 }
0639
0640 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
0641
0642
0643 if (ret == -ENOTRECOVERABLE)
0644 return 0;
0645 if (ret)
0646 return ret;
0647
0648
0649 ret = jffs2_prealloc_raw_node_refs(c, jeb, 2);
0650 if (ret)
0651 return ret;
0652
0653 sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL);
0654
0655 if (unlikely(jeb->free_size)) {
0656 JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
0657 jeb->free_size, jeb->offset);
0658 jeb->wasted_size += jeb->free_size;
0659 c->wasted_size += jeb->free_size;
0660 c->free_size -= jeb->free_size;
0661 jeb->free_size = 0;
0662 }
0663
0664 return jffs2_scan_classify_jeb(c, jeb);
0665
0666 crc_err:
0667 JFFS2_WARNING("Summary node crc error, skipping summary information.\n");
0668
0669 return 0;
0670 }
0671
0672
0673
0674 static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
0675 uint32_t infosize, uint32_t datasize, int padsize)
0676 {
0677 struct jffs2_raw_summary isum;
0678 union jffs2_sum_mem *temp;
0679 struct jffs2_sum_marker *sm;
0680 struct kvec vecs[2];
0681 uint32_t sum_ofs;
0682 void *wpage;
0683 int ret;
0684 size_t retlen;
0685
0686 if (padsize + datasize > MAX_SUMMARY_SIZE) {
0687
0688 jffs2_sum_disable_collecting(c->summary);
0689
0690 JFFS2_WARNING("Summary too big (%d data, %d pad) in eraseblock at %08x\n",
0691 datasize, padsize, jeb->offset);
0692
0693 return 0;
0694 }
0695
0696 if (padsize < 0) {
0697
0698 jffs2_sum_disable_collecting(c->summary);
0699
0700 JFFS2_WARNING("Not enough space for summary, padsize = %d\n",
0701 padsize);
0702
0703 return 0;
0704 }
0705
0706 memset(c->summary->sum_buf, 0xff, datasize);
0707 memset(&isum, 0, sizeof(isum));
0708
0709 isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
0710 isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY);
0711 isum.totlen = cpu_to_je32(infosize);
0712 isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4));
0713 isum.padded = cpu_to_je32(c->summary->sum_padded);
0714 isum.cln_mkr = cpu_to_je32(c->cleanmarker_size);
0715 isum.sum_num = cpu_to_je32(c->summary->sum_num);
0716 wpage = c->summary->sum_buf;
0717
0718 while (c->summary->sum_num) {
0719 temp = c->summary->sum_list_head;
0720
0721 switch (je16_to_cpu(temp->u.nodetype)) {
0722 case JFFS2_NODETYPE_INODE: {
0723 struct jffs2_sum_inode_flash *sino_ptr = wpage;
0724
0725 sino_ptr->nodetype = temp->i.nodetype;
0726 sino_ptr->inode = temp->i.inode;
0727 sino_ptr->version = temp->i.version;
0728 sino_ptr->offset = temp->i.offset;
0729 sino_ptr->totlen = temp->i.totlen;
0730
0731 wpage += JFFS2_SUMMARY_INODE_SIZE;
0732
0733 break;
0734 }
0735
0736 case JFFS2_NODETYPE_DIRENT: {
0737 struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
0738
0739 sdrnt_ptr->nodetype = temp->d.nodetype;
0740 sdrnt_ptr->totlen = temp->d.totlen;
0741 sdrnt_ptr->offset = temp->d.offset;
0742 sdrnt_ptr->pino = temp->d.pino;
0743 sdrnt_ptr->version = temp->d.version;
0744 sdrnt_ptr->ino = temp->d.ino;
0745 sdrnt_ptr->nsize = temp->d.nsize;
0746 sdrnt_ptr->type = temp->d.type;
0747
0748 memcpy(sdrnt_ptr->name, temp->d.name,
0749 temp->d.nsize);
0750
0751 wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
0752
0753 break;
0754 }
0755 #ifdef CONFIG_JFFS2_FS_XATTR
0756 case JFFS2_NODETYPE_XATTR: {
0757 struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
0758
0759 temp = c->summary->sum_list_head;
0760 sxattr_ptr->nodetype = temp->x.nodetype;
0761 sxattr_ptr->xid = temp->x.xid;
0762 sxattr_ptr->version = temp->x.version;
0763 sxattr_ptr->offset = temp->x.offset;
0764 sxattr_ptr->totlen = temp->x.totlen;
0765
0766 wpage += JFFS2_SUMMARY_XATTR_SIZE;
0767 break;
0768 }
0769 case JFFS2_NODETYPE_XREF: {
0770 struct jffs2_sum_xref_flash *sxref_ptr = wpage;
0771
0772 temp = c->summary->sum_list_head;
0773 sxref_ptr->nodetype = temp->r.nodetype;
0774 sxref_ptr->offset = temp->r.offset;
0775
0776 wpage += JFFS2_SUMMARY_XREF_SIZE;
0777 break;
0778 }
0779 #endif
0780 default : {
0781 if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
0782 == JFFS2_FEATURE_RWCOMPAT_COPY) {
0783 dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
0784 je16_to_cpu(temp->u.nodetype));
0785 jffs2_sum_disable_collecting(c->summary);
0786
0787 goto bail_rwcompat;
0788 } else {
0789 BUG();
0790 }
0791 }
0792 }
0793
0794 c->summary->sum_list_head = temp->u.next;
0795 kfree(temp);
0796
0797 c->summary->sum_num--;
0798 }
0799 bail_rwcompat:
0800
0801 jffs2_sum_reset_collected(c->summary);
0802
0803 wpage += padsize;
0804
0805 sm = wpage;
0806 sm->offset = cpu_to_je32(c->sector_size - jeb->free_size);
0807 sm->magic = cpu_to_je32(JFFS2_SUM_MAGIC);
0808
0809 isum.sum_crc = cpu_to_je32(crc32(0, c->summary->sum_buf, datasize));
0810 isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8));
0811
0812 vecs[0].iov_base = &isum;
0813 vecs[0].iov_len = sizeof(isum);
0814 vecs[1].iov_base = c->summary->sum_buf;
0815 vecs[1].iov_len = datasize;
0816
0817 sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
0818
0819 dbg_summary("writing out data to flash to pos : 0x%08x\n", sum_ofs);
0820
0821 ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
0822
0823 if (ret || (retlen != infosize)) {
0824
0825 JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
0826 infosize, sum_ofs, ret, retlen);
0827
0828 if (retlen) {
0829
0830 spin_lock(&c->erase_completion_lock);
0831 jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
0832 spin_unlock(&c->erase_completion_lock);
0833 }
0834
0835 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
0836
0837 return 0;
0838 }
0839
0840 spin_lock(&c->erase_completion_lock);
0841 jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
0842 spin_unlock(&c->erase_completion_lock);
0843
0844 return 0;
0845 }
0846
0847
0848
0849 int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
0850 __must_hold(&c->erase_completion_block)
0851 {
0852 int datasize, infosize, padsize;
0853 struct jffs2_eraseblock *jeb;
0854 int ret = 0;
0855
0856 dbg_summary("called\n");
0857
0858 spin_unlock(&c->erase_completion_lock);
0859
0860 jeb = c->nextblock;
0861 jffs2_prealloc_raw_node_refs(c, jeb, 1);
0862
0863 if (!c->summary->sum_num || !c->summary->sum_list_head) {
0864 JFFS2_WARNING("Empty summary info!!!\n");
0865 BUG();
0866 }
0867
0868 datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker);
0869 infosize = sizeof(struct jffs2_raw_summary) + datasize;
0870 padsize = jeb->free_size - infosize;
0871 infosize += padsize;
0872 datasize += padsize;
0873
0874 ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
0875 spin_lock(&c->erase_completion_lock);
0876 return ret;
0877 }