return DEFAULT_EMPTY_SCAN_SIZE;
}
-static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
-{
- int ret;
-
- if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
- return ret;
- if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
- return ret;
- /* Turned wasted size into dirty, since we apparently
- think it's recoverable now. */
- jeb->dirty_size += jeb->wasted_size;
- c->dirty_size += jeb->wasted_size;
- c->wasted_size -= jeb->wasted_size;
- jeb->wasted_size = 0;
- if (VERYDIRTY(c, jeb->dirty_size)) {
- list_add(&jeb->list, &c->very_dirty_list);
- } else {
- list_add(&jeb->list, &c->dirty_list);
- }
- return 0;
-}
-
int jffs2_scan_medium(struct jffs2_sb_info *c)
{
int i, ret;
(!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
/* Better candidate for the next writes to go to */
if (c->nextblock) {
- ret = file_dirty(c, c->nextblock);
- if (ret)
- return ret;
+ c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
+ c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
+ c->free_size -= c->nextblock->free_size;
+ c->wasted_size -= c->nextblock->wasted_size;
+ c->nextblock->free_size = c->nextblock->wasted_size = 0;
+ if (VERYDIRTY(c, c->nextblock->dirty_size)) {
+ list_add(&c->nextblock->list, &c->very_dirty_list);
+ } else {
+ list_add(&c->nextblock->list, &c->dirty_list);
+ }
/* deleting summary information of the old nextblock */
jffs2_sum_reset_collected(c->summary);
}
- /* update collected summary information for the current nextblock */
+ /* update collected summary infromation for the current nextblock */
jffs2_sum_move_collected(c, s);
D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset));
c->nextblock = jeb;
} else {
- ret = file_dirty(c, jeb);
- if (ret)
- return ret;
+ jeb->dirty_size += jeb->free_size + jeb->wasted_size;
+ c->dirty_size += jeb->free_size + jeb->wasted_size;
+ c->free_size -= jeb->free_size;
+ c->wasted_size -= jeb->wasted_size;
+ jeb->free_size = jeb->wasted_size = 0;
+ if (VERYDIRTY(c, jeb->dirty_size)) {
+ list_add(&jeb->list, &c->very_dirty_list);
+ } else {
+ list_add(&jeb->list, &c->dirty_list);
+ }
}
break;
}
}
+ if (jffs2_sum_active() && s)
+ kfree(s);
+
/* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
if (c->nextblock && (c->nextblock->dirty_size)) {
c->nextblock->wasted_size += c->nextblock->dirty_size;
D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
skip));
- jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
- jffs2_scan_dirty_space(c, c->nextblock, skip);
+ c->nextblock->wasted_size += skip;
+ c->wasted_size += skip;
+
+ c->nextblock->free_size -= skip;
+ c->free_size -= skip;
}
#endif
if (c->nr_erasing_blocks) {
else
c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
#endif
- if (s)
- kfree(s);
-
return ret;
}
-static int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
- uint32_t ofs, uint32_t len)
+int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf,
+ uint32_t ofs, uint32_t len)
{
int ret;
size_t retlen;
int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{
if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
- && (!jeb->first_node || !ref_next(jeb->first_node)) )
+ && (!jeb->first_node || !jeb->first_node->next_phys) )
return BLK_STATE_CLEANMARKER;
/* move blocks with max 4 byte dirty space to cleanlist */
return BLK_STATE_ALLDIRTY;
}
-#ifdef CONFIG_JFFS2_FS_XATTR
-static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
- struct jffs2_raw_xattr *rx, uint32_t ofs,
- struct jffs2_summary *s)
-{
- struct jffs2_xattr_datum *xd;
- uint32_t xid, version, totlen, crc;
- int err;
-
- crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
- if (crc != je32_to_cpu(rx->node_crc)) {
- JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
- ofs, je32_to_cpu(rx->node_crc), crc);
- if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
- return err;
- return 0;
- }
-
- xid = je32_to_cpu(rx->xid);
- version = je32_to_cpu(rx->version);
-
- totlen = PAD(sizeof(struct jffs2_raw_xattr)
- + rx->name_len + 1 + je16_to_cpu(rx->value_len));
- if (totlen != je32_to_cpu(rx->totlen)) {
- JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
- ofs, je32_to_cpu(rx->totlen), totlen);
- if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
- return err;
- return 0;
- }
-
- xd = jffs2_setup_xattr_datum(c, xid, version);
- if (IS_ERR(xd))
- return PTR_ERR(xd);
-
- if (xd->version > version) {
- struct jffs2_raw_node_ref *raw
- = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
- raw->next_in_ino = xd->node->next_in_ino;
- xd->node->next_in_ino = raw;
- } else {
- xd->version = version;
- xd->xprefix = rx->xprefix;
- xd->name_len = rx->name_len;
- xd->value_len = je16_to_cpu(rx->value_len);
- xd->data_crc = je32_to_cpu(rx->data_crc);
-
- jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
- }
-
- if (jffs2_sum_active())
- jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
- dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
- ofs, xd->xid, xd->version);
- return 0;
-}
-
-static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
- struct jffs2_raw_xref *rr, uint32_t ofs,
- struct jffs2_summary *s)
-{
- struct jffs2_xattr_ref *ref;
- uint32_t crc;
- int err;
-
- crc = crc32(0, rr, sizeof(*rr) - 4);
- if (crc != je32_to_cpu(rr->node_crc)) {
- JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
- ofs, je32_to_cpu(rr->node_crc), crc);
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
- return err;
- return 0;
- }
-
- if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
- JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n",
- ofs, je32_to_cpu(rr->totlen),
- PAD(sizeof(struct jffs2_raw_xref)));
- if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
- return err;
- return 0;
- }
-
- ref = jffs2_alloc_xattr_ref();
- if (!ref)
- return -ENOMEM;
-
- /* BEFORE jffs2_build_xattr_subsystem() called,
- * and AFTER xattr_ref is marked as a dead xref,
- * ref->xid is used to store 32bit xid, xd is not used
- * ref->ino is used to store 32bit inode-number, ic is not used
- * Thoes variables are declared as union, thus using those
- * are exclusive. In a similar way, ref->next is temporarily
- * used to chain all xattr_ref object. It's re-chained to
- * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
- */
- ref->ino = je32_to_cpu(rr->ino);
- ref->xid = je32_to_cpu(rr->xid);
- ref->xseqno = je32_to_cpu(rr->xseqno);
- if (ref->xseqno > c->highest_xseqno)
- c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
- ref->next = c->xref_temp;
- c->xref_temp = ref;
-
- jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
-
- if (jffs2_sum_active())
- jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
- dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
- ofs, ref->xid, ref->ino);
- return 0;
-}
-#endif
-
-/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
- the flash, XIP-style */
static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
- unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
+ unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
struct jffs2_unknown_node *node;
struct jffs2_unknown_node crcnode;
+ struct jffs2_sum_marker *sm;
uint32_t ofs, prevofs;
uint32_t hdr_crc, buf_ofs, buf_len;
int err;
#endif
if (jffs2_sum_active()) {
- struct jffs2_sum_marker *sm;
- void *sumptr = NULL;
- uint32_t sumlen;
-
- if (!buf_size) {
- /* XIP case. Just look, point at the summary if it's there */
- sm = (void *)buf + c->sector_size - sizeof(*sm);
- if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
- sumptr = buf + je32_to_cpu(sm->offset);
- sumlen = c->sector_size - je32_to_cpu(sm->offset);
- }
- } else {
- /* If NAND flash, read a whole page of it. Else just the end */
- if (c->wbuf_pagesize)
- buf_len = c->wbuf_pagesize;
- else
- buf_len = sizeof(*sm);
-
- /* Read as much as we want into the _end_ of the preallocated buffer */
- err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
- jeb->offset + c->sector_size - buf_len,
- buf_len);
- if (err)
- return err;
-
- sm = (void *)buf + buf_size - sizeof(*sm);
- if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
- sumlen = c->sector_size - je32_to_cpu(sm->offset);
- sumptr = buf + buf_size - sumlen;
-
- /* Now, make sure the summary itself is available */
- if (sumlen > buf_size) {
- /* Need to kmalloc for this. */
- sumptr = kmalloc(sumlen, GFP_KERNEL);
- if (!sumptr)
- return -ENOMEM;
- memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
- }
- if (buf_len < sumlen) {
- /* Need to read more so that the entire summary node is present */
- err = jffs2_fill_scan_buf(c, sumptr,
- jeb->offset + c->sector_size - sumlen,
- sumlen - buf_len);
- if (err)
- return err;
- }
- }
-
+ sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL);
+ if (!sm) {
+ return -ENOMEM;
}
- if (sumptr) {
- err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
+ err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
+ sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
+ if (err) {
+ kfree(sm);
+ return err;
+ }
- if (buf_size && sumlen > buf_size)
- kfree(sumptr);
- /* If it returns with a real error, bail.
- If it returns positive, that's a block classification
- (i.e. BLK_STATE_xxx) so return that too.
- If it returns zero, fall through to full scan. */
- if (err)
+ if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) {
+ err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random);
+ if (err) {
+ kfree(sm);
return err;
+ }
}
+
+ kfree(sm);
+
+ ofs = jeb->offset;
+ prevofs = jeb->offset - 1;
}
buf_ofs = jeb->offset;
if (!buf_size) {
- /* This is the XIP case -- we're reading _directly_ from the flash chip */
buf_len = c->sector_size;
+
+ if (jffs2_sum_active()) {
+ /* must reread because of summary test */
+ err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
+ if (err)
+ return err;
+ }
+
} else {
buf_len = EMPTY_SCAN_SIZE(c->sector_size);
err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
if (ofs) {
D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
jeb->offset + ofs));
- if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
- return err;
- if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
- return err;
+ DIRTY_SPACE(ofs);
}
/* Now ofs is a complete physical flash offset as it always was... */
jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
- /* Make sure there are node refs available for use */
- err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
- if (err)
- return err;
-
cond_resched();
if (ofs & 3) {
}
if (ofs == prevofs) {
printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs);
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node),
jeb->offset, c->sector_size, ofs, sizeof(*node)));
- if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
- return err;
+ DIRTY_SPACE((jeb->offset + c->sector_size)-ofs);
break;
}
if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
empty_start, ofs);
- if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
- return err;
+ DIRTY_SPACE(ofs-empty_start);
goto scan_more;
}
/* If we're only checking the beginning of a block with a cleanmarker,
bail now */
if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
- c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
+ c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) {
D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
return BLK_STATE_CLEANMARKER;
}
if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs);
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs));
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);
printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n",
JFFS2_MAGIC_BITMASK, ofs,
je16_to_cpu(node->magic));
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
je32_to_cpu(node->totlen),
je32_to_cpu(node->hdr_crc),
hdr_crc);
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
ofs, je32_to_cpu(node->totlen));
printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
- if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
- return err;
+ DIRTY_SPACE(4);
ofs += 4;
continue;
}
if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
/* Wheee. This is an obsoleted node */
D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
ofs += PAD(je32_to_cpu(node->totlen));
continue;
}
ofs += PAD(je32_to_cpu(node->totlen));
break;
-#ifdef CONFIG_JFFS2_FS_XATTR
- case JFFS2_NODETYPE_XATTR:
- if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
- buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
- D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
- " left to end of buf. Reading 0x%x at 0x%08x\n",
- je32_to_cpu(node->totlen), buf_len, ofs));
- err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
- if (err)
- return err;
- buf_ofs = ofs;
- node = (void *)buf;
- }
- err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
- if (err)
- return err;
- ofs += PAD(je32_to_cpu(node->totlen));
- break;
- case JFFS2_NODETYPE_XREF:
- if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
- buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
- D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
- " left to end of buf. Reading 0x%x at 0x%08x\n",
- je32_to_cpu(node->totlen), buf_len, ofs));
- err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
- if (err)
- return err;
- buf_ofs = ofs;
- node = (void *)buf;
- }
- err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
- if (err)
- return err;
- ofs += PAD(je32_to_cpu(node->totlen));
- break;
-#endif /* CONFIG_JFFS2_FS_XATTR */
-
case JFFS2_NODETYPE_CLEANMARKER:
D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
- return err;
+ DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
ofs += PAD(sizeof(struct jffs2_unknown_node));
} else if (jeb->first_node) {
printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
- return err;
+ DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
ofs += PAD(sizeof(struct jffs2_unknown_node));
} else {
- jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
+ struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
+ if (!marker_ref) {
+ printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");
+ return -ENOMEM;
+ }
+ marker_ref->next_in_ino = NULL;
+ marker_ref->next_phys = NULL;
+ marker_ref->flash_offset = ofs | REF_NORMAL;
+ marker_ref->__totlen = c->cleanmarker_size;
+ jeb->first_node = jeb->last_node = marker_ref;
+ USED_SPACE(PAD(c->cleanmarker_size));
ofs += PAD(c->cleanmarker_size);
}
break;
case JFFS2_NODETYPE_PADDING:
if (jffs2_sum_active())
jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
ofs += PAD(je32_to_cpu(node->totlen));
break;
c->flags |= JFFS2_SB_FLAG_RO;
if (!(jffs2_is_readonly(c)))
return -EROFS;
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
ofs += PAD(je32_to_cpu(node->totlen));
break;
case JFFS2_FEATURE_RWCOMPAT_DELETE:
D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
ofs += PAD(je32_to_cpu(node->totlen));
break;
- case JFFS2_FEATURE_RWCOMPAT_COPY: {
+ case JFFS2_FEATURE_RWCOMPAT_COPY:
D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-
- jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
-
- /* We can't summarise nodes we don't grok */
- jffs2_sum_disable_collecting(s);
+ USED_SPACE(PAD(je32_to_cpu(node->totlen)));
ofs += PAD(je32_to_cpu(node->totlen));
break;
- }
}
}
}
}
}
- D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
- jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
-
+ D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset,
+ jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size));
+
/* mark_node_obsolete can add to wasted !! */
if (jeb->wasted_size) {
jeb->dirty_size += jeb->wasted_size;
static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
{
+ struct jffs2_raw_node_ref *raw;
struct jffs2_inode_cache *ic;
uint32_t ino = je32_to_cpu(ri->ino);
- int err;
D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
Which means that the _full_ amount of time to get to proper write mode with GC
operational may actually be _longer_ than before. Sucks to be me. */
+ raw = jffs2_alloc_raw_node_ref();
+ if (!raw) {
+ printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
+ return -ENOMEM;
+ }
+
ic = jffs2_get_ino_cache(c, ino);
if (!ic) {
/* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
ofs, je32_to_cpu(ri->node_crc), crc);
/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
+ jffs2_free_raw_node_ref(raw);
return 0;
}
ic = jffs2_scan_make_ino_cache(c, ino);
- if (!ic)
+ if (!ic) {
+ jffs2_free_raw_node_ref(raw);
return -ENOMEM;
+ }
}
/* Wheee. It worked */
- jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
+
+ raw->flash_offset = ofs | REF_UNCHECKED;
+ raw->__totlen = PAD(je32_to_cpu(ri->totlen));
+ raw->next_phys = NULL;
+ raw->next_in_ino = ic->nodes;
+
+ ic->nodes = raw;
+ if (!jeb->first_node)
+ jeb->first_node = raw;
+ if (jeb->last_node)
+ jeb->last_node->next_phys = raw;
+ jeb->last_node = raw;
D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
pseudo_random += je32_to_cpu(ri->version);
+ UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
+
if (jffs2_sum_active()) {
jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
}
static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
{
+ struct jffs2_raw_node_ref *raw;
struct jffs2_full_dirent *fd;
struct jffs2_inode_cache *ic;
uint32_t crc;
- int err;
D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));
printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
ofs, je32_to_cpu(rd->node_crc), crc);
/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
return 0;
}
jffs2_free_full_dirent(fd);
/* FIXME: Why do we believe totlen? */
/* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
- if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
- return err;
+ DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
return 0;
}
+ raw = jffs2_alloc_raw_node_ref();
+ if (!raw) {
+ jffs2_free_full_dirent(fd);
+ printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");
+ return -ENOMEM;
+ }
ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
if (!ic) {
jffs2_free_full_dirent(fd);
+ jffs2_free_raw_node_ref(raw);
return -ENOMEM;
}
- fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
+ raw->__totlen = PAD(je32_to_cpu(rd->totlen));
+ raw->flash_offset = ofs | REF_PRISTINE;
+ raw->next_phys = NULL;
+ raw->next_in_ino = ic->nodes;
+ ic->nodes = raw;
+ if (!jeb->first_node)
+ jeb->first_node = raw;
+ if (jeb->last_node)
+ jeb->last_node->next_phys = raw;
+ jeb->last_node = raw;
+ fd->raw = raw;
fd->next = NULL;
fd->version = je32_to_cpu(rd->version);
fd->ino = je32_to_cpu(rd->ino);
fd->nhash = full_name_hash(fd->name, rd->nsize);
fd->type = rd->type;
+ USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
if (jffs2_sum_active()) {