diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/dir.c | 12 | ||||
-rw-r--r-- | fs/jffs2/fs.c | 25 | ||||
-rw-r--r-- | fs/jffs2/gc.c | 7 | ||||
-rw-r--r-- | fs/jffs2/nodelist.h | 11 | ||||
-rw-r--r-- | fs/jffs2/nodemgmt.c | 39 | ||||
-rw-r--r-- | fs/jffs2/os-linux.h | 4 | ||||
-rw-r--r-- | fs/jffs2/scan.c | 85 | ||||
-rw-r--r-- | fs/jffs2/summary.c | 36 | ||||
-rw-r--r-- | fs/jffs2/summary.h | 3 |
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 | ||
284 | static 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 | |||
284 | static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) | 295 | static 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 */ | ||
440 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 442 | static 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 : { |
586 | printk("nodetype = %#04x\n",je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)); | 580 | printk("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 | |||
600 | int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 591 | int 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 | |||
200 | int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs); | 200 | int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs); |
201 | int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs); | 201 | int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs); |
202 | int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 202 | int 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 | ||