linux内存未四字节对齐,linux的nand中计算ECC的时候buf地址不4字节对齐的问题

本文探讨了在Linux内核中JFFS2文件系统遇到的内存对齐问题,源于非4字节对齐导致的异常。焦点在于`nand_calculate_ecc()`函数,以及`jffs2_garbage_collect_dnode()`中的内存处理。作者揭示了更换工具链后引发的问题,涉及`start`地址的更新和`ISDIRTY`判断。此外,文章还提及了垃圾收集过程中与块擦除的同步问题及其对系统性能的影响。
摘要由CSDN通过智能技术生成

最近发现的 __nand_calculate_ecc(buf,eccsize,code)中buf地址非4字节对齐导致的异常问题, 经查发现是由于fs/jffs2/gc.c中

jffs2_garbage_collect_live()函数中获取的start值非对齐引起,这个start值传给给jffs2_garbage_collect_dnode(),

在jffs2_garbage_collect_dnode()中,会根据start值算出对应的frag(frag=jffs2_lookup_node_frag(&f->fragtree,start)),然

后找这个frag的前一个frag, 如下代码所示:

while((frag = frag_prev(frag)) && frag->ofs >= min) {

/* If the previous frag doesn't even reach the beginning, there's

excessive fragmentation. Just merge. */

if (frag->ofs > min) {

D1(printk(KERN_DEBUG "Expanding down to cover partial frag (0x%x-0x%x)\n",

frag->ofs, frag->ofs+frag->size));

start = frag->ofs;

continue;

}

/* OK. This frag holds the first byte of the page. */

if (!frag->node || !frag->node->raw) {

D1(printk(KERN_DEBUG "First frag in page is hole (0x%x-0x%x). Not expanding down.\n",

frag->ofs, frag->ofs+frag->size));

start = frag->ofs;

break;

} else {

/* OK, it's a frag which extends to the beginning of the page. Does it live

in a block which is still considered clean? If so, don't obsolete it.

If not, cover it anyway. */

struct jffs2_raw_node_ref *raw = frag->node->raw;

struct jffs2_eraseblock *jeb;

jeb = &c->blocks[raw->flash_offset / c->sector_size];

if (jeb == c->gcblock) {

D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in gcblock at %08x\n",

frag->ofs, frag->ofs+frag->size, ref_offset(raw)));

start = frag->ofs;

break;

}

if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) {

D1(printk(KERN_DEBUG "Not expanding down to cover frag (0x%x-0x%x) in clean block %08x\n",

frag->ofs, frag->ofs+frag->size, jeb->offset));

//add for fix bug--start

if(start%4){

start = frag->ofs;

printk("expanding down to cover frag (0x%x-0x%x) in clean block %08x, anyway, other wise unalligned exception

will be raised if start address unalligned\n",frag->ofs, frag->ofs+frag->size, jeb->offset);

}

//add for fix bug--start

break;

}

D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in dirty block %08x\n",         frag->ofs, frag->ofs+frag->size, jeb->offset));     start = frag->ofs;     break;    }   }  正常情况下,找到前一个frag的frag->ofs是大于min的,而且是4字节对齐的,但现在的情况是frag->ofs刚好等于min, 而且又满足  if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) 条件,导致start没有更新,start仍然未对齐,进而导致异常。  这个问题是更换toolchain(从uclibc到glibc)引起的,用uclibc时,while中的if (frag->ofs > min) 条件满足,start被更新成对齐的地址。  更深层的原因暂时没能找到,暂时作如此修改。    另外,发现linux内核跑起来后,过了大概10几秒钟,会跑到jffs2_garbage_collect_pass()中的以下代码,不断调用jffs2_erase_pending_blocks(),   /* If there are any blocks which need erasing, erase them now */   if (!list_empty(&c->erase_complete_list) ||    !list_empty(&c->erase_pending_list)) {    spin_unlock(&c->erase_completion_lock);    D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n"));    if (jffs2_erase_pending_blocks(c, 1)) {     mutex_unlock(&c->alloc_sem);     return 0;    }    D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));    spin_lock(&c->erase_completion_lock);   }     在jffs2_erase_pending_blocks()中,也只是调用到jffs2_mark_erased_block()。这个过程会持续大概半分钟,在这半分钟内,几乎不能运行其它APP,  不知道是否正常,以前的版本也没有注意,使用uclibc toolchain也一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值