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

最近发现的 __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也一样。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值