4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
16 #ifdef HAVE_ATTR_XATTR_H
17 #include <attr/xattr.h>
19 #ifdef HAVE_LINUX_XATTR_H
20 #include <linux/xattr.h>
26 const char *seg_type_name[SEG_TYPE_MAX + 1] = {
34 void nat_dump(struct f2fs_sb_info *sbi, nid_t start_nat, nid_t end_nat)
36 struct f2fs_nat_block *nat_block;
37 struct f2fs_node *node_block;
43 nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
45 node_block = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
48 fd = open("dump_nat", O_CREAT|O_WRONLY|O_TRUNC, 0666);
51 for (nid = start_nat; nid < end_nat; nid++) {
52 struct f2fs_nat_entry raw_nat;
54 if(nid == 0 || nid == F2FS_NODE_INO(sbi) ||
55 nid == F2FS_META_INO(sbi))
59 block_addr = current_nat_addr(sbi, nid, &pack);
61 if (lookup_nat_in_journal(sbi, nid, &raw_nat) >= 0) {
62 node_info_from_raw_nat(&ni, &raw_nat);
63 ret = dev_read_block(node_block, ni.blk_addr);
65 if (ni.blk_addr != 0x0) {
66 memset(buf, 0, BUF_SZ);
68 "nid:%5u\tino:%5u\toffset:%5u"
69 "\tblkaddr:%10u\tpack:%d\n",
71 le32_to_cpu(node_block->footer.flag) >>
74 ret = write(fd, buf, strlen(buf));
78 ret = dev_read_block(nat_block, block_addr);
80 node_info_from_raw_nat(&ni,
81 &nat_block->entries[nid % NAT_ENTRY_PER_BLOCK]);
85 ret = dev_read_block(node_block, ni.blk_addr);
87 memset(buf, 0, BUF_SZ);
89 "nid:%5u\tino:%5u\toffset:%5u"
90 "\tblkaddr:%10u\tpack:%d\n",
92 le32_to_cpu(node_block->footer.flag) >>
95 ret = write(fd, buf, strlen(buf));
106 void sit_dump(struct f2fs_sb_info *sbi, unsigned int start_sit,
107 unsigned int end_sit)
109 struct seg_entry *se;
110 struct sit_info *sit_i = SIT_I(sbi);
114 u64 valid_blocks = 0;
119 fd = open("dump_sit", O_CREAT|O_WRONLY|O_TRUNC, 0666);
122 snprintf(buf, BUF_SZ, "segment_type(0:HD, 1:WD, 2:CD, "
123 "3:HN, 4:WN, 5:CN)\n");
124 ret = write(fd, buf, strlen(buf));
127 for (segno = start_sit; segno < end_sit; segno++) {
128 se = get_seg_entry(sbi, segno);
129 offset = SIT_BLOCK_OFFSET(sit_i, segno);
130 memset(buf, 0, BUF_SZ);
131 snprintf(buf, BUF_SZ,
132 "\nsegno:%8u\tvblocks:%3u\tseg_type:%d\tsit_pack:%d\n\n",
133 segno, se->valid_blocks, se->type,
134 f2fs_test_bit(offset, sit_i->sit_bitmap) ? 2 : 1);
136 ret = write(fd, buf, strlen(buf));
139 if (se->valid_blocks == 0x0) {
144 ASSERT(se->valid_blocks <= 512);
145 valid_blocks += se->valid_blocks;
147 for (i = 0; i < 64; i++) {
148 memset(buf, 0, BUF_SZ);
149 snprintf(buf, BUF_SZ, " %02x",
150 *(se->cur_valid_map + i));
151 ret = write(fd, buf, strlen(buf));
154 if ((i + 1) % 16 == 0) {
155 snprintf(buf, BUF_SZ, "\n");
156 ret = write(fd, buf, strlen(buf));
162 memset(buf, 0, BUF_SZ);
163 snprintf(buf, BUF_SZ,
164 "valid_blocks:[0x%" PRIx64 "]\tvalid_segs:%d\t free_segs:%d\n",
166 SM_I(sbi)->main_segments - free_segs,
168 ret = write(fd, buf, strlen(buf));
174 void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
176 struct f2fs_summary_block *sum_blk;
178 int segno, type, i, ret;
181 fd = open("dump_ssa", O_CREAT|O_WRONLY|O_TRUNC, 0666);
184 snprintf(buf, BUF_SZ, "Note: dump.f2fs -b blkaddr = 0x%x + segno * "
186 sbi->sm_info->main_blkaddr);
187 ret = write(fd, buf, strlen(buf));
190 for (segno = start_ssa; segno < end_ssa; segno++) {
191 sum_blk = get_sum_block(sbi, segno, &type);
193 memset(buf, 0, BUF_SZ);
195 case SEG_TYPE_CUR_NODE:
196 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Node\n", segno);
198 case SEG_TYPE_CUR_DATA:
199 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Data\n", segno);
202 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Node\n", segno);
205 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Data\n", segno);
208 ret = write(fd, buf, strlen(buf));
211 for (i = 0; i < ENTRIES_IN_SUM; i++) {
212 memset(buf, 0, BUF_SZ);
215 ret = write(fd, buf, strlen(buf));
218 snprintf(buf, BUF_SZ, "[%3d: %6x]", i,
219 le32_to_cpu(sum_blk->entries[i].nid));
220 ret = write(fd, buf, strlen(buf));
223 if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
224 type == SEG_TYPE_MAX)
230 static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 blkaddr)
232 char buf[F2FS_BLKSIZE];
234 if (blkaddr == NULL_ADDR)
238 if (blkaddr == NEW_ADDR || !IS_VALID_BLK_ADDR(sbi, blkaddr)) {
239 memset(buf, 0, F2FS_BLKSIZE);
242 ret = dev_read_block(buf, blkaddr);
247 dev_write_dump(buf, offset, F2FS_BLKSIZE);
250 static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
254 struct f2fs_node *node_blk;
258 get_node_info(sbi, nid, &ni);
260 node_blk = calloc(BLOCK_SZ, 1);
263 dev_read_block(node_blk, ni.blk_addr);
266 case TYPE_DIRECT_NODE:
267 skip = idx = ADDRS_PER_BLOCK(&node_blk->i);
269 case TYPE_INDIRECT_NODE:
270 idx = NIDS_PER_BLOCK;
271 skip = idx * ADDRS_PER_BLOCK(&node_blk->i);
273 case TYPE_DOUBLE_INDIRECT_NODE:
275 idx = NIDS_PER_BLOCK;
284 for (i = 0; i < idx; i++, (*ofs)++) {
286 case TYPE_DIRECT_NODE:
287 dump_data_blk(sbi, *ofs * F2FS_BLKSIZE,
288 le32_to_cpu(node_blk->dn.addr[i]));
290 case TYPE_INDIRECT_NODE:
291 dump_node_blk(sbi, TYPE_DIRECT_NODE,
292 le32_to_cpu(node_blk->in.nid[i]), ofs);
294 case TYPE_DOUBLE_INDIRECT_NODE:
295 dump_node_blk(sbi, TYPE_INDIRECT_NODE,
296 le32_to_cpu(node_blk->in.nid[i]), ofs);
303 #ifdef HAVE_FSETXATTR
304 static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk)
307 struct f2fs_xattr_entry *ent;
308 char xattr_name[F2FS_NAME_LEN] = {0};
311 xattr = read_all_xattrs(sbi, node_blk);
315 list_for_each_xattr(ent, xattr) {
316 char *name = strndup(ent->e_name, ent->e_name_len);
317 void *value = ent->e_name + ent->e_name_len;
322 switch (ent->e_name_index) {
323 case F2FS_XATTR_INDEX_USER:
324 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
325 XATTR_USER_PREFIX, name);
328 case F2FS_XATTR_INDEX_SECURITY:
329 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
330 XATTR_SECURITY_PREFIX, name);
332 case F2FS_XATTR_INDEX_TRUSTED:
333 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
334 XATTR_TRUSTED_PREFIX, name);
337 MSG(0, "Unknown xattr index 0x%x\n", ent->e_name_index);
341 if (ret >= F2FS_NAME_LEN) {
342 MSG(0, "XATTR index 0x%x name too long\n", ent->e_name_index);
347 DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name);
348 #if defined(__linux__)
349 ret = fsetxattr(c.dump_fd, xattr_name, value,
350 le16_to_cpu(ent->e_value_size), 0);
351 #elif defined(__APPLE__)
352 ret = fsetxattr(c.dump_fd, xattr_name, value,
353 le16_to_cpu(ent->e_value_size), 0,
357 MSG(0, "XATTR index 0x%x set xattr failed error %d\n",
358 ent->e_name_index, errno);
366 static void dump_xattr(struct f2fs_sb_info *UNUSED(sbi),
367 struct f2fs_node *UNUSED(node_blk))
369 MSG(0, "XATTR does not support\n");
373 static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
374 struct f2fs_node *node_blk)
379 if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
380 DBG(3, "ino[0x%x] has inline data!\n", nid);
381 /* recover from inline data */
382 dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
383 0, MAX_INLINE_DATA(node_blk));
387 /* check data blocks in inode */
388 for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
389 dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu(
390 node_blk->i.i_addr[get_extra_isize(node_blk) + i]));
392 /* check node blocks in inode */
393 for (i = 0; i < 5; i++) {
394 if (i == 0 || i == 1)
395 dump_node_blk(sbi, TYPE_DIRECT_NODE,
396 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
397 else if (i == 2 || i == 3)
398 dump_node_blk(sbi, TYPE_INDIRECT_NODE,
399 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
401 dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
402 le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
407 dump_xattr(sbi, node_blk);
410 static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
411 struct f2fs_node *node_blk, int force)
413 struct f2fs_inode *inode = &node_blk->i;
414 u32 imode = le16_to_cpu(inode->i_mode);
415 u32 namelen = le32_to_cpu(inode->i_namelen);
416 char name[F2FS_NAME_LEN + 1] = {0};
417 char path[1024] = {0};
419 int is_encrypted = file_is_encrypt(inode);
423 MSG(force, "File is encrypted\n");
427 if (!S_ISREG(imode) || namelen == 0 || namelen > F2FS_NAME_LEN) {
428 MSG(force, "Not a regular file or wrong name info\n\n");
434 printf("Do you want to dump this file into ./lost_found/? [Y/N] ");
435 ret = scanf("%s", ans);
438 if (!strcasecmp(ans, "y")) {
440 ret = system("mkdir -p ./lost_found");
444 strncpy(name, (const char *)inode->i_name, namelen);
446 sprintf(path, "./lost_found/%s", name);
448 c.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666);
449 ASSERT(c.dump_fd >= 0);
451 /* dump file's data */
452 dump_inode_blk(sbi, ni->ino, node_blk);
454 /* adjust file size */
455 ret = ftruncate(c.dump_fd, le32_to_cpu(inode->i_size));
462 static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr)
464 struct seg_entry *se;
467 se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr));
468 offset = OFFSET_IN_SEG(sbi, blk_addr);
470 return f2fs_test_bit(offset,
471 (const char *)se->cur_valid_map) != 0;
474 void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
477 struct f2fs_node *node_blk;
479 get_node_info(sbi, nid, &ni);
481 node_blk = calloc(BLOCK_SZ, 1);
484 dev_read_block(node_blk, ni.blk_addr);
486 DBG(1, "Node ID [0x%x]\n", nid);
487 DBG(1, "nat_entry.block_addr [0x%x]\n", ni.blk_addr);
488 DBG(1, "nat_entry.version [0x%x]\n", ni.version);
489 DBG(1, "nat_entry.ino [0x%x]\n", ni.ino);
491 if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
492 MSG(force, "Invalid node blkaddr: %u\n\n", ni.blk_addr);
496 if (ni.blk_addr == 0x0)
497 MSG(force, "Invalid nat entry\n\n");
498 else if (!is_sit_bitmap_set(sbi, ni.blk_addr))
499 MSG(force, "Invalid sit bitmap, %u\n\n", ni.blk_addr);
501 DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino));
502 DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid));
504 if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
505 le32_to_cpu(node_blk->footer.nid) == ni.nid) {
506 print_node_info(sbi, node_blk, force);
508 if (ni.ino == ni.nid)
509 dump_file(sbi, &ni, node_blk, force);
511 print_node_info(sbi, node_blk, force);
512 MSG(force, "Invalid (i)node block\n\n");
518 static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
520 struct f2fs_node *node_blk;
523 node_blk = calloc(BLOCK_SZ, 1);
526 ret = dev_read_block(node_blk, blk_addr);
530 print_node_info(sbi, node_blk, 0);
532 print_inode_info(sbi, node_blk, 1);
537 unsigned int start_bidx_of_node(unsigned int node_ofs,
538 struct f2fs_node *node_blk)
540 unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
548 } else if (node_ofs <= indirect_blks) {
549 int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
550 bidx = node_ofs - 2 - dec;
552 int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
553 bidx = node_ofs - 5 - dec;
555 return bidx * ADDRS_PER_BLOCK(&node_blk->i) +
556 ADDRS_PER_INODE(&node_blk->i);
559 static void dump_data_offset(u32 blk_addr, int ofs_in_node)
561 struct f2fs_node *node_blk;
563 unsigned int node_ofs;
566 node_blk = calloc(BLOCK_SZ, 1);
569 ret = dev_read_block(node_blk, blk_addr);
572 node_ofs = ofs_of_node(node_blk);
574 bidx = start_bidx_of_node(node_ofs, node_blk);
577 setlocale(LC_ALL, "");
578 MSG(0, " - Data offset : 0x%x (4KB), %'u (bytes)\n",
583 static void dump_node_offset(u32 blk_addr)
585 struct f2fs_node *node_blk;
588 node_blk = calloc(BLOCK_SZ, 1);
591 ret = dev_read_block(node_blk, blk_addr);
594 MSG(0, " - Node offset : 0x%x\n", ofs_of_node(node_blk));
598 static int has_dirent(u32 blk_addr, int is_inline, int *enc_name)
600 struct f2fs_node *node_blk;
601 int ret, is_dentry = 0;
603 node_blk = calloc(BLOCK_SZ, 1);
606 ret = dev_read_block(node_blk, blk_addr);
609 if (IS_INODE(node_blk) && S_ISDIR(le16_to_cpu(node_blk->i.i_mode)))
612 if (is_inline && !(node_blk->i.i_inline & F2FS_INLINE_DENTRY))
615 *enc_name = file_is_encrypt(&node_blk->i);
622 static void dump_dirent(u32 blk_addr, int is_inline, int enc_name)
624 struct f2fs_dentry_ptr d;
625 void *inline_dentry, *blk;
628 blk = calloc(BLOCK_SZ, 1);
631 ret = dev_read_block(blk, blk_addr);
635 inline_dentry = inline_data_addr((struct f2fs_node *)blk);
636 make_dentry_ptr(&d, blk, inline_dentry, 2);
638 make_dentry_ptr(&d, NULL, blk, 1);
641 DBG(1, "%sDentry block:\n", is_inline ? "Inline " : "");
644 struct f2fs_dir_entry *de;
645 char en[F2FS_PRINT_NAMELEN];
649 if (!test_bit_le(i, d.bitmap)) {
661 name_len = le16_to_cpu(de->name_len);
664 if (de->file_type == F2FS_FT_DIR) {
665 if ((d.filename[i][0] == '.' && name_len == 1) ||
666 (d.filename[i][0] == '.' &&
667 d.filename[i][1] == '.' && name_len == 2)) {
672 pretty_print_filename(d.filename[i], name_len, en, enc);
674 DBG(1, "bitmap pos[0x%x] name[%s] len[0x%x] hash[0x%x] ino[0x%x] type[0x%x]\n",
677 le32_to_cpu(de->hash_code),
678 le32_to_cpu(de->ino),
681 i += GET_DENTRY_SLOTS(name_len);
687 int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
691 struct f2fs_summary sum_entry;
692 struct node_info ni, ino_ni;
696 MSG(0, "\n== Dump data from block address ==\n\n");
698 if (blk_addr < SM_I(sbi)->seg0_blkaddr) {
699 MSG(0, "\nFS Reserved Area for SEG #0: ");
701 } else if (blk_addr < SIT_I(sbi)->sit_base_addr) {
702 MSG(0, "\nFS Metadata Area: ");
704 } else if (blk_addr < NM_I(sbi)->nat_blkaddr) {
705 MSG(0, "\nFS SIT Area: ");
707 } else if (blk_addr < SM_I(sbi)->ssa_blkaddr) {
708 MSG(0, "\nFS NAT Area: ");
710 } else if (blk_addr < SM_I(sbi)->main_blkaddr) {
711 MSG(0, "\nFS SSA Area: ");
713 } else if (blk_addr > __end_block_addr(sbi)) {
714 MSG(0, "\nOut of address space: ");
719 MSG(0, "User data is from 0x%x to 0x%x\n\n",
720 SM_I(sbi)->main_blkaddr,
721 __end_block_addr(sbi));
725 if (!is_sit_bitmap_set(sbi, blk_addr))
726 MSG(0, "\nblkaddr is not valid\n");
728 type = get_sum_entry(sbi, blk_addr, &sum_entry);
729 nid = le32_to_cpu(sum_entry.nid);
731 get_node_info(sbi, nid, &ni);
733 DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n");
734 DBG(1, "Block_addr [0x%x]\n", blk_addr);
735 DBG(1, " - Segno [0x%x]\n", GET_SEGNO(sbi, blk_addr));
736 DBG(1, " - Offset [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr));
737 DBG(1, "SUM.nid [0x%x]\n", nid);
738 DBG(1, "SUM.type [%s]\n", type >= 0 ?
739 seg_type_name[type] :
741 DBG(1, "SUM.version [%d]\n", sum_entry.version);
742 DBG(1, "SUM.ofs_in_node [0x%x]\n", sum_entry.ofs_in_node);
743 DBG(1, "NAT.blkaddr [0x%x]\n", ni.blk_addr);
744 DBG(1, "NAT.ino [0x%x]\n", ni.ino);
746 get_node_info(sbi, ni.ino, &ino_ni);
748 /* inode block address */
749 if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) {
750 MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n",
757 dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
759 if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
760 MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
761 MSG(0, " - Direct node block : id = 0x%x from 0x%x\n",
763 MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
764 ni.ino, ino_ni.blk_addr);
765 dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
766 dump_data_offset(ni.blk_addr,
767 le16_to_cpu(sum_entry.ofs_in_node));
769 if (has_dirent(ino_ni.blk_addr, 0, &enc_name))
770 dump_dirent(blk_addr, 0, enc_name);
772 MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr);
773 if (ni.ino == ni.nid) {
774 MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
775 ni.ino, ino_ni.blk_addr);
776 dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
778 if (has_dirent(ino_ni.blk_addr, 1, &enc_name))
779 dump_dirent(blk_addr, 1, enc_name);
781 MSG(0, " - Node block : id = 0x%x from 0x%x\n",
783 MSG(0, " - Inode block : id = 0x%x from 0x%x\n",
784 ni.ino, ino_ni.blk_addr);
785 dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
786 dump_node_offset(ni.blk_addr);