gpt4 book ai didi

linux - UBIFS中UBI的腐败

转载 作者:可可西里 更新时间:2023-11-01 11:49:19 25 4
gpt4 key购买 nike

我们在我们的系统中使用 Linux-2.6.28 和 2 Gb NAND 闪存;经过一些电源循环测试后,我们观察到以下错误:

Volume operational found at volume id 3
read 21966848 bytes from volume 3 to 80400000(buf address)
UBI error: ubi_io_read: error -77 while reading 126976 bytes from PEB 1074:4096, read 126976 bytes
UBI: force data checking
UBI error: ubi_io_read: error -77 while reading 126976 bytes from PEB 1074:4096, read 126976 bytes
UBI warning: ubi_eba_read_leb: CRC error: calculated 0xa7cab743, must be 0x15716fce
read err ffffffb3

这些错误不是硬件错误,因为如果我们删除了有问题的分区,我们就可以正常启动硬件;也许 UBIFS 没有纠正错误的 UBI block 。

在最新的内核中添加了任何 UBI 补丁来解决这个问题吗?谢谢。

最佳答案

打印的错误是UBI错误。让我们看看the source在 177 号线附近,

ubi_err("error %d while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, len, pnum, offset, read);

因此,当尝试读取偏移量 4096 处的“物理删除 block ”#1074(2k 页的第 2 页)时,NAND 闪存驱动程序返回错误“-77”(通常为 -EBADFD)。 UBI 包括卷管理页面,这些页面通常位于物理删除 block (简称 PEB)的开头。

请注意 latest mainline of io.c有以下注释和代码,

/*
* Deliberately corrupt the buffer to improve robustness. Indeed, if we
* do not do this, the following may happen:
* 1. The buffer contains data from previous operation, e.g., read from
* another PEB previously. The data looks like expected, e.g., if we
* just do not read anything and return - the caller would not
* notice this. E.g., if we are reading a VID header, the buffer may
* contain a valid VID header from another PEB.
* 2. The driver is buggy and returns us success or -EBADMSG or
* -EUCLEAN, but it does not actually put any data to the buffer.
*
* This may confuse UBI or upper layers - they may think the buffer
* contains valid data while in fact it is just old data. This is
* especially possible because UBI (and UBIFS) relies on CRC, and
* treats data as correct even in case of ECC errors if the CRC is
* correct.
*
* Try to prevent this situation by changing the first byte of the
* buffer.
*/
*((uint8_t *)buf) ^= 0xFF;

以下代码可用于处理 UBI/UbiFS 转储并查找异常,

/* -*- mode: c; compile-command: "gcc -Wall -g -o parse_ubi parse_ubi.c"; -*- */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define __packed __attribute__((packed))
#include "ubi-media.h"

#define bswap16 be16toh
#define bswap32 be32toh
#define bswap64 be64toh

static int dump_vid = 0;

#define CRCPOLY_LE 0xedb88320
static unsigned int crc32(unsigned int crc, void const *_p, size_t len)
{
unsigned char const *p = _p;
int i;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
}
return crc;
}

#define ALEN(a) (sizeof(a)/sizeof(a[0]))
static void print_ec(struct ubi_ec_hdr *ec)
{
if(ec->version != UBI_VERSION || ec->magic != UBI_EC_HDR_MAGIC) {
printf(" Magic: %x\n", ec->magic);
printf(" Version: %d\n", (int)ec->version);
printf(" EC: %llx\n", ec->ec);
printf(" VID offset: %x\n", ec->vid_hdr_offset);
printf(" Data offset: %x\n", ec->data_offset);
printf(" Image seq: %x\n", ec->image_seq);
exit(-1);
}
}

static void read_ec(int fd, struct ubi_ec_hdr *ec)
{
int rval = read(fd, ec,sizeof(*ec));
if(rval == sizeof(*ec)) {
unsigned int crc;
crc = crc32(UBI_CRC32_INIT, ec, UBI_EC_HDR_SIZE_CRC);
ec->magic = bswap32(ec->magic);
ec->vid_hdr_offset = bswap32(ec->vid_hdr_offset);
ec->data_offset = bswap32(ec->data_offset);
ec->image_seq = bswap32(ec->image_seq);
ec->hdr_crc = bswap32(ec->hdr_crc);
ec->ec = bswap64(ec->ec);
if(crc != ec->hdr_crc)
printf("EC CRC: %x/%x\n", crc, ec->hdr_crc);
} else
memset(ec, 0, sizeof(*ec));
}

