aboutsummaryrefslogtreecommitdiffstats
path: root/fsck
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-12-13 13:55:59 -0800
committerJP Abgrall <jpa@google.com>2015-03-23 10:10:26 -0700
commitc511d5d0ec5290dbf1e4e1bc8afc8ddd8feac4c4 (patch)
tree3ddbc1bbb849dab6fc1ed59137a2984f0f0c2452 /fsck
parent1e69ed2c8a4164968f853a28a8ae54afefaaae4c (diff)
downloadandroid_external_f2fs-tools-c511d5d0ec5290dbf1e4e1bc8afc8ddd8feac4c4.tar.gz
android_external_f2fs-tools-c511d5d0ec5290dbf1e4e1bc8afc8ddd8feac4c4.tar.bz2
android_external_f2fs-tools-c511d5d0ec5290dbf1e4e1bc8afc8ddd8feac4c4.zip
dump.f2fs: dump owner of data given block address
This patch introduces a feature to dump owner information of given block address. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fsck')
-rw-r--r--fsck/dump.c161
-rw-r--r--fsck/f2fs.h12
-rw-r--r--fsck/fsck.h4
-rw-r--r--fsck/main.c2
-rw-r--r--fsck/mount.c14
5 files changed, 169 insertions, 24 deletions
diff --git a/fsck/dump.c b/fsck/dump.c
index 4bb906f..3c4a8d1 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -11,6 +11,7 @@
#include <inttypes.h>
#include "fsck.h"
+#include <locale.h>
#define BUF_SZ 80
@@ -298,13 +299,114 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid)
free(node_blk);
}
-int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
+static void dump_node_from_blkaddr(u32 blk_addr)
{
- nid_t ino, nid;
- int type, ret;
- struct f2fs_summary sum_entry;
- struct node_info ni;
struct f2fs_node *node_blk;
+ int ret;
+
+ node_blk = calloc(BLOCK_SZ, 1);
+ ASSERT(node_blk);
+
+ ret = dev_read_block(node_blk, blk_addr);
+ ASSERT(ret >= 0);
+
+ if (config.dbg_lv > 0)
+ print_node_info(node_blk);
+ else
+ print_inode_info(&node_blk->i, 1);
+
+ free(node_blk);
+}
+
+static void dump_data_offset(u32 blk_addr, int ofs_in_node)
+{
+ struct f2fs_node *node_blk;
+ unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
+ unsigned int bidx = 0;
+ unsigned int node_ofs;
+ int ret;
+
+ node_blk = calloc(BLOCK_SZ, 1);
+ ASSERT(node_blk);
+
+ ret = dev_read_block(node_blk, blk_addr);
+ ASSERT(ret >= 0);
+
+ node_ofs = ofs_of_node(node_blk);
+
+ if (node_ofs == 0)
+ goto got_it;
+
+ if (node_ofs > 0 && node_ofs <= 2) {
+ bidx = node_ofs - 1;
+ } else if (node_ofs <= indirect_blks) {
+ int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
+ bidx = node_ofs - 2 - dec;
+ } else {
+ int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
+ bidx = node_ofs - 5 - dec;
+ }
+ bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(&node_blk->i);
+got_it:
+ bidx += ofs_in_node;
+
+ setlocale(LC_ALL, "");
+ MSG(0, " - Data offset : 0x%x (4KB), %'u (bytes)\n",
+ bidx, bidx * 4096);
+ free(node_blk);
+}
+
+static void dump_node_offset(u32 blk_addr)
+{
+ struct f2fs_node *node_blk;
+ int ret;
+
+ node_blk = calloc(BLOCK_SZ, 1);
+ ASSERT(node_blk);
+
+ ret = dev_read_block(node_blk, blk_addr);
+ ASSERT(ret >= 0);
+
+ MSG(0, " - Node offset : 0x%x\n", ofs_of_node(node_blk));
+ free(node_blk);
+}
+
+int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
+{
+ nid_t nid;
+ int type;
+ struct f2fs_summary sum_entry;
+ struct node_info ni, ino_ni;
+ int ret = 0;
+
+ MSG(0, "\n== Dump data from block address ==\n\n");
+
+ if (blk_addr < SM_I(sbi)->seg0_blkaddr) {
+ MSG(0, "\nFS Reserved Area for SEG #0: ");
+ ret = -EINVAL;
+ } else if (blk_addr < SIT_I(sbi)->sit_base_addr) {
+ MSG(0, "\nFS Metadata Area: ");
+ ret = -EINVAL;
+ } else if (blk_addr < NM_I(sbi)->nat_blkaddr) {
+ MSG(0, "\nFS SIT Area: ");
+ ret = -EINVAL;
+ } else if (blk_addr < SM_I(sbi)->ssa_blkaddr) {
+ MSG(0, "\nFS NAT Area: ");
+ ret = -EINVAL;
+ } else if (blk_addr < SM_I(sbi)->main_blkaddr) {
+ MSG(0, "\nFS SSA Area: ");
+ ret = -EINVAL;
+ } else if (blk_addr > __end_block_addr(sbi)) {
+ MSG(0, "\nOut of address space: ");
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ MSG(0, "User data is from 0x%x to 0x%x\n\n",
+ SM_I(sbi)->main_blkaddr,
+ __end_block_addr(sbi));
+ return ret;
+ }
type = get_sum_entry(sbi, blk_addr, &sum_entry);
nid = le32_to_cpu(sum_entry.nid);
@@ -318,26 +420,47 @@ int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
DBG(1, "SUM.nid [0x%x]\n", nid);
DBG(1, "SUM.type [%s]\n", seg_type_name[type]);
DBG(1, "SUM.version [%d]\n", sum_entry.version);
- DBG(1, "SUM.ofs_in_node [%d]\n", sum_entry.ofs_in_node);
+ DBG(1, "SUM.ofs_in_node [0x%x]\n", sum_entry.ofs_in_node);
DBG(1, "NAT.blkaddr [0x%x]\n", ni.blk_addr);
DBG(1, "NAT.ino [0x%x]\n", ni.ino);
- node_blk = calloc(BLOCK_SZ, 1);
-
-read_node_blk:
- ret = dev_read_block(node_blk, blk_addr);
- ASSERT(ret >= 0);
+ get_node_info(sbi, ni.ino, &ino_ni);
- ino = le32_to_cpu(node_blk->footer.ino);
- nid = le32_to_cpu(node_blk->footer.nid);
+ /* inode block address */
+ if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) {
+ MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n",
+ blk_addr);
+ return -EINVAL;
+ }
- if (ino == nid) {
- print_node_info(node_blk);
+ /* print inode */
+ if (config.dbg_lv > 0)
+ dump_node_from_blkaddr(ino_ni.blk_addr);
+
+ if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
+ MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
+ MSG(0, " - Direct node block : id = 0x%x from 0x%x\n",
+ nid, ni.blk_addr);
+ MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
+ ni.ino, ino_ni.blk_addr);
+ dump_node_from_blkaddr(ino_ni.blk_addr);
+ dump_data_offset(ni.blk_addr,
+ le16_to_cpu(sum_entry.ofs_in_node));
} else {
- get_node_info(sbi, ino, &ni);
- goto read_node_blk;
+ MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr);
+ if (ni.ino == ni.nid) {
+ MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
+ ni.ino, ino_ni.blk_addr);
+ dump_node_from_blkaddr(ino_ni.blk_addr);
+ } else {
+ MSG(0, " - Node block : id = 0x%x from 0x%x\n",
+ nid, ni.blk_addr);
+ MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
+ ni.ino, ino_ni.blk_addr);
+ dump_node_from_blkaddr(ino_ni.blk_addr);
+ dump_node_offset(ni.blk_addr);
+ }
}
- free(node_blk);
- return ino;
+ return 0;
}
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 57bad9b..c268f15 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -197,6 +197,12 @@ static inline void *inline_data_addr(struct f2fs_node *node_blk)
return (void *)&(node_blk->i.i_addr[1]);
}
+static inline unsigned int ofs_of_node(struct f2fs_node *node_blk)
+{
+ unsigned flag = le32_to_cpu(node_blk->footer.flag);
+ return flag >> OFFSET_BIT_SHIFT;
+}
+
static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
@@ -255,6 +261,12 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
}
+static inline block_t __end_block_addr(struct f2fs_sb_info *sbi)
+{
+ block_t end = SM_I(sbi)->main_blkaddr;
+ return end + le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count);
+}
+
#define GET_ZONENO_FROM_SEGNO(sbi, segno) \
((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 49d6d1d..9cad013 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -97,7 +97,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
u32 *, u32 *);
extern void print_node_info(struct f2fs_node *);
-extern void print_inode_info(struct f2fs_inode *);
+extern void print_inode_info(struct f2fs_inode *, int);
extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
extern int get_sum_block(struct f2fs_sb_info *, unsigned int,
struct f2fs_summary_block *);
@@ -126,6 +126,6 @@ struct dump_option {
extern void sit_dump(struct f2fs_sb_info *, int, int);
extern void ssa_dump(struct f2fs_sb_info *, int, int);
extern void dump_node(struct f2fs_sb_info *, nid_t);
-extern int dump_inode_from_blkaddr(struct f2fs_sb_info *, u32);
+extern int dump_info_from_blkaddr(struct f2fs_sb_info *, u32);
#endif /* _FSCK_H_ */
diff --git a/fsck/main.c b/fsck/main.c
index 2af3daf..e05e528 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -169,7 +169,7 @@ static void do_dump(struct f2fs_sb_info *sbi)
if (opt->start_ssa != -1)
ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
if (opt->blk_addr != -1) {
- dump_inode_from_blkaddr(sbi, opt->blk_addr);
+ dump_info_from_blkaddr(sbi, opt->blk_addr);
goto cleanup;
}
dump_node(sbi, opt->nid);
diff --git a/fsck/mount.c b/fsck/mount.c
index 0aca60b..73eba6b 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -9,12 +9,22 @@
* published by the Free Software Foundation.
*/
#include "fsck.h"
+#include <locale.h>
-void print_inode_info(struct f2fs_inode *inode)
+void print_inode_info(struct f2fs_inode *inode, int name)
{
unsigned int i = 0;
int namelen = le32_to_cpu(inode->i_namelen);
+ if (name && namelen) {
+ inode->i_name[namelen] = '\0';
+ MSG(0, " - File name : %s\n", inode->i_name);
+ setlocale(LC_ALL, "");
+ MSG(0, " - File size : %'llu (bytes)\n",
+ le64_to_cpu(inode->i_size));
+ return;
+ }
+
DISP_u32(inode, i_mode);
DISP_u32(inode, i_uid);
DISP_u32(inode, i_gid);
@@ -76,7 +86,7 @@ void print_node_info(struct f2fs_node *node_block)
/* Is this inode? */
if (ino == nid) {
DBG(0, "Node ID [0x%x:%u] is inode\n", nid, nid);
- print_inode_info(&node_block->i);
+ print_inode_info(&node_block->i, 0);
} else {
int i;
u32 *dump_blk = (u32 *)node_block;