mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
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:
parent
70741004dc
commit
9b7076229e
3 changed files with 368 additions and 1 deletions
|
@ -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
163
fs/jffs2/summary.h
Normal 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 */
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue