[PATCH] nilfs2: correct logic of translation virtual blocks number into physical ones

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

The issue report is contained description of mount failure:

[  822.390075] NILFS version 2 loaded
[  822.436888] segctord starting. Construction interval = 5 seconds, CP frequency < 30 seconds
[  822.437107] NILFS: corrupt root inode.

The first phase of investigation discovered that it tries to read
really something wrong instead of root inode:

[ 4148.318860] NILFS HEXDUMP (fs/nilfs2/inode.c, 529): nilfs_read_inode_common:
[ 4148.318864] raw_inode: ffff880076b3c100: 2e 0a 09 20 20 41 54 41 50 49 20 69 73 20 61 20  ...  ATAPI is a
[ 4148.318866] raw_inode: ffff880076b3c110: 6e 65 77 65 72 20 70 72 6f 74 6f 63 6f 6c 20 75  newer protocol u
[ 4148.318869] raw_inode: ffff880076b3c120: 73 65 64 20 62 79 20 49 44 45 20 74 61 70 65 20  sed by IDE tape
[ 4148.318871] raw_inode: ffff880076b3c130: 61 6e 64 20 43 44 2d 52 4f 4d 20 64 72 69 76 65  and CD-ROM drive
[ 4148.318874] raw_inode: ffff880076b3c140: 73 2c 0a 09 20 20 73 69 6d 69 6c 61 72 20 74 6f  s,..  similar to
[ 4148.318876] raw_inode: ffff880076b3c150: 20 74 68 65 20 53 43 53 49 20 70 72 6f 74 6f 63   the SCSI protoc
[ 4148.318879] raw_inode: ffff880076b3c160: 6f 6c 2e 20 20 49 66 20 79 6f 75 20 68 61 76 65  ol.  If you have
[ 4148.318881] raw_inode: ffff880076b3c170: 20 61 6e 20 53 43 53 49 20 74 61 70 65 20 64 72   an SCSI tape dr

Thereby, it means that file system has some corruption that
results in reading of wrong block.

The second phase of investigation is discovered such things:

