JFFS2 when rename a directory there maybe occur hard link between directories

wang.bo116 at zte.com.cn wang.bo116 at zte.com.cn
Sun Sep 28 18:38:43 PDT 2014


Hi,everyone

Our kernel version is 2.6.21.7, and we update the jffs2 part to version 3.16.3,
our machine has 256MB nor flash, and we use 236MB for jffs2.(CONFIG_JFFS2_SUMMARY = y)

We do the test like this.
1. create some directories under root, like /SW1, /SW2,
2. create directory under root, named old, the dirent is /old
3. mv(rename) /SW1 /SW2 under /old  then now is /old/SW1 /old/SW2 ,
 then do some other things but don't touch /old/SW1 /old/SW2
4. mv(rename) /old/SW1 /old/SW2 under root, so there is /SW1 /SW2,
and the /old is empty
5. delete(remove) /old
6. reboot

Now, after the machine rebooted, we found /SW1 and /old/SW1 become hardlink,
but /old/SW1 shouldn't exist. So we catched some logs.
----------------------------------------------------------------
ino = 0, name = SW1, version = 6, pino = 71, ofs = 0x056803e4
ino = 0, name = SW2, version = 7, pino = 71, ofs = 0x0568043c

ino = 2, name = SW1, version = 2, pino = 71, ofs = 0x0e6186e8
ino = 3, name = SW2, version = 3, pino = 71, ofs = 0x0e618740
ino = 0, name = old, version = 298, pino = 1, ofs = 0x0e6185c4
ino = 71, name = old, version = 299, pino = 1, ofs = 0x0e6186bc
-----------------------------------------------------------------
from the log, we can see the old(ino 71) has deleted ,and SW1 SW2 seem good,
they all have their deletion dirent, everything's ok.

Then,we reboot the machine and also catched some logs.
-----------------------------------------------------------------
ino = 2, name = SW1, version = 2, pino = 71, ofs = 0x0e6186e8
ino = 3, name = SW2, version = 3, pino = 71, ofs = 0x0e618740
child dir "SW1" (ino #2) of dir ino #71 appears to be a hard link
child dir "SW2" (ino #3) of dir ino #71 appears to be a hard link
-----------------------------------------------------------------

/old/SW1 and /old/SW2 's deletion dirent has gone,
and /SW1 <-> /old/SW1 /SW2 <->/old/SW2 become hard link.

We found, after reboot , during mount JFFS2, in jffs2_build_remove_unlinked_inode

static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
					struct jffs2_inode_cache *ic,
					struct jffs2_full_dirent **dead_fds)
{
	...
	while (raw != (void *)ic) {
		struct jffs2_raw_node_ref *next = raw->next_in_ino;
		dbg_fsbuild("obsoleting node at 0x%08x\n", ref_offset(raw));
		jffs2_mark_node_obsolete(c, raw);
		raw = next;
	}
	...
}

Because /old/SW1 and /old/SW1 deletion dirent still exist in the flash, during scan,
could create its parent's inode cache. /old has deleted,then should do
jffs2_build_remove_unlinked_inode, and make every under /old to obsolete,
include /old/SW1's deletion dirent.If the deletion dirent's eraseblock is totally dirty,
then will erase it.So, the obsolete /old/SW1 is still in flash.
/old/SW1 is obsoleted but just record in ram, if we reboot before the obsoleted /old/SW1 erased,
after reboot, there will be a hard link between /old/SW1 and /SW1.
Then, /old/SW1 and /SW1 share inode,but in jffs2_build_remove_unlinked_inode will
make /old/SW1's inode obsolete.So, if we want to enter /SW1,
we'll found /SW1 has none valid nodes and got -EIO. /SW1 dirent can not access.

Thanks!

Best Regards


More information about the linux-mtd mailing list