jffs2: summary support

This patch adds support for reading fs information from summary
node instead of scanning full eraseblock.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
This commit is contained in:
Ilya Yanok 2008-11-13 19:49:35 +03:00 committed by Wolfgang Denk
parent 70741004dc
commit 9b7076229e
3 changed files with 368 additions and 1 deletions

View file

@ -138,6 +138,8 @@
# define DEBUGF(fmt,args...)
#endif
#include "summary.h"
/* keeps pointer to currentlu processed partition */
static struct part_info *current_part;
@ -1214,6 +1216,132 @@ jffs2_1pass_rescan_needed(struct part_info *part)
return 0;
}
#define dbg_summary(...) do {} while (0);
/* Process the stored summary information - helper function for
* jffs2_sum_scan_sumnode()
*/
static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset,
struct jffs2_raw_summary *summary,
struct b_lists *pL)
{
void *sp;
int i;
sp = summary->sum;
for (i = 0; i < summary->sum_num; i++) {
dbg_summary("processing summary index %d\n", i);
switch (((struct jffs2_sum_unknown_flash *)sp)->nodetype) {
case JFFS2_NODETYPE_INODE: {
struct jffs2_sum_inode_flash *spi;
spi = sp;
dbg_summary("Inode at 0x%08x-0x%08x\n",
offset + spi->offset,
offset + spi->offset + spi->totlen);
if (insert_node(&pL->frag, (u32) part->offset +
offset + spi->offset) == NULL)
return -1;
sp += JFFS2_SUMMARY_INODE_SIZE;
break;
}
case JFFS2_NODETYPE_DIRENT: {
struct jffs2_sum_dirent_flash *spd;
spd = sp;
dbg_summary("Dirent at 0x%08x-0x%08x\n",
offset + spd->offset,
offset + spd->offset + spd->totlen);
if (insert_node(&pL->dir, (u32) part->offset +
offset + spd->offset) == NULL)
return -1;
sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
break;
}
default : {
uint16_t nodetype =
((struct jffs2_sum_unknown_flash *)
sp)->nodetype;
printf("Unsupported node type %x found in "
"summary!\n", nodetype);
break;
}
}
}
return 0;
}
/* Process the summary node - called from jffs2_scan_eraseblock() */
int jffs2_sum_scan_sumnode(struct part_info *part, uint32_t offset,
struct jffs2_raw_summary *summary, uint32_t sumsize,
struct b_lists *pL)
{
struct jffs2_unknown_node crcnode;
int ret, ofs;
uint32_t crc;
ofs = part->sector_size - sumsize;
dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
offset, offset + ofs, sumsize);
/* OK, now check for node validity and CRC */
crcnode.magic = JFFS2_MAGIC_BITMASK;
crcnode.nodetype = JFFS2_NODETYPE_SUMMARY;
crcnode.totlen = summary->totlen;
crc = crc32_no_comp(0, (uchar *)&crcnode, sizeof(crcnode)-4);
if (summary->hdr_crc != crc) {
dbg_summary("Summary node header is corrupt (bad CRC or "
"no summary at all)\n");
goto crc_err;
}
if (summary->totlen != sumsize) {
dbg_summary("Summary node is corrupt (wrong erasesize?)\n");
goto crc_err;
}
crc = crc32_no_comp(0, (uchar *)summary,
sizeof(struct jffs2_raw_summary)-8);
if (summary->node_crc != crc) {
dbg_summary("Summary node is corrupt (bad CRC)\n");
goto crc_err;
}
crc = crc32_no_comp(0, (uchar *)summary->sum,
sumsize - sizeof(struct jffs2_raw_summary));
if (summary->sum_crc != crc) {
dbg_summary("Summary node data is corrupt (bad CRC)\n");
goto crc_err;
}
if (summary->cln_mkr)
dbg_summary("Summary : CLEANMARKER node \n");
ret = jffs2_sum_process_sum_data(part, offset, summary, pL);
if (ret)
return ret; /* real error */
return 1;
crc_err:
putstr("Summary node crc error, skipping summary information.\n");
return 0;
}
#ifdef DEBUG_FRAGMENTS
static void
dump_fragments(struct b_lists *pL)
@ -1321,10 +1449,65 @@ jffs2_1pass_build_lists(struct part_info * part)
for (i = 0; i < nr_sectors; i++) {
uint32_t sector_ofs = i * part->sector_size;
uint32_t buf_ofs = sector_ofs;
uint32_t buf_len = EMPTY_SCAN_SIZE(part->sector_size);
uint32_t buf_len;
uint32_t ofs, prevofs;
struct jffs2_sum_marker *sm;
void *sumptr = NULL;
uint32_t sumlen;
int ret;
WATCHDOG_RESET();
buf_len = sizeof(*sm);
/* Read as much as we want into the _end_ of the preallocated
* buffer
*/
get_fl_mem(part->offset + sector_ofs + part->sector_size -
buf_len, buf_len, buf + buf_size - buf_len);
sm = (void *)buf + buf_size - sizeof(*sm);
if (sm->magic == JFFS2_SUM_MAGIC) {
sumlen = part->sector_size - 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 = malloc(sumlen);
if (!sumptr) {
putstr("Can't get memory for summary "
"node!\n");
return 0;
}
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
*/
get_fl_mem(part->offset + sector_ofs +
part->sector_size - sumlen,
sumlen - buf_len, sumptr);
}
}
if (sumptr) {
ret = jffs2_sum_scan_sumnode(part, sector_ofs, sumptr,
sumlen, pL);
if (buf_size && sumlen > buf_size)
free(sumptr);
if (ret < 0)
return 0;
if (ret)
continue;
}
buf_len = EMPTY_SCAN_SIZE(part->sector_size);
get_fl_mem((u32)part->offset + buf_ofs, buf_len, buf);
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
@ -1477,6 +1660,8 @@ jffs2_1pass_build_lists(struct part_info * part)
node->totlen,
sizeof(struct jffs2_unknown_node));
break;
case JFFS2_NODETYPE_SUMMARY:
break;
default:
printf("Unknown node type: %x len %d offset 0x%x\n",
node->nodetype,

163
fs/jffs2/summary.h Normal file
View file

@ -0,0 +1,163 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* Zoltan Sogor <weth@inf.u-szeged.hu>,
* Patrik Kluba <pajko@halom.u-szeged.hu>,
* University of Szeged, Hungary
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/
#ifndef JFFS2_SUMMARY_H
#define JFFS2_SUMMARY_H
#define BLK_STATE_ALLFF 0
#define BLK_STATE_CLEAN 1
#define BLK_STATE_PARTDIRTY 2
#define BLK_STATE_CLEANMARKER 3
#define BLK_STATE_ALLDIRTY 4
#define BLK_STATE_BADBLOCK 5
#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
/* Summary structures used on flash */
struct jffs2_sum_unknown_flash
{
__u16 nodetype; /* node type */
};
struct jffs2_sum_inode_flash
{
__u16 nodetype; /* node type */
__u32 inode; /* inode number */
__u32 version; /* inode version */
__u32 offset; /* offset on jeb */
__u32 totlen; /* record length */
} __attribute__((packed));
struct jffs2_sum_dirent_flash
{
__u16 nodetype; /* == JFFS_NODETYPE_DIRENT */
__u32 totlen; /* record length */
__u32 offset; /* offset on jeb */
__u32 pino; /* parent inode */
__u32 version; /* dirent version */
__u32 ino; /* == zero for unlink */
uint8_t nsize; /* dirent name size */
uint8_t type; /* dirent type */
uint8_t name[0]; /* dirent name */
} __attribute__((packed));
struct jffs2_sum_xattr_flash
{
__u16 nodetype; /* == JFFS2_NODETYPE_XATR */
__u32 xid; /* xattr identifier */
__u32 version; /* version number */
__u32 offset; /* offset on jeb */
__u32 totlen; /* node length */
} __attribute__((packed));
struct jffs2_sum_xref_flash
{
__u16 nodetype; /* == JFFS2_NODETYPE_XREF */
__u32 offset; /* offset on jeb */
} __attribute__((packed));
union jffs2_sum_flash
{
struct jffs2_sum_unknown_flash u;
struct jffs2_sum_inode_flash i;
struct jffs2_sum_dirent_flash d;
struct jffs2_sum_xattr_flash x;
struct jffs2_sum_xref_flash r;
};
/* Summary structures used in the memory */
struct jffs2_sum_unknown_mem
{
union jffs2_sum_mem *next;
__u16 nodetype; /* node type */
};
struct jffs2_sum_inode_mem
{
union jffs2_sum_mem *next;
__u16 nodetype; /* node type */
__u32 inode; /* inode number */
__u32 version; /* inode version */
__u32 offset; /* offset on jeb */
__u32 totlen; /* record length */
} __attribute__((packed));
struct jffs2_sum_dirent_mem
{
union jffs2_sum_mem *next;
__u16 nodetype; /* == JFFS_NODETYPE_DIRENT */
__u32 totlen; /* record length */
__u32 offset; /* ofset on jeb */
__u32 pino; /* parent inode */
__u32 version; /* dirent version */
__u32 ino; /* == zero for unlink */
uint8_t nsize; /* dirent name size */
uint8_t type; /* dirent type */
uint8_t name[0]; /* dirent name */
} __attribute__((packed));
struct jffs2_sum_xattr_mem
{
union jffs2_sum_mem *next;
__u16 nodetype;
__u32 xid;
__u32 version;
__u32 offset;
__u32 totlen;
} __attribute__((packed));
struct jffs2_sum_xref_mem
{
union jffs2_sum_mem *next;
__u16 nodetype;
__u32 offset;
} __attribute__((packed));
union jffs2_sum_mem
{
struct jffs2_sum_unknown_mem u;
struct jffs2_sum_inode_mem i;
struct jffs2_sum_dirent_mem d;
struct jffs2_sum_xattr_mem x;
struct jffs2_sum_xref_mem r;
};
/* Summary related information stored in superblock */
struct jffs2_summary
{
uint32_t sum_size; /* collected summary information for nextblock */
uint32_t sum_num;
uint32_t sum_padded;
union jffs2_sum_mem *sum_list_head;
union jffs2_sum_mem *sum_list_tail;
__u32 *sum_buf; /* buffer for writing out summary */
};
/* Summary marker is stored at the end of every sumarized erase block */
struct jffs2_sum_marker
{
__u32 offset; /* offset of the summary node in the jeb */
__u32 magic; /* == JFFS2_SUM_MAGIC */
};
#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker))
#endif /* JFFS2_SUMMARY_H */

View file

@ -50,6 +50,9 @@
#define JFFS2_EMPTY_BITMASK 0xffff
#define JFFS2_DIRTY_BITMASK 0x0000
/* Summary node MAGIC marker */
#define JFFS2_SUM_MAGIC 0x02851885
/* We only allow a single char for length, and 0xFF is empty flash so
we don't want it confused with a real length. Hence max 254.
*/
@ -89,6 +92,7 @@
#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)
#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4)
#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
/* Maybe later... */
/*#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) */
@ -166,9 +170,24 @@ struct jffs2_raw_inode
/* __u8 data[dsize]; */
} __attribute__((packed));
struct jffs2_raw_summary
{
__u16 magic;
__u16 nodetype; /* = JFFS2_NODETYPE_SUMMARY */
__u32 totlen;
__u32 hdr_crc;
__u32 sum_num; /* number of sum entries*/
__u32 cln_mkr; /* clean marker size, 0 = no cleanmarker */
__u32 padded; /* sum of the size of padding nodes */
__u32 sum_crc; /* summary information crc */
__u32 node_crc; /* node crc */
__u32 sum[0]; /* inode summary info */
};
union jffs2_node_union {
struct jffs2_raw_inode i;
struct jffs2_raw_dirent d;
struct jffs2_raw_summary s;
struct jffs2_unknown_node u;
} __attribute__((packed));