[  236.389166] NILFS DEBUG (fs/nilfs2/inode.c, 527): nilfs_read_inode_common:
[  236.389171] i_ino 6
[  236.389175] NILFS HEXDUMP (fs/nilfs2/inode.c, 529): nilfs_read_inode_common:
[  236.389180] raw_inode: ffff88007056b640: fb 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00  .`..............
[  236.389186] raw_inode: ffff88007056b650: a1 8f 2d 50 00 00 00 00 a1 8f 2d 50 00 00 00 00  ..-P......-P....
[  236.389190] raw_inode: ffff88007056b660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
[  236.389195] raw_inode: ffff88007056b670: 00 80 01 00 00 00 00 00 01 03 01 00 00 00 00 00  ................
[  236.389199] raw_inode: ffff88007056b680: 00 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00  ................
[  236.389203] raw_inode: ffff88007056b690: fe 01 00 00 00 00 00 00 e7 f4 09 00 00 00 00 00  ................
[  236.389208] raw_inode: ffff88007056b6a0: 04 33 04 00 00 00 00 00 05 33 04 00 00 00 00 00  .3.......3......
[  236.389212] raw_inode: ffff88007056b6b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Namely, block of ifile's btree of second level is located in 0x9f4e7 (#652519)
virtual block number.

[  945.415667] NILFS DEBUG (fs/nilfs2/mdt.c, 148): nilfs_mdt_submit_block:
[  945.415670] i_ino 6, blkoff 2, mode 0x0, out_bh ffff88007055dac8
[  945.415691] NILFS DEBUG (fs/nilfs2/bmap.c, 87): nilfs_bmap_lookup_at_level:
[  945.415694] i_ino 6, key 2, level 1

[  945.415734] NILFS DEBUG (fs/nilfs2/dat.c, 488): nilfs_dat_translate:
[  945.415737] i_ino 3, vblocknr 652519, blocknrp ffff88007055d870
[  945.415752] NILFS DEBUG (fs/nilfs2/mdt.c, 148): nilfs_mdt_submit_block:
[  945.415754] i_ino 3, blkoff 5118, mode 0x0, out_bh ffff88007055d638
[  945.417063] NILFS DEBUG (fs/nilfs2/dat.c, 516): nilfs_dat_translate:
[  945.417065] blocknr 405468

As a result, we have #405468 physical block number after translation.

segment: segnum = 197
  sequence number = 568325, next segnum = 198
partial segment: blocknr = 405460, nblocks = 44
    creation time = 2013-06-23 05:00:59
      ino = 6, cno = 373808, nblocks = 8, ndatblk = 6
        vblocknr = 692137, blocknr = 405467
        vblocknr = 652519, blocknr = 405468

The dumpseg output includes info about this [652519 : 405468] blocks pair.

The block #405468 contains information about virtual block on the next level.

dd if=/dev/loop0 bs=4096 skip=405468 | hexdump -vC

00000000  00 02 0d 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  ff 00 00 00 00 00 00 00  |................|

00000800  00 00 00 00 00 00 00 00  a9 8f 0a 00 00 00 00 00  |................|
00000810  80 43 08 00 00 00 00 00  e0 cf 07 00 00 00 00 00  |.C..............|

Virtual block number of next btree level is #a8fa9 (#692137).

[ 945.417138] NILFS DEBUG (fs/nilfs2/dat.c, 488): nilfs_dat_translate:
[  945.417141] i_ino 3, vblocknr 692137, blocknrp ffff88007055d870
[  945.417156] NILFS DEBUG (fs/nilfs2/mdt.c, 148): nilfs_mdt_submit_block:
[  945.417158] i_ino 3, blkoff 5430, mode 0x0, out_bh ffff88007055d638
[  945.418361] NILFS DEBUG (fs/nilfs2/dat.c, 516): nilfs_dat_translate:
[  945.418363] blocknr 405467

As a result, we have #405467 physical block number after translation.

segment: segnum = 197
  sequence number = 568325, next segnum = 198
   partial segment: blocknr = 405460, nblocks = 44
    creation time = 2013-06-23 05:00:59
      ino = 6, cno = 373808, nblocks = 8, ndatblk = 6
        vblocknr = 692137, blocknr = 405467
        vblocknr = 652519, blocknr = 405468

The dumpseg output includes info about this [692137 : 405467] blocks pair.

The block #405467 contains information about virtual block that
describes location of ifile block with blkoff = 2.

dd if=/dev/loop0 bs=4096 skip=405467 | hexdump -vC

00000000  00 01 ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|
00000020  02 00 00 00 00 00 00 00  03 00 00 00 00 00 00 00  |................|

00000800  fe 00 00 00 00 00 00 00  6d 78 0b 00 00 00 00 00  |........mx......|
00000810  85 39 09 00 00 00 00 00  de 67 07 00 00 00 00 00  |.9.......g......|

The virtual block of ifile block with blkoff = 2 is 0x767de (#485342).
But dumpseg output for all segments on the partition doesn't contain
virtual block with such number. However, translation of virtual block
number into physical results with #51321 block number.

[  945.418420] NILFS DEBUG (fs/nilfs2/dat.c, 488): nilfs_dat_translate:
[  945.418423] i_ino 3, vblocknr 485342, blocknrp ffff88007055da30
[  945.418438] NILFS DEBUG (fs/nilfs2/mdt.c, 148): nilfs_mdt_submit_block:
[  945.418440] i_ino 3, blkoff 3807, mode 0x0, out_bh ffff88007055d808
[  945.418626] NILFS DEBUG (fs/nilfs2/bmap.c, 106): nilfs_bmap_lookup_at_level:
[  945.418629] ptr 353444
[  945.419557] NILFS DEBUG (fs/nilfs2/dat.c, 516): nilfs_dat_translate:
[  945.419559] blocknr 51321

Such result takes place because of calculated block (#353444) of DAT file
on blkoff 3807 contains:

dd if=/dev/loop0 bs=4096 skip=353444 | hexdump -vC

00000bc0  79 c8 00 00 00 00 00 00  95 b1 05 00 00 00 00 00  |y...............|
00000bd0  96 b1 05 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

But block 0xc879 (51321) was alive from checkpoint 0x5b195 (#373141)
till checkpoint 0x5b196 (#373142). So, it makes sense to add logic
of comparing current checkpoint number with start and end checkpoint
numbers. And, if current checkpoint is outside of checkpoints range
of requested block then operation of translation should fail with
error.

With the best regards,
Vyacheslav Dubeyko.
---
From: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
Subject: [PATCH] nilfs2: correct logic of translation virtual blocks number into physical ones

The issue report is contained description of mount failure:

[  822.390075] NILFS version 2 loaded
[  822.436888] segctord starting. Construction interval = 5 seconds, CP frequency < 30 seconds
[  822.437107] NILFS: corrupt root inode.

Investigation of the issue discovered that it takes places
reading of ifile's block from not proper placement because of
successful ending of operation of virtual block number translation
into physical one.

This patch adds checking of start checkpoint and end checkpoint by
comparing with current checkpoint number during translation of
virtual block number into physical block number. Because it makes
sense to operate with blocks that are alive for current checkpoint.

As a result, mount fails with such error message:

[17348.793335] NILFS warning (device loop0): nilfs_ifile_get_inode_block: unable to read inode: 2
[17348.793869] NILFS: get root inode failed

Reported-by: Bryce Gibson <bryce@xxxxxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
CC: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx>
---
 fs/nilfs2/dat.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index fa0f803..08d9268 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -396,9 +396,11 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
  */
 int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
 {
+	struct the_nilfs *nilfs = dat->i_sb->s_fs_info;
 	struct buffer_head *entry_bh, *bh;
 	struct nilfs_dat_entry *entry;
 	sector_t blocknr;
+	__u64 cur_cno, start_cno, end_cno;
 	void *kaddr;
 	int ret;
 
@@ -422,6 +424,13 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
 		ret = -ENOENT;
 		goto out;
 	}
+	cur_cno = nilfs->ns_cno;
+	start_cno = le64_to_cpu(entry->de_start);
+	end_cno = le64_to_cpu(entry->de_end);
+	if (cur_cno < start_cno || cur_cno > end_cno) {
+		ret = -ENOENT;
+		goto out;
+	}
 	*blocknrp = blocknr;
 
  out:
-- 
1.7.9.5



--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux