aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/jffs2/dir.c12
-rw-r--r--fs/jffs2/fs.c25
-rw-r--r--fs/jffs2/gc.c7
-rw-r--r--fs/jffs2/nodelist.h11
-rw-r--r--fs/jffs2/nodemgmt.c39
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/scan.c85
-rw-r--r--fs/jffs2/summary.c36
-rw-r--r--fs/jffs2/summary.h3
9 files changed, 122 insertions, 100 deletions
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index f1b18b99a3cd..ff1b7950dd44 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -629,12 +629,12 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
629 struct jffs2_full_dnode *fn; 629 struct jffs2_full_dnode *fn;
630 struct jffs2_full_dirent *fd; 630 struct jffs2_full_dirent *fd;
631 int namelen; 631 int namelen;
632 jint16_t dev; 632 union jffs2_device_node dev;
633 int devlen = 0; 633 int devlen = 0;
634 uint32_t alloclen, phys_ofs; 634 uint32_t alloclen, phys_ofs;
635 int ret; 635 int ret;
636 636
637 if (!old_valid_dev(rdev)) 637 if (!new_valid_dev(rdev))
638 return -EINVAL; 638 return -EINVAL;
639 639
640 ri = jffs2_alloc_raw_inode(); 640 ri = jffs2_alloc_raw_inode();
@@ -643,17 +643,15 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
643 643
644 c = JFFS2_SB_INFO(dir_i->i_sb); 644 c = JFFS2_SB_INFO(dir_i->i_sb);
645 645
646 if (S_ISBLK(mode) || S_ISCHR(mode)) { 646 if (S_ISBLK(mode) || S_ISCHR(mode))
647 dev = cpu_to_je16(old_encode_dev(rdev)); 647 devlen = jffs2_encode_dev(&dev, rdev);
648 devlen = sizeof(dev);
649 }
650 648
651 /* Try to reserve enough space for both node and dirent. 649 /* Try to reserve enough space for both node and dirent.
652 * Just the node will do for now, though 650 * Just the node will do for now, though
653 */ 651 */
654 namelen = dentry->d_name.len; 652 namelen = dentry->d_name.len;
655 ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, 653 ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen,
656 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 654 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
657 655
658 if (ret) { 656 if (ret) {
659 jffs2_free_raw_inode(ri); 657 jffs2_free_raw_inode(ri);
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 4607cdc4c46d..a0f84673ce54 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -33,7 +33,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
33 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 33 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
34 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 34 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
35 struct jffs2_raw_inode *ri; 35 struct jffs2_raw_inode *ri;
36 unsigned short dev; 36 union jffs2_device_node dev;
37 unsigned char *mdata = NULL; 37 unsigned char *mdata = NULL;
38 int mdatalen = 0; 38 int mdatalen = 0;
39 unsigned int ivalid; 39 unsigned int ivalid;
@@ -51,9 +51,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
51 it out again with the appropriate data attached */ 51 it out again with the appropriate data attached */
52 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { 52 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
53 /* For these, we don't actually need to read the old node */ 53 /* For these, we don't actually need to read the old node */
54 dev = old_encode_dev(inode->i_rdev); 54 mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
55 mdata = (char *)&dev; 55 mdata = (char *)&dev;
56 mdatalen = sizeof(dev);
57 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); 56 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
58 } else if (S_ISLNK(inode->i_mode)) { 57 } else if (S_ISLNK(inode->i_mode)) {
59 down(&f->sem); 58 down(&f->sem);
@@ -238,6 +237,8 @@ void jffs2_read_inode (struct inode *inode)
238 struct jffs2_inode_info *f; 237 struct jffs2_inode_info *f;
239 struct jffs2_sb_info *c; 238 struct jffs2_sb_info *c;
240 struct jffs2_raw_inode latest_node; 239 struct jffs2_raw_inode latest_node;
240 union jffs2_device_node jdev;
241 dev_t rdev = 0;
241 int ret; 242 int ret;
242 243
243 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); 244 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
@@ -269,7 +270,6 @@ void jffs2_read_inode (struct inode *inode)
269 inode->i_blocks = (inode->i_size + 511) >> 9; 270 inode->i_blocks = (inode->i_size + 511) >> 9;
270 271
271 switch (inode->i_mode & S_IFMT) { 272 switch (inode->i_mode & S_IFMT) {
272 jint16_t rdev;
273 273
274 case S_IFLNK: 274 case S_IFLNK:
275 inode->i_op = &jffs2_symlink_inode_operations; 275 inode->i_op = &jffs2_symlink_inode_operations;
@@ -303,8 +303,16 @@ void jffs2_read_inode (struct inode *inode)
303 case S_IFBLK: 303 case S_IFBLK:
304 case S_IFCHR: 304 case S_IFCHR:
305 /* Read the device numbers from the media */ 305 /* Read the device numbers from the media */
306 if (f->metadata->size != sizeof(jdev.old) &&
307 f->metadata->size != sizeof(jdev.new)) {
308 printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
309 up(&f->sem);
310 jffs2_do_clear_inode(c, f);
311 make_bad_inode(inode);
312 return;
313 }
306 D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); 314 D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
307 if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { 315 if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
308 /* Eep */ 316 /* Eep */
309 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); 317 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
310 up(&f->sem); 318 up(&f->sem);
@@ -312,12 +320,15 @@ void jffs2_read_inode (struct inode *inode)
312 make_bad_inode(inode); 320 make_bad_inode(inode);
313 return; 321 return;
314 } 322 }
323 if (f->metadata->size == sizeof(jdev.old))
324 rdev = old_decode_dev(je16_to_cpu(jdev.old));
325 else
326 rdev = new_decode_dev(je32_to_cpu(jdev.new));
315 327
316 case S_IFSOCK: 328 case S_IFSOCK:
317 case S_IFIFO: 329 case S_IFIFO:
318 inode->i_op = &jffs2_file_inode_operations; 330 inode->i_op = &jffs2_file_inode_operations;
319 init_special_inode(inode, inode->i_mode, 331 init_special_inode(inode, inode->i_mode, rdev);
320 old_decode_dev((je16_to_cpu(rdev))));
321 break; 332 break;
322 333
323 default: 334 default:
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index a5ef9814f165..23587f8a221f 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -700,7 +700,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
700 struct jffs2_full_dnode *new_fn; 700 struct jffs2_full_dnode *new_fn;
701 struct jffs2_raw_inode ri; 701 struct jffs2_raw_inode ri;
702 struct jffs2_node_frag *last_frag; 702 struct jffs2_node_frag *last_frag;
703 jint16_t dev; 703 union jffs2_device_node dev;
704 char *mdata = NULL, mdatalen = 0; 704 char *mdata = NULL, mdatalen = 0;
705 uint32_t alloclen, phys_ofs, ilen; 705 uint32_t alloclen, phys_ofs, ilen;
706 int ret; 706 int ret;
@@ -708,11 +708,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
708 if (S_ISBLK(JFFS2_F_I_MODE(f)) || 708 if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
709 S_ISCHR(JFFS2_F_I_MODE(f)) ) { 709 S_ISCHR(JFFS2_F_I_MODE(f)) ) {
710 /* For these, we don't actually need to read the old node */ 710 /* For these, we don't actually need to read the old node */
711 /* FIXME: for minor or major > 255. */ 711 mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
712 dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) |
713 JFFS2_F_I_RDEV_MIN(f)));
714 mdata = (char *)&dev; 712 mdata = (char *)&dev;
715 mdatalen = sizeof(dev);
716 D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); 713 D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
717 } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { 714 } else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
718 mdatalen = fn->size; 715 mdatalen = fn->size;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 351d947c9375..8dda98ff5561 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -281,6 +281,17 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
281 281
282#define PAD(x) (((x)+3)&~3) 282#define PAD(x) (((x)+3)&~3)
283 283
284static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
285{
286 if (old_valid_dev(rdev)) {
287 jdev->old = cpu_to_je16(old_encode_dev(rdev));
288 return sizeof(jdev->old);
289 } else {
290 jdev->new = cpu_to_je32(new_encode_dev(rdev));
291 return sizeof(jdev->new);
292 }
293}
294
284static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) 295static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
285{ 296{
286 while(raw->next_in_ino) { 297 while(raw->next_in_ino) {
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 49127a1f0458..0e1f58aa606c 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -470,6 +470,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
470 struct jffs2_unknown_node n; 470 struct jffs2_unknown_node n;
471 int ret, addedsize; 471 int ret, addedsize;
472 size_t retlen; 472 size_t retlen;
473 uint32_t freed_len;
473 474
474 if(!ref) { 475 if(!ref) {
475 printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); 476 printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
@@ -499,32 +500,34 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
499 500
500 spin_lock(&c->erase_completion_lock); 501 spin_lock(&c->erase_completion_lock);
501 502
503 freed_len = ref_totlen(c, jeb, ref);
504
502 if (ref_flags(ref) == REF_UNCHECKED) { 505 if (ref_flags(ref) == REF_UNCHECKED) {
503 D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { 506 D1(if (unlikely(jeb->unchecked_size < freed_len)) {
504 printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", 507 printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
505 ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); 508 freed_len, blocknr, ref->flash_offset, jeb->used_size);
506 BUG(); 509 BUG();
507 }) 510 })
508 D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); 511 D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), freed_len));
509 jeb->unchecked_size -= ref_totlen(c, jeb, ref); 512 jeb->unchecked_size -= freed_len;
510 c->unchecked_size -= ref_totlen(c, jeb, ref); 513 c->unchecked_size -= freed_len;
511 } else { 514 } else {
512 D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { 515 D1(if (unlikely(jeb->used_size < freed_len)) {
513 printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", 516 printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
514 ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); 517 freed_len, blocknr, ref->flash_offset, jeb->used_size);
515 BUG(); 518 BUG();
516 }) 519 })
517 D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); 520 D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), freed_len));
518 jeb->used_size -= ref_totlen(c, jeb, ref); 521 jeb->used_size -= freed_len;
519 c->used_size -= ref_totlen(c, jeb, ref); 522 c->used_size -= freed_len;
520 } 523 }
521 524
522 // Take care, that wasted size is taken into concern 525 // Take care, that wasted size is taken into concern
523 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { 526 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
524 D1(printk(KERN_DEBUG "Dirtying\n")); 527 D1(printk(KERN_DEBUG "Dirtying\n"));
525 addedsize = ref_totlen(c, jeb, ref); 528 addedsize = freed_len;
526 jeb->dirty_size += ref_totlen(c, jeb, ref); 529 jeb->dirty_size += freed_len;
527 c->dirty_size += ref_totlen(c, jeb, ref); 530 c->dirty_size += freed_len;
528 531
529 /* Convert wasted space to dirty, if not a bad block */ 532 /* Convert wasted space to dirty, if not a bad block */
530 if (jeb->wasted_size) { 533 if (jeb->wasted_size) {
@@ -545,8 +548,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
545 } else { 548 } else {
546 D1(printk(KERN_DEBUG "Wasting\n")); 549 D1(printk(KERN_DEBUG "Wasting\n"));
547 addedsize = 0; 550 addedsize = 0;
548 jeb->wasted_size += ref_totlen(c, jeb, ref); 551 jeb->wasted_size += freed_len;
549 c->wasted_size += ref_totlen(c, jeb, ref); 552 c->wasted_size += freed_len;
550 } 553 }
551 ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; 554 ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
552 555
@@ -634,8 +637,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
634 printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); 637 printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen);
635 goto out_erase_sem; 638 goto out_erase_sem;
636 } 639 }
637 if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { 640 if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
638 printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); 641 printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), freed_len);
639 goto out_erase_sem; 642 goto out_erase_sem;
640 } 643 }
641 if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { 644 if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 9936ae23f8dc..d2ad2a2081d8 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -31,9 +31,7 @@ struct kvec;
31#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) 31#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
32#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) 32#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
33#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) 33#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
34 34#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
35#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f)))
36#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f)))
37 35
38#define ITIME(sec) ((struct timespec){sec, 0}) 36#define ITIME(sec) ((struct timespec){sec, 0})
39#define I_SEC(tv) ((tv).tv_sec) 37#define I_SEC(tv) ((tv).tv_sec)
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 5847e76ce16c..40d62d057aa4 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -437,11 +437,12 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
437} 437}
438#endif 438#endif
439 439
440/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
441 the flash, XIP-style */
440static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 442static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
441 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { 443 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
442 struct jffs2_unknown_node *node; 444 struct jffs2_unknown_node *node;
443 struct jffs2_unknown_node crcnode; 445 struct jffs2_unknown_node crcnode;
444 struct jffs2_sum_marker *sm;
445 uint32_t ofs, prevofs; 446 uint32_t ofs, prevofs;
446 uint32_t hdr_crc, buf_ofs, buf_len; 447 uint32_t hdr_crc, buf_ofs, buf_len;
447 int err; 448 int err;
@@ -475,44 +476,70 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
475#endif 476#endif
476 477
477 if (jffs2_sum_active()) { 478 if (jffs2_sum_active()) {
478 sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); 479 struct jffs2_sum_marker *sm;
479 if (!sm) { 480 void *sumptr = NULL;
480 return -ENOMEM; 481 uint32_t sumlen;
481 } 482
483 if (!buf_size) {
484 /* XIP case. Just look, point at the summary if it's there */
485 sm = (void *)buf + jeb->offset - sizeof(*sm);
486 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
487 sumptr = buf + je32_to_cpu(sm->offset);
488 sumlen = c->sector_size - je32_to_cpu(sm->offset);
489 }
490 } else {
491 /* If NAND flash, read a whole page of it. Else just the end */
492 if (c->wbuf_pagesize)
493 buf_len = c->wbuf_pagesize;
494 else
495 buf_len = sizeof(*sm);
496
497 /* Read as much as we want into the _end_ of the preallocated buffer */
498 err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
499 jeb->offset + c->sector_size - buf_len,
500 buf_len);
501 if (err)
502 return err;
503
504 sm = (void *)buf + buf_size - sizeof(*sm);
505 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
506 sumlen = c->sector_size - je32_to_cpu(sm->offset);
507 sumptr = buf + buf_size - sumlen;
508
509 /* Now, make sure the summary itself is available */
510 if (sumlen > buf_size) {
511 /* Need to kmalloc for this. */
512 sumptr = kmalloc(sumlen, GFP_KERNEL);
513 if (!sumptr)
514 return -ENOMEM;
515 memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
516 }
517 if (buf_len < sumlen) {
518 /* Need to read more so that the entire summary node is present */
519 err = jffs2_fill_scan_buf(c, sumptr,
520 jeb->offset + c->sector_size - sumlen,
521 sumlen - buf_len);
522 if (err)
523 return err;
524 }
525 }
482 526
483 err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
484 sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
485 if (err) {
486 kfree(sm);
487 return err;
488 } 527 }
489 528
490 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { 529 if (sumptr) {
491 err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); 530 err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
492 if (err) { 531 if (err)
493 kfree(sm);
494 return err; 532 return err;
495 } 533 if (buf_size && sumlen > buf_size)
534 kfree(sumptr);
496 } 535 }
497
498 kfree(sm);
499
500 ofs = jeb->offset;
501 prevofs = jeb->offset - 1;
502 } 536 }
503 537
504 buf_ofs = jeb->offset; 538 buf_ofs = jeb->offset;
505 539
506 if (!buf_size) { 540 if (!buf_size) {
541 /* This is the XIP case -- we're reading _directly_ from the flash chip */
507 buf_len = c->sector_size; 542 buf_len = c->sector_size;
508
509 if (jffs2_sum_active()) {
510 /* must reread because of summary test */
511 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
512 if (err)
513 return err;
514 }
515
516 } else { 543 } else {
517 buf_len = EMPTY_SCAN_SIZE(c->sector_size); 544 buf_len = EMPTY_SCAN_SIZE(c->sector_size);
518 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); 545 err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 439b9f6d5837..5dbe87b67ab6 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -399,7 +399,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
399 raw = jffs2_alloc_raw_node_ref(); 399 raw = jffs2_alloc_raw_node_ref();
400 if (!raw) { 400 if (!raw) {
401 JFFS2_NOTICE("allocation of node reference failed\n"); 401 JFFS2_NOTICE("allocation of node reference failed\n");
402 kfree(summary);
403 return -ENOMEM; 402 return -ENOMEM;
404 } 403 }
405 404
@@ -407,7 +406,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
407 if (!ic) { 406 if (!ic) {
408 JFFS2_NOTICE("scan_make_ino_cache failed\n"); 407 JFFS2_NOTICE("scan_make_ino_cache failed\n");
409 jffs2_free_raw_node_ref(raw); 408 jffs2_free_raw_node_ref(raw);
410 kfree(summary);
411 return -ENOMEM; 409 return -ENOMEM;
412 } 410 }
413 411
@@ -439,10 +437,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
439 jeb->offset + je32_to_cpu(spd->offset)); 437 jeb->offset + je32_to_cpu(spd->offset));
440 438
441 fd = jffs2_alloc_full_dirent(spd->nsize+1); 439 fd = jffs2_alloc_full_dirent(spd->nsize+1);
442 if (!fd) { 440 if (!fd)
443 kfree(summary);
444 return -ENOMEM; 441 return -ENOMEM;
445 }
446 442
447 memcpy(&fd->name, spd->name, spd->nsize); 443 memcpy(&fd->name, spd->name, spd->nsize);
448 fd->name[spd->nsize] = 0; 444 fd->name[spd->nsize] = 0;
@@ -451,7 +447,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
451 if (!raw) { 447 if (!raw) {
452 jffs2_free_full_dirent(fd); 448 jffs2_free_full_dirent(fd);
453 JFFS2_NOTICE("allocation of node reference failed\n"); 449 JFFS2_NOTICE("allocation of node reference failed\n");
454 kfree(summary);
455 return -ENOMEM; 450 return -ENOMEM;
456 } 451 }
457 452
@@ -459,7 +454,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
459 if (!ic) { 454 if (!ic) {
460 jffs2_free_full_dirent(fd); 455 jffs2_free_full_dirent(fd);
461 jffs2_free_raw_node_ref(raw); 456 jffs2_free_raw_node_ref(raw);
462 kfree(summary);
463 return -ENOMEM; 457 return -ENOMEM;
464 } 458 }
465 459
@@ -585,45 +579,28 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
585 default : { 579 default : {
586printk("nodetype = %#04x\n",je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)); 580printk("nodetype = %#04x\n",je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype));
587 JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); 581 JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
588 kfree(summary);
589 return -EIO; 582 return -EIO;
590 } 583 }
591 } 584 }
592 } 585 }
593 586
594 kfree(summary);
595 return 0; 587 return 0;
596} 588}
597 589
598/* Process the summary node - called from jffs2_scan_eraseblock() */ 590/* Process the summary node - called from jffs2_scan_eraseblock() */
599
600int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 591int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
601 uint32_t ofs, uint32_t *pseudo_random) 592 struct jffs2_raw_summary *summary, uint32_t sumsize,
593 uint32_t *pseudo_random)
602{ 594{
603 struct jffs2_unknown_node crcnode; 595 struct jffs2_unknown_node crcnode;
604 struct jffs2_raw_node_ref *cache_ref; 596 struct jffs2_raw_node_ref *cache_ref;
605 struct jffs2_raw_summary *summary; 597 int ret, ofs;
606 int ret, sumsize;
607 uint32_t crc; 598 uint32_t crc;
608 599
609 sumsize = c->sector_size - ofs; 600 ofs = jeb->offset + c->sector_size - sumsize;
610 ofs += jeb->offset;
611 601
612 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", 602 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
613 jeb->offset, ofs, sumsize); 603 jeb->offset, ofs, sumsize);
614
615 summary = kmalloc(sumsize, GFP_KERNEL);
616
617 if (!summary) {
618 return -ENOMEM;
619 }
620
621 ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
622
623 if (ret) {
624 kfree(summary);
625 return ret;
626 }
627 604
628 /* OK, now check for node validity and CRC */ 605 /* OK, now check for node validity and CRC */
629 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 606 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -673,7 +650,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
673 650
674 if (!marker_ref) { 651 if (!marker_ref) {
675 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); 652 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
676 kfree(summary);
677 return -ENOMEM; 653 return -ENOMEM;
678 } 654 }
679 655
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index a3b66c18aae9..ce892d57ad59 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -200,7 +200,8 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r
200int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs); 200int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs);
201int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs); 201int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs);
202int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 202int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
203 uint32_t ofs, uint32_t *pseudo_random); 203 struct jffs2_raw_summary *summary, uint32_t sumlen,
204 uint32_t *pseudo_random);
204 205
205#else /* SUMMARY DISABLED */ 206#else /* SUMMARY DISABLED */
206 207