144c10e7183ea9464cd460e33e502ff1026d8be2
[platform/upstream/f2fs-tools.git] / fsck / dump.c
1 /**
2  * dump.c
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5  *             http://www.samsung.com/
6  *
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.
10  */
11 #include <inttypes.h>
12
13 #include "node.h"
14 #include "fsck.h"
15 #include "xattr.h"
16 #ifdef HAVE_ATTR_XATTR_H
17 #include <attr/xattr.h>
18 #endif
19 #ifdef HAVE_LINUX_XATTR_H
20 #include <linux/xattr.h>
21 #endif
22 #include <locale.h>
23
24 #define BUF_SZ  80
25
26 const char *seg_type_name[SEG_TYPE_MAX + 1] = {
27         "SEG_TYPE_DATA",
28         "SEG_TYPE_CUR_DATA",
29         "SEG_TYPE_NODE",
30         "SEG_TYPE_CUR_NODE",
31         "SEG_TYPE_NONE",
32 };
33
34 void nat_dump(struct f2fs_sb_info *sbi, nid_t start_nat, nid_t end_nat)
35 {
36         struct f2fs_nat_block *nat_block;
37         struct f2fs_node *node_block;
38         nid_t nid;
39         pgoff_t block_addr;
40         char buf[BUF_SZ];
41         int fd, ret, pack;
42
43         nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
44         ASSERT(nat_block);
45         node_block = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
46         ASSERT(node_block);
47
48         fd = open("dump_nat", O_CREAT|O_WRONLY|O_TRUNC, 0666);
49         ASSERT(fd >= 0);
50
51         for (nid = start_nat; nid < end_nat; nid++) {
52                 struct f2fs_nat_entry raw_nat;
53                 struct node_info ni;
54                 if(nid == 0 || nid == F2FS_NODE_INO(sbi) ||
55                                         nid == F2FS_META_INO(sbi))
56                         continue;
57
58                 ni.nid = nid;
59                 block_addr = current_nat_addr(sbi, nid, &pack);
60
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);
64                         ASSERT(ret >= 0);
65                         if (ni.blk_addr != 0x0) {
66                                 memset(buf, 0, BUF_SZ);
67                                 snprintf(buf, BUF_SZ,
68                                         "nid:%5u\tino:%5u\toffset:%5u"
69                                         "\tblkaddr:%10u\tpack:%d\n",
70                                         ni.nid, ni.ino,
71                                         le32_to_cpu(node_block->footer.flag) >>
72                                                 OFFSET_BIT_SHIFT,
73                                         ni.blk_addr, pack);
74                                 ret = write(fd, buf, strlen(buf));
75                                 ASSERT(ret >= 0);
76                         }
77                 } else {
78                         ret = dev_read_block(nat_block, block_addr);
79                         ASSERT(ret >= 0);
80                         node_info_from_raw_nat(&ni,
81                                         &nat_block->entries[nid % NAT_ENTRY_PER_BLOCK]);
82                         if (ni.blk_addr == 0)
83                                 continue;
84
85                         ret = dev_read_block(node_block, ni.blk_addr);
86                         ASSERT(ret >= 0);
87                         memset(buf, 0, BUF_SZ);
88                         snprintf(buf, BUF_SZ,
89                                 "nid:%5u\tino:%5u\toffset:%5u"
90                                 "\tblkaddr:%10u\tpack:%d\n",
91                                 ni.nid, ni.ino,
92                                 le32_to_cpu(node_block->footer.flag) >>
93                                         OFFSET_BIT_SHIFT,
94                                 ni.blk_addr, pack);
95                         ret = write(fd, buf, strlen(buf));
96                         ASSERT(ret >= 0);
97                 }
98         }
99
100         free(nat_block);
101         free(node_block);
102
103         close(fd);
104 }
105
106 void sit_dump(struct f2fs_sb_info *sbi, unsigned int start_sit,
107                                         unsigned int end_sit)
108 {
109         struct seg_entry *se;
110         struct sit_info *sit_i = SIT_I(sbi);
111         unsigned int segno;
112         char buf[BUF_SZ];
113         u32 free_segs = 0;;
114         u64 valid_blocks = 0;
115         int ret;
116         int fd, i;
117         unsigned int offset;
118
119         fd = open("dump_sit", O_CREAT|O_WRONLY|O_TRUNC, 0666);
120         ASSERT(fd >= 0);
121
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));
125         ASSERT(ret >= 0);
126
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);
135
136                 ret = write(fd, buf, strlen(buf));
137                 ASSERT(ret >= 0);
138
139                 if (se->valid_blocks == 0x0) {
140                         free_segs++;
141                         continue;
142                 }
143
144                 ASSERT(se->valid_blocks <= 512);
145                 valid_blocks += se->valid_blocks;
146
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));
152                         ASSERT(ret >= 0);
153
154                         if ((i + 1) % 16 == 0) {
155                                 snprintf(buf, BUF_SZ, "\n");
156                                 ret = write(fd, buf, strlen(buf));
157                                 ASSERT(ret >= 0);
158                         }
159                 }
160         }
161
162         memset(buf, 0, BUF_SZ);
163         snprintf(buf, BUF_SZ,
164                 "valid_blocks:[0x%" PRIx64 "]\tvalid_segs:%d\t free_segs:%d\n",
165                         valid_blocks,
166                         SM_I(sbi)->main_segments - free_segs,
167                         free_segs);
168         ret = write(fd, buf, strlen(buf));
169         ASSERT(ret >= 0);
170
171         close(fd);
172 }
173
174 void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
175 {
176         struct f2fs_summary_block *sum_blk;
177         char buf[BUF_SZ];
178         int segno, type, i, ret;
179         int fd;
180
181         fd = open("dump_ssa", O_CREAT|O_WRONLY|O_TRUNC, 0666);
182         ASSERT(fd >= 0);
183
184         snprintf(buf, BUF_SZ, "Note: dump.f2fs -b blkaddr = 0x%x + segno * "
185                                 " 0x200 + offset\n",
186                                 sbi->sm_info->main_blkaddr);
187         ret = write(fd, buf, strlen(buf));
188         ASSERT(ret >= 0);
189
190         for (segno = start_ssa; segno < end_ssa; segno++) {
191                 sum_blk = get_sum_block(sbi, segno, &type);
192
193                 memset(buf, 0, BUF_SZ);
194                 switch (type) {
195                 case SEG_TYPE_CUR_NODE:
196                         snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Node\n", segno);
197                         break;
198                 case SEG_TYPE_CUR_DATA:
199                         snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Data\n", segno);
200                         break;
201                 case SEG_TYPE_NODE:
202                         snprintf(buf, BUF_SZ, "\n\nsegno: %x, Node\n", segno);
203                         break;
204                 case SEG_TYPE_DATA:
205                         snprintf(buf, BUF_SZ, "\n\nsegno: %x, Data\n", segno);
206                         break;
207                 }
208                 ret = write(fd, buf, strlen(buf));
209                 ASSERT(ret >= 0);
210
211                 for (i = 0; i < ENTRIES_IN_SUM; i++) {
212                         memset(buf, 0, BUF_SZ);
213                         if (i % 10 == 0) {
214                                 buf[0] = '\n';
215                                 ret = write(fd, buf, strlen(buf));
216                                 ASSERT(ret >= 0);
217                         }
218                         snprintf(buf, BUF_SZ, "[%3d: %6x]", i,
219                                         le32_to_cpu(sum_blk->entries[i].nid));
220                         ret = write(fd, buf, strlen(buf));
221                         ASSERT(ret >= 0);
222                 }
223                 if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
224                                         type == SEG_TYPE_MAX)
225                         free(sum_blk);
226         }
227         close(fd);
228 }
229
230 static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 blkaddr)
231 {
232         char buf[F2FS_BLKSIZE];
233
234         if (blkaddr == NULL_ADDR)
235                 return;
236
237         /* get data */
238         if (blkaddr == NEW_ADDR || !IS_VALID_BLK_ADDR(sbi, blkaddr)) {
239                 memset(buf, 0, F2FS_BLKSIZE);
240         } else {
241                 int ret;
242                 ret = dev_read_block(buf, blkaddr);
243                 ASSERT(ret >= 0);
244         }
245
246         /* write blkaddr */
247         dev_write_dump(buf, offset, F2FS_BLKSIZE);
248 }
249
250 static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
251                                                 u32 nid, u64 *ofs)
252 {
253         struct node_info ni;
254         struct f2fs_node *node_blk;
255         u32 skip = 0;
256         u32 i, idx = 0;
257
258         get_node_info(sbi, nid, &ni);
259
260         node_blk = calloc(BLOCK_SZ, 1);
261         ASSERT(node_blk);
262
263         dev_read_block(node_blk, ni.blk_addr);
264
265         switch (ntype) {
266         case TYPE_DIRECT_NODE:
267                 skip = idx = ADDRS_PER_BLOCK(&node_blk->i);
268                 break;
269         case TYPE_INDIRECT_NODE:
270                 idx = NIDS_PER_BLOCK;
271                 skip = idx * ADDRS_PER_BLOCK(&node_blk->i);
272                 break;
273         case TYPE_DOUBLE_INDIRECT_NODE:
274                 skip = 0;
275                 idx = NIDS_PER_BLOCK;
276                 break;
277         }
278
279         if (nid == 0) {
280                 *ofs += skip;
281                 return;
282         }
283
284         for (i = 0; i < idx; i++, (*ofs)++) {
285                 switch (ntype) {
286                 case TYPE_DIRECT_NODE:
287                         dump_data_blk(sbi, *ofs * F2FS_BLKSIZE,
288                                         le32_to_cpu(node_blk->dn.addr[i]));
289                         break;
290                 case TYPE_INDIRECT_NODE:
291                         dump_node_blk(sbi, TYPE_DIRECT_NODE,
292                                         le32_to_cpu(node_blk->in.nid[i]), ofs);
293                         break;
294                 case TYPE_DOUBLE_INDIRECT_NODE:
295                         dump_node_blk(sbi, TYPE_INDIRECT_NODE,
296                                         le32_to_cpu(node_blk->in.nid[i]), ofs);
297                         break;
298                 }
299         }
300         free(node_blk);
301 }
302
303 #ifdef HAVE_FSETXATTR
304 static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk)
305 {
306         void *xattr;
307         struct f2fs_xattr_entry *ent;
308         char xattr_name[F2FS_NAME_LEN] = {0};
309         int ret;
310
311         xattr = read_all_xattrs(sbi, node_blk);
312
313         list_for_each_xattr(ent, xattr) {
314                 char *name = strndup(ent->e_name, ent->e_name_len);
315                 void *value = ent->e_name + ent->e_name_len;
316
317                 if (!name)
318                         continue;
319
320                 switch (ent->e_name_index) {
321                 case F2FS_XATTR_INDEX_USER:
322                         ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
323                                        XATTR_USER_PREFIX, name);
324                         break;
325
326                 case F2FS_XATTR_INDEX_SECURITY:
327                         ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
328                                        XATTR_SECURITY_PREFIX, name);
329                         break;
330                 case F2FS_XATTR_INDEX_TRUSTED:
331                         ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
332                                        XATTR_TRUSTED_PREFIX, name);
333                         break;
334                 default:
335                         MSG(0, "Unknown xattr index 0x%x\n", ent->e_name_index);
336                         free(name);
337                         continue;
338                 }
339                 if (ret >= F2FS_NAME_LEN) {
340                         MSG(0, "XATTR index 0x%x name too long\n", ent->e_name_index);
341                         free(name);
342                         continue;
343                 }
344
345                 DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name);
346 #if defined(__linux__)
347                 ret = fsetxattr(c.dump_fd, xattr_name, value,
348                                 le16_to_cpu(ent->e_value_size), 0);
349 #elif defined(__APPLE__)
350                 ret = fsetxattr(c.dump_fd, xattr_name, value,
351                                 le16_to_cpu(ent->e_value_size), 0,
352                                 XATTR_CREATE);
353 #endif
354                 if (ret)
355                         MSG(0, "XATTR index 0x%x set xattr failed error %d\n",
356                             ent->e_name_index, errno);
357
358                 free(name);
359         }
360
361         free(xattr);
362 }
363 #else
364 static void dump_xattr(struct f2fs_sb_info *UNUSED(sbi),
365                                 struct f2fs_node *UNUSED(node_blk))
366 {
367         MSG(0, "XATTR does not support\n");
368 }
369 #endif
370
371 static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
372                                         struct f2fs_node *node_blk)
373 {
374         u32 i = 0;
375         u64 ofs = 0;
376
377         if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
378                 DBG(3, "ino[0x%x] has inline data!\n", nid);
379                 /* recover from inline data */
380                 dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
381                                                 0, MAX_INLINE_DATA(node_blk));
382                 return;
383         }
384
385         /* check data blocks in inode */
386         for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
387                 dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu(
388                         node_blk->i.i_addr[get_extra_isize(node_blk) + i]));
389
390         /* check node blocks in inode */
391         for (i = 0; i < 5; i++) {
392                 if (i == 0 || i == 1)
393                         dump_node_blk(sbi, TYPE_DIRECT_NODE,
394                                         le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
395                 else if (i == 2 || i == 3)
396                         dump_node_blk(sbi, TYPE_INDIRECT_NODE,
397                                         le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
398                 else if (i == 4)
399                         dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
400                                         le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
401                 else
402                         ASSERT(0);
403         }
404
405         dump_xattr(sbi, node_blk);
406 }
407
408 static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
409                                 struct f2fs_node *node_blk, int force)
410 {
411         struct f2fs_inode *inode = &node_blk->i;
412         u32 imode = le16_to_cpu(inode->i_mode);
413         u32 namelen = le32_to_cpu(inode->i_namelen);
414         char name[F2FS_NAME_LEN + 1] = {0};
415         char path[1024] = {0};
416         char ans[255] = {0};
417         int is_encrypted = file_is_encrypt(inode);
418         int ret;
419
420         if (is_encrypted) {
421                 MSG(force, "File is encrypted\n");
422                 return;
423         }
424
425         if (!S_ISREG(imode) || namelen == 0 || namelen > F2FS_NAME_LEN) {
426                 MSG(force, "Not a regular file or wrong name info\n\n");
427                 return;
428         }
429         if (force)
430                 goto dump;
431
432         printf("Do you want to dump this file into ./lost_found/? [Y/N] ");
433         ret = scanf("%s", ans);
434         ASSERT(ret >= 0);
435
436         if (!strcasecmp(ans, "y")) {
437 dump:
438                 ret = system("mkdir -p ./lost_found");
439                 ASSERT(ret >= 0);
440
441                 /* make a file */
442                 strncpy(name, (const char *)inode->i_name, namelen);
443                 name[namelen] = 0;
444                 sprintf(path, "./lost_found/%s", name);
445
446                 c.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666);
447                 ASSERT(c.dump_fd >= 0);
448
449                 /* dump file's data */
450                 dump_inode_blk(sbi, ni->ino, node_blk);
451
452                 /* adjust file size */
453                 ret = ftruncate(c.dump_fd, le32_to_cpu(inode->i_size));
454                 ASSERT(ret >= 0);
455
456                 close(c.dump_fd);
457         }
458 }
459
460 static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr)
461 {
462         struct seg_entry *se;
463         u32 offset;
464
465         se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr));
466         offset = OFFSET_IN_SEG(sbi, blk_addr);
467
468         return f2fs_test_bit(offset,
469                         (const char *)se->cur_valid_map) != 0;
470 }
471
472 void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
473 {
474         struct node_info ni;
475         struct f2fs_node *node_blk;
476
477         get_node_info(sbi, nid, &ni);
478
479         node_blk = calloc(BLOCK_SZ, 1);
480         ASSERT(node_blk);
481
482         dev_read_block(node_blk, ni.blk_addr);
483
484         DBG(1, "Node ID               [0x%x]\n", nid);
485         DBG(1, "nat_entry.block_addr  [0x%x]\n", ni.blk_addr);
486         DBG(1, "nat_entry.version     [0x%x]\n", ni.version);
487         DBG(1, "nat_entry.ino         [0x%x]\n", ni.ino);
488
489         if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
490                 MSG(force, "Invalid node blkaddr: %u\n\n", ni.blk_addr);
491                 goto out;
492         }
493
494         if (ni.blk_addr == 0x0)
495                 MSG(force, "Invalid nat entry\n\n");
496         else if (!is_sit_bitmap_set(sbi, ni.blk_addr))
497                 MSG(force, "Invalid sit bitmap, %u\n\n", ni.blk_addr);
498
499         DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino));
500         DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid));
501
502         if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
503                         le32_to_cpu(node_blk->footer.nid) == ni.nid) {
504                 print_node_info(sbi, node_blk, force);
505
506                 if (ni.ino == ni.nid)
507                         dump_file(sbi, &ni, node_blk, force);
508         } else {
509                 print_node_info(sbi, node_blk, force);
510                 MSG(force, "Invalid (i)node block\n\n");
511         }
512 out:
513         free(node_blk);
514 }
515
516 static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
517 {
518         struct f2fs_node *node_blk;
519         int ret;
520
521         node_blk = calloc(BLOCK_SZ, 1);
522         ASSERT(node_blk);
523
524         ret = dev_read_block(node_blk, blk_addr);
525         ASSERT(ret >= 0);
526
527         if (c.dbg_lv > 0)
528                 print_node_info(sbi, node_blk, 0);
529         else
530                 print_inode_info(sbi, node_blk, 1);
531
532         free(node_blk);
533 }
534
535 unsigned int start_bidx_of_node(unsigned int node_ofs,
536                                         struct f2fs_node *node_blk)
537 {
538         unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
539         unsigned int bidx;
540
541         if (node_ofs == 0)
542                 return 0;
543
544         if (node_ofs <= 2) {
545                 bidx = node_ofs - 1;
546         } else if (node_ofs <= indirect_blks) {
547                 int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
548                 bidx = node_ofs - 2 - dec;
549         } else {
550                 int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
551                 bidx = node_ofs - 5 - dec;
552         }
553         return bidx * ADDRS_PER_BLOCK(&node_blk->i) +
554                                 ADDRS_PER_INODE(&node_blk->i);
555 }
556
557 static void dump_data_offset(u32 blk_addr, int ofs_in_node)
558 {
559         struct f2fs_node *node_blk;
560         unsigned int bidx;
561         unsigned int node_ofs;
562         int ret;
563
564         node_blk = calloc(BLOCK_SZ, 1);
565         ASSERT(node_blk);
566
567         ret = dev_read_block(node_blk, blk_addr);
568         ASSERT(ret >= 0);
569
570         node_ofs = ofs_of_node(node_blk);
571
572         bidx = start_bidx_of_node(node_ofs, node_blk);
573         bidx +=  ofs_in_node;
574
575         setlocale(LC_ALL, "");
576         MSG(0, " - Data offset       : 0x%x (4KB), %'u (bytes)\n",
577                                 bidx, bidx * 4096);
578         free(node_blk);
579 }
580
581 static void dump_node_offset(u32 blk_addr)
582 {
583         struct f2fs_node *node_blk;
584         int ret;
585
586         node_blk = calloc(BLOCK_SZ, 1);
587         ASSERT(node_blk);
588
589         ret = dev_read_block(node_blk, blk_addr);
590         ASSERT(ret >= 0);
591
592         MSG(0, " - Node offset       : 0x%x\n", ofs_of_node(node_blk));
593         free(node_blk);
594 }
595
596 static int has_dirent(u32 blk_addr, int is_inline, int *enc_name)
597 {
598         struct f2fs_node *node_blk;
599         int ret, is_dentry = 0;
600
601         node_blk = calloc(BLOCK_SZ, 1);
602         ASSERT(node_blk);
603
604         ret = dev_read_block(node_blk, blk_addr);
605         ASSERT(ret >= 0);
606
607         if (IS_INODE(node_blk) && S_ISDIR(le16_to_cpu(node_blk->i.i_mode)))
608                 is_dentry = 1;
609
610         if (is_inline && !(node_blk->i.i_inline & F2FS_INLINE_DENTRY))
611                 is_dentry = 0;
612
613         *enc_name = file_is_encrypt(&node_blk->i);
614
615         free(node_blk);
616
617         return is_dentry;
618 }
619
620 static void dump_dirent(u32 blk_addr, int is_inline, int enc_name)
621 {
622         struct f2fs_dentry_ptr d;
623         void *inline_dentry, *blk;
624         int ret, i = 0;
625
626         blk = calloc(BLOCK_SZ, 1);
627         ASSERT(blk);
628
629         ret = dev_read_block(blk, blk_addr);
630         ASSERT(ret >= 0);
631
632         if (is_inline) {
633                 inline_dentry = inline_data_addr((struct f2fs_node *)blk);
634                 make_dentry_ptr(&d, blk, inline_dentry, 2);
635         } else {
636                 make_dentry_ptr(&d, NULL, blk, 1);
637         }
638
639         DBG(1, "%sDentry block:\n", is_inline ? "Inline " : "");
640
641         while (i < d.max) {
642                 struct f2fs_dir_entry *de;
643                 char en[F2FS_PRINT_NAMELEN];
644                 u16 name_len;
645                 int enc;
646
647                 if (!test_bit_le(i, d.bitmap)) {
648                         i++;
649                         continue;
650                 }
651
652                 de = &d.dentry[i];
653
654                 if (!de->name_len) {
655                         i++;
656                         continue;
657                 }
658
659                 name_len = le16_to_cpu(de->name_len);
660                 enc = enc_name;
661
662                 if (de->file_type == F2FS_FT_DIR) {
663                         if ((d.filename[i][0] == '.' && name_len == 1) ||
664                                 (d.filename[i][0] == '.' &&
665                                 d.filename[i][1] == '.' && name_len == 2)) {
666                                 enc = 0;
667                         }
668                 }
669
670                 pretty_print_filename(d.filename[i], name_len, en, enc);
671
672                 DBG(1, "bitmap pos[0x%x] name[%s] len[0x%x] hash[0x%x] ino[0x%x] type[0x%x]\n",
673                                 i, en,
674                                 name_len,
675                                 le32_to_cpu(de->hash_code),
676                                 le32_to_cpu(de->ino),
677                                 de->file_type);
678
679                 i += GET_DENTRY_SLOTS(name_len);
680         }
681
682         free(blk);
683 }
684
685 int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
686 {
687         nid_t nid;
688         int type;
689         struct f2fs_summary sum_entry;
690         struct node_info ni, ino_ni;
691         int enc_name;
692         int ret = 0;
693
694         MSG(0, "\n== Dump data from block address ==\n\n");
695
696         if (blk_addr < SM_I(sbi)->seg0_blkaddr) {
697                 MSG(0, "\nFS Reserved Area for SEG #0: ");
698                 ret = -EINVAL;
699         } else if (blk_addr < SIT_I(sbi)->sit_base_addr) {
700                 MSG(0, "\nFS Metadata Area: ");
701                 ret = -EINVAL;
702         } else if (blk_addr < NM_I(sbi)->nat_blkaddr) {
703                 MSG(0, "\nFS SIT Area: ");
704                 ret = -EINVAL;
705         } else if (blk_addr < SM_I(sbi)->ssa_blkaddr) {
706                 MSG(0, "\nFS NAT Area: ");
707                 ret = -EINVAL;
708         } else if (blk_addr < SM_I(sbi)->main_blkaddr) {
709                 MSG(0, "\nFS SSA Area: ");
710                 ret = -EINVAL;
711         } else if (blk_addr > __end_block_addr(sbi)) {
712                 MSG(0, "\nOut of address space: ");
713                 ret = -EINVAL;
714         }
715
716         if (ret) {
717                 MSG(0, "User data is from 0x%x to 0x%x\n\n",
718                         SM_I(sbi)->main_blkaddr,
719                         __end_block_addr(sbi));
720                 return ret;
721         }
722
723         if (!is_sit_bitmap_set(sbi, blk_addr))
724                 MSG(0, "\nblkaddr is not valid\n");
725
726         type = get_sum_entry(sbi, blk_addr, &sum_entry);
727         nid = le32_to_cpu(sum_entry.nid);
728
729         get_node_info(sbi, nid, &ni);
730
731         DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n");
732         DBG(1, "Block_addr            [0x%x]\n", blk_addr);
733         DBG(1, " - Segno              [0x%x]\n", GET_SEGNO(sbi, blk_addr));
734         DBG(1, " - Offset             [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr));
735         DBG(1, "SUM.nid               [0x%x]\n", nid);
736         DBG(1, "SUM.type              [%s]\n", type >= 0 ?
737                                                 seg_type_name[type] :
738                                                 "Broken");
739         DBG(1, "SUM.version           [%d]\n", sum_entry.version);
740         DBG(1, "SUM.ofs_in_node       [0x%x]\n", sum_entry.ofs_in_node);
741         DBG(1, "NAT.blkaddr           [0x%x]\n", ni.blk_addr);
742         DBG(1, "NAT.ino               [0x%x]\n", ni.ino);
743
744         get_node_info(sbi, ni.ino, &ino_ni);
745
746         /* inode block address */
747         if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) {
748                 MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n",
749                         blk_addr);
750                 return -EINVAL;
751         }
752
753         /* print inode */
754         if (c.dbg_lv > 0)
755                 dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
756
757         if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
758                 MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
759                 MSG(0, " - Direct node block : id = 0x%x from 0x%x\n",
760                                         nid, ni.blk_addr);
761                 MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
762                                         ni.ino, ino_ni.blk_addr);
763                 dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
764                 dump_data_offset(ni.blk_addr,
765                         le16_to_cpu(sum_entry.ofs_in_node));
766
767                 if (has_dirent(ino_ni.blk_addr, 0, &enc_name))
768                         dump_dirent(blk_addr, 0, enc_name);
769         } else {
770                 MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr);
771                 if (ni.ino == ni.nid) {
772                         MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
773                                         ni.ino, ino_ni.blk_addr);
774                         dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
775
776                         if (has_dirent(ino_ni.blk_addr, 1, &enc_name))
777                                 dump_dirent(blk_addr, 1, enc_name);
778                 } else {
779                         MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
780                                         nid, ni.blk_addr);
781                         MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
782                                         ni.ino, ino_ni.blk_addr);
783                         dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
784                         dump_node_offset(ni.blk_addr);
785                 }
786         }
787
788         return 0;
789 }