static void print_vid(int vid_num, struct ubi_vid_hdr *vid)
{
if(vid->magic != UBI_VID_HDR_MAGIC)
printf(" Magic: %x\n", vid->magic);
if(vid->version != UBI_VERSION)
printf(" Version: %d\n", (int)vid->version);

if(!dump_vid) return;

printf("VID %d\n", vid_num);

/* This is usually the same. */
if(vid->vol_id >= UBI_INTERNAL_VOL_START)
printf("Internal vol_id: %d\n", vid->vol_id - UBI_INTERNAL_VOL_START);
if(vid->vol_type != UBI_VID_DYNAMIC)
printf(" vol_type: %s\n",
vid->vol_type == UBI_VID_DYNAMIC ? "dynamic" : "static");
if(vid->used_ebs)
printf(" used_ebs: %d\n", vid->used_ebs);
if(vid->data_pad)
printf(" data_pad: %d\n", vid->data_pad);
if((vid->copy_flag != 1 && vid->data_size) ||
(vid->copy_flag == 0 && vid->data_size))
printf(" copy_flag: %d\n", (int)vid->copy_flag);

printf(" lnum: %d\n", vid->lnum);
if(vid->compat) {
const char *compat[] = {
[UBI_COMPAT_DELETE] = "delete",
[UBI_COMPAT_RO] = "ro",
[UBI_COMPAT_PRESERVE] = "preserve",
[UBI_COMPAT_REJECT] = "reject"
};
printf(" compat: %s\n", compat[vid->compat]);
}
printf(" data_size: %d\n", vid->data_size);
/* printf(" data_crc: %x\n", vid->data_crc); */
printf(" hdr_crc: %x\n", vid->hdr_crc);
printf(" sqnum: %lld\n", vid->sqnum);
}

static int read_vid(int fd, struct ubi_vid_hdr *vid)
{
int rval = read(fd, vid,sizeof(*vid));
if(rval == sizeof(*vid)) {
unsigned int crc;
crc = crc32(UBI_CRC32_INIT, vid, UBI_EC_HDR_SIZE_CRC);
vid->magic = bswap32(vid->magic);
vid->vol_id = bswap32(vid->vol_id);
vid->lnum = bswap32(vid->lnum);
vid->data_size = bswap32(vid->data_size);
vid->used_ebs = bswap32(vid->used_ebs);
vid->data_pad = bswap32(vid->data_pad);
vid->data_crc = bswap32(vid->data_crc);
vid->hdr_crc = bswap32(vid->hdr_crc);
vid->sqnum = bswap64(vid->sqnum);
if(crc != vid->hdr_crc && vid->magic == UBI_VID_HDR_MAGIC)
printf("VID CRC: %x/%x\n", crc, vid->hdr_crc);
} else
memset(vid, 0, sizeof(*vid));
return rval;
}

static void print_vtbl(struct ubi_vtbl_record *vtbl)
{
printf(" Found vtbl [%d] %s\n", vtbl->name_len, vtbl->name);
printf(" Reserved PEBs: %d\n", vtbl->reserved_pebs);
printf(" Align: %d\n", vtbl->alignment);
printf(" Pad: %d\n", vtbl->data_pad);
if(vtbl->vol_type != UBI_VID_DYNAMIC)
printf(" vol_type: %s\n",
vtbl->vol_type == UBI_VID_DYNAMIC ? "dynamic" : "static");
printf(" Update: %d\n", vtbl->upd_marker);
printf(" Flags: %d\n", (int)vtbl->flags);
}

static void read_vtbl(int fd, struct ubi_vtbl_record *vtbl)
{
int rval = read(fd, vtbl, sizeof(*vtbl));
if(rval == sizeof(*vtbl)) {
vtbl->reserved_pebs = bswap32(vtbl->reserved_pebs);
vtbl->alignment = bswap32(vtbl->alignment);
vtbl->data_pad = bswap32(vtbl->data_pad);
vtbl->crc = bswap32(vtbl->crc);
vtbl->name_len = bswap16(vtbl->name_len);
} else
memset(vtbl, 0, sizeof(*vtbl));
}

static void print_fm_sb(struct ubi_fm_sb *fm_sb)
{
int i;

if(fm_sb->magic != UBI_FM_SB_MAGIC)
printf(" Magic: %x\n", fm_sb->magic);
if(fm_sb->version != UBI_VERSION)
printf(" Version: %d\n", (int)fm_sb->version);
printf(" data_crc: %x\n", fm_sb->data_crc);
printf(" used_blocks: %x\n", fm_sb->used_blocks);
for(i = 0; i < fm_sb->used_blocks; i++)
printf(" block_loc[%d]: %d\n", i, fm_sb->block_loc[i]);
for(i=0; i < fm_sb->used_blocks; i++)
printf(" block_ec[%d]: %d\n", i, fm_sb->block_ec[i]);
printf(" sqnum: %lld\n", fm_sb->sqnum);
}

static void read_fm_sb(int fd, struct ubi_fm_sb *fm_sb)
{
int rval = read(fd, fm_sb, sizeof(*fm_sb));
if(rval == sizeof(*fm_sb)) {
int i;
fm_sb->magic = bswap32(fm_sb->magic);
fm_sb->data_crc = bswap32(fm_sb->data_crc);
fm_sb->used_blocks = bswap32(fm_sb->used_blocks);
for(i=0; i < UBI_FM_MAX_BLOCKS; i++)
fm_sb->block_loc[i] = bswap32(fm_sb->block_loc[i]);
for(i=0; i < UBI_FM_MAX_BLOCKS; i++)
fm_sb->block_ec[i] = bswap32(fm_sb->block_ec[i]);
fm_sb->sqnum = bswap64(fm_sb->sqnum);
} else
memset(fm_sb, 0, sizeof(*fm_sb));
}

/* Set logical block at physical. */
static int eba_map[1920];
static int pba_map[1920];

static void usage(char *name)
{
printf("Usage: %s -b [erase block size] -e -v <ubi file> \n", name);
printf("Where,\n -e is dump the logic to physical block map.\n");
printf(" -v is dump the VID headers.\n");
printf(" -b [size] sets the erase block size (flash dependent).\n");

}

typedef struct fastmap {
struct ubi_fm_sb fm_sb;
struct ubi_fm_hdr hdr;
struct ubi_fm_scan_pool pool1;
struct ubi_fm_scan_pool pool2;
/* Free, Used, Scrub and Erase */
struct ubi_fm_ec ec[0];
/* ... */
/* struct ubi_fm_volhdr vol; */
/* struct ubi_fm_eba eba[0]; */

} fastmap;

int main (int argc, char *argv[])
{
int fd, i, erase_block = 0, eba_flag = 0;
int c;
struct ubi_ec_hdr ec;
struct ubi_vid_hdr vid;
int erase_size = 0x20000;
int leb_size;
off_t cur_ec = 0;
int vidless_blocks = 0;

while ((c = getopt (argc, argv, "hveb:")) != -1)
switch (c)
{
case 'h': /* Help */
usage(argv[0]);
goto out;
case 'b':
erase_size = atoi(optarg);
break;
case 'e':
eba_flag = 1;
break;
case 'v':
dump_vid = 1;
break;
case '?':
if (optopt == 'b')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
goto out;
}

if(optind >= argc) {
usage(argv[0]);
goto out;
}

fd = open(argv[optind], O_RDONLY);
if(fd < 0) {
printf("Bad file: %s\n", argv[1]);
goto out;
}

memset(eba_map, -1, sizeof(eba_map));
memset(pba_map, -1, sizeof(pba_map));

/* Process each 'erase block'. */
read_ec(fd,&ec);
while(ec.magic == UBI_EC_HDR_MAGIC) {
leb_size = erase_size - ec.data_offset;
print_ec(&ec);

/* VID present? */
if(lseek(fd, ec.vid_hdr_offset-sizeof(ec), SEEK_CUR) == -1) {
printf("Seek error: %s\n", argv[1]);
goto out;
}

if(read_vid(fd,&vid) != sizeof(vid)) {
printf("File too small: %s\n", argv[1]);
goto out;
}
if(vid.magic == UBI_VID_HDR_MAGIC) {
print_vid(erase_block, &vid);
if(vid.vol_id == 3) {
if(eba_map[vid.lnum] != -1)
printf("EBA dup: %d %d\n", eba_map[vid.lnum], erase_block);
eba_map[vid.lnum] = erase_block;
}
pba_map[erase_block] = vid.lnum;

/* Read volume table. */
if(vid.vol_id == UBI_INTERNAL_VOL_START) {
/* Seek to PEB data offset. */
if(lseek(fd,
ec.data_offset - ec.vid_hdr_offset - sizeof(vid),
SEEK_CUR) == -1)
printf("Seek error: %s\n", argv[1]);
else {
int i;
struct ubi_vtbl_record vtbl;
for(i = 0; i < UBI_MAX_VOLUMES; i++) {
read_vtbl(fd, &vtbl);
if(vtbl.reserved_pebs ||
vtbl.name_len ||
strcmp((char*)vtbl.name, "") != 0) {
printf("VTBL %d\n", i);
print_vtbl(&vtbl);
}
}
}
} else if(vid.vol_id == UBI_FM_SB_VOLUME_ID) {
printf("Found Fastmap super block @PEB %d.\n", erase_block);
if(lseek(fd,
ec.data_offset - ec.vid_hdr_offset - sizeof(vid),
SEEK_CUR) == -1)
printf("Seek error: %s\n", argv[1]);
else {
void *data = alloca(leb_size);
struct ubi_fm_sb *fm_sb = data;
read_fm_sb(fd, data);
print_fm_sb(fm_sb);
}
} else if(vid.vol_id == UBI_FM_DATA_VOLUME_ID) {
printf("Found Fastmap data block @PEB %d.\n", erase_block);
printf("UNSUPPORTED!!!\n");
}

} else if(vid.magic != 0xffffffff){
printf("VID %d corrupt! %x\n", erase_block, vid.magic);
} else {
vidless_blocks++;
}

erase_block++;
cur_ec += erase_size;
cur_ec = lseek(fd, cur_ec, SEEK_SET);

/* Process Erase counter. */
read_ec(fd,&ec);
}

printf("Found %d vidless (free) blocks.\n", vidless_blocks);
if(eba_flag) {
printf("Logical to physical.\n");
for(i = 0; i < ALEN(eba_map); i+=8)
printf("%4d: %4d %4d %4d %4d %4d %4d %4d %4d"
" %4d %4d %4d %4d %4d %4d %4d %4d\n", i,
eba_map[i], eba_map[i+1],
eba_map[i+2], eba_map[i+3],
eba_map[i+4], eba_map[i+5],
eba_map[i+6], eba_map[i+7],
eba_map[i+8], eba_map[i+9],
eba_map[i+10], eba_map[i+11],
eba_map[i+12], eba_map[i+13],
eba_map[i+14], eba_map[i+15]);
printf("Physical to logical.\n");
for(i = 0; i < ALEN(pba_map); i+=8)
printf("%4d: %4d %4d %4d %4d %4d %4d %4d %4d"
" %4d %4d %4d %4d %4d %4d %4d %4d\n", i,
pba_map[i], pba_map[i+1],
pba_map[i+2], pba_map[i+3],
pba_map[i+4], pba_map[i+5],
pba_map[i+6], pba_map[i+7],
pba_map[i+8], pba_map[i+9],
pba_map[i+10], pba_map[i+11],
pba_map[i+12], pba_map[i+13],
pba_map[i+14], pba_map[i+15]);
}
out:
return 0;
}

从 UBI 目录构建复制 ubi-media.h 并运行 gcc -Wall -g -o parse_ubi parse_ubi.c。该代码可能在大端平台上有问题;它也没有用 2.6.28 进行测试,但我相信它应该可以工作,因为 UBI 结构不应该改变。如果无法编译,您可能必须删除一些 fastmap 代码。该代码应该对 PEB#1074 的问题给出一些指示。失败时复制分区并使用上面的代码分析UBI层。

MTD 驱动程序很可能做了一些异常的事情,阻止了 UBI 附加到 MTD 分区。这反过来会阻止 UbiFS 挂载。如果您知道正在使用什么 MTD Nand 闪存 Controller ,将有助于其他人确定问题出在哪里。

它可能是由 MTD 错误和/或硬件错误或 UBI/UbiFS 问题引起的。如果是UBI/UbiFs,则有backport treesnewer 3.0 .你可以尝试从 2.6.32 窃取补丁;全部应用后,添加 3.0。

同样,问题可能出在 MTD 驱动程序上。获取特定 CPU/SOC NAND 闪存 Controller 的 MTD 更改。我从主线做这件事;一些更改是错误修复和其他基础结构。你必须单独查看每个补丁

关于linux - UBIFS中UBI的腐败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21144164/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com