1*59bfda1fSAndroid Build Coastguard Worker /**
2*59bfda1fSAndroid Build Coastguard Worker * fsck.c
3*59bfda1fSAndroid Build Coastguard Worker *
4*59bfda1fSAndroid Build Coastguard Worker * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5*59bfda1fSAndroid Build Coastguard Worker * http://www.samsung.com/
6*59bfda1fSAndroid Build Coastguard Worker *
7*59bfda1fSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
8*59bfda1fSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License version 2 as
9*59bfda1fSAndroid Build Coastguard Worker * published by the Free Software Foundation.
10*59bfda1fSAndroid Build Coastguard Worker */
11*59bfda1fSAndroid Build Coastguard Worker #include "fsck.h"
12*59bfda1fSAndroid Build Coastguard Worker #include "xattr.h"
13*59bfda1fSAndroid Build Coastguard Worker #include "quotaio.h"
14*59bfda1fSAndroid Build Coastguard Worker #include <time.h>
15*59bfda1fSAndroid Build Coastguard Worker
16*59bfda1fSAndroid Build Coastguard Worker char *tree_mark;
17*59bfda1fSAndroid Build Coastguard Worker uint32_t tree_mark_size = 256;
18*59bfda1fSAndroid Build Coastguard Worker
f2fs_set_main_bitmap(struct f2fs_sb_info * sbi,u32 blk,int type)19*59bfda1fSAndroid Build Coastguard Worker int f2fs_set_main_bitmap(struct f2fs_sb_info *sbi, u32 blk, int type)
20*59bfda1fSAndroid Build Coastguard Worker {
21*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
22*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
23*59bfda1fSAndroid Build Coastguard Worker int fix = 0;
24*59bfda1fSAndroid Build Coastguard Worker
25*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, GET_SEGNO(sbi, blk));
26*59bfda1fSAndroid Build Coastguard Worker if (se->type >= NO_CHECK_TYPE)
27*59bfda1fSAndroid Build Coastguard Worker fix = 1;
28*59bfda1fSAndroid Build Coastguard Worker else if (IS_DATASEG(se->type) != IS_DATASEG(type))
29*59bfda1fSAndroid Build Coastguard Worker fix = 1;
30*59bfda1fSAndroid Build Coastguard Worker
31*59bfda1fSAndroid Build Coastguard Worker /* just check data and node types */
32*59bfda1fSAndroid Build Coastguard Worker if (fix) {
33*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Wrong segment type [0x%x] %x -> %x",
34*59bfda1fSAndroid Build Coastguard Worker GET_SEGNO(sbi, blk), se->type, type);
35*59bfda1fSAndroid Build Coastguard Worker se->type = type;
36*59bfda1fSAndroid Build Coastguard Worker }
37*59bfda1fSAndroid Build Coastguard Worker return f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->main_area_bitmap);
38*59bfda1fSAndroid Build Coastguard Worker }
39*59bfda1fSAndroid Build Coastguard Worker
f2fs_test_main_bitmap(struct f2fs_sb_info * sbi,u32 blk)40*59bfda1fSAndroid Build Coastguard Worker static inline int f2fs_test_main_bitmap(struct f2fs_sb_info *sbi, u32 blk)
41*59bfda1fSAndroid Build Coastguard Worker {
42*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
43*59bfda1fSAndroid Build Coastguard Worker
44*59bfda1fSAndroid Build Coastguard Worker return f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk),
45*59bfda1fSAndroid Build Coastguard Worker fsck->main_area_bitmap);
46*59bfda1fSAndroid Build Coastguard Worker }
47*59bfda1fSAndroid Build Coastguard Worker
f2fs_clear_main_bitmap(struct f2fs_sb_info * sbi,u32 blk)48*59bfda1fSAndroid Build Coastguard Worker int f2fs_clear_main_bitmap(struct f2fs_sb_info *sbi, u32 blk)
49*59bfda1fSAndroid Build Coastguard Worker {
50*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
51*59bfda1fSAndroid Build Coastguard Worker
52*59bfda1fSAndroid Build Coastguard Worker return f2fs_clear_bit(BLKOFF_FROM_MAIN(sbi, blk),
53*59bfda1fSAndroid Build Coastguard Worker fsck->main_area_bitmap);
54*59bfda1fSAndroid Build Coastguard Worker }
55*59bfda1fSAndroid Build Coastguard Worker
f2fs_test_sit_bitmap(struct f2fs_sb_info * sbi,u32 blk)56*59bfda1fSAndroid Build Coastguard Worker static inline int f2fs_test_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk)
57*59bfda1fSAndroid Build Coastguard Worker {
58*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
59*59bfda1fSAndroid Build Coastguard Worker
60*59bfda1fSAndroid Build Coastguard Worker return f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->sit_area_bitmap);
61*59bfda1fSAndroid Build Coastguard Worker }
62*59bfda1fSAndroid Build Coastguard Worker
f2fs_set_sit_bitmap(struct f2fs_sb_info * sbi,u32 blk)63*59bfda1fSAndroid Build Coastguard Worker int f2fs_set_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk)
64*59bfda1fSAndroid Build Coastguard Worker {
65*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
66*59bfda1fSAndroid Build Coastguard Worker
67*59bfda1fSAndroid Build Coastguard Worker return f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk), fsck->sit_area_bitmap);
68*59bfda1fSAndroid Build Coastguard Worker }
69*59bfda1fSAndroid Build Coastguard Worker
f2fs_clear_sit_bitmap(struct f2fs_sb_info * sbi,u32 blk)70*59bfda1fSAndroid Build Coastguard Worker int f2fs_clear_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk)
71*59bfda1fSAndroid Build Coastguard Worker {
72*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
73*59bfda1fSAndroid Build Coastguard Worker
74*59bfda1fSAndroid Build Coastguard Worker return f2fs_clear_bit(BLKOFF_FROM_MAIN(sbi, blk),
75*59bfda1fSAndroid Build Coastguard Worker fsck->sit_area_bitmap);
76*59bfda1fSAndroid Build Coastguard Worker }
77*59bfda1fSAndroid Build Coastguard Worker
add_into_hard_link_list(struct f2fs_sb_info * sbi,u32 nid,u32 link_cnt)78*59bfda1fSAndroid Build Coastguard Worker static int add_into_hard_link_list(struct f2fs_sb_info *sbi,
79*59bfda1fSAndroid Build Coastguard Worker u32 nid, u32 link_cnt)
80*59bfda1fSAndroid Build Coastguard Worker {
81*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
82*59bfda1fSAndroid Build Coastguard Worker struct hard_link_node *node = NULL, *tmp = NULL, *prev = NULL;
83*59bfda1fSAndroid Build Coastguard Worker
84*59bfda1fSAndroid Build Coastguard Worker node = calloc(sizeof(struct hard_link_node), 1);
85*59bfda1fSAndroid Build Coastguard Worker ASSERT(node != NULL);
86*59bfda1fSAndroid Build Coastguard Worker
87*59bfda1fSAndroid Build Coastguard Worker node->nid = nid;
88*59bfda1fSAndroid Build Coastguard Worker node->links = link_cnt;
89*59bfda1fSAndroid Build Coastguard Worker node->actual_links = 1;
90*59bfda1fSAndroid Build Coastguard Worker node->next = NULL;
91*59bfda1fSAndroid Build Coastguard Worker
92*59bfda1fSAndroid Build Coastguard Worker if (fsck->hard_link_list_head == NULL) {
93*59bfda1fSAndroid Build Coastguard Worker fsck->hard_link_list_head = node;
94*59bfda1fSAndroid Build Coastguard Worker goto out;
95*59bfda1fSAndroid Build Coastguard Worker }
96*59bfda1fSAndroid Build Coastguard Worker
97*59bfda1fSAndroid Build Coastguard Worker tmp = fsck->hard_link_list_head;
98*59bfda1fSAndroid Build Coastguard Worker
99*59bfda1fSAndroid Build Coastguard Worker /* Find insertion position */
100*59bfda1fSAndroid Build Coastguard Worker while (tmp && (nid < tmp->nid)) {
101*59bfda1fSAndroid Build Coastguard Worker ASSERT(tmp->nid != nid);
102*59bfda1fSAndroid Build Coastguard Worker prev = tmp;
103*59bfda1fSAndroid Build Coastguard Worker tmp = tmp->next;
104*59bfda1fSAndroid Build Coastguard Worker }
105*59bfda1fSAndroid Build Coastguard Worker
106*59bfda1fSAndroid Build Coastguard Worker if (tmp == fsck->hard_link_list_head) {
107*59bfda1fSAndroid Build Coastguard Worker node->next = tmp;
108*59bfda1fSAndroid Build Coastguard Worker fsck->hard_link_list_head = node;
109*59bfda1fSAndroid Build Coastguard Worker } else {
110*59bfda1fSAndroid Build Coastguard Worker prev->next = node;
111*59bfda1fSAndroid Build Coastguard Worker node->next = tmp;
112*59bfda1fSAndroid Build Coastguard Worker }
113*59bfda1fSAndroid Build Coastguard Worker
114*59bfda1fSAndroid Build Coastguard Worker out:
115*59bfda1fSAndroid Build Coastguard Worker DBG(2, "ino[0x%x] has hard links [0x%x]\n", nid, link_cnt);
116*59bfda1fSAndroid Build Coastguard Worker return 0;
117*59bfda1fSAndroid Build Coastguard Worker }
118*59bfda1fSAndroid Build Coastguard Worker
find_and_dec_hard_link_list(struct f2fs_sb_info * sbi,u32 nid)119*59bfda1fSAndroid Build Coastguard Worker static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid)
120*59bfda1fSAndroid Build Coastguard Worker {
121*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
122*59bfda1fSAndroid Build Coastguard Worker struct hard_link_node *node = NULL, *prev = NULL;
123*59bfda1fSAndroid Build Coastguard Worker
124*59bfda1fSAndroid Build Coastguard Worker if (fsck->hard_link_list_head == NULL)
125*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
126*59bfda1fSAndroid Build Coastguard Worker
127*59bfda1fSAndroid Build Coastguard Worker node = fsck->hard_link_list_head;
128*59bfda1fSAndroid Build Coastguard Worker
129*59bfda1fSAndroid Build Coastguard Worker while (node && (nid < node->nid)) {
130*59bfda1fSAndroid Build Coastguard Worker prev = node;
131*59bfda1fSAndroid Build Coastguard Worker node = node->next;
132*59bfda1fSAndroid Build Coastguard Worker }
133*59bfda1fSAndroid Build Coastguard Worker
134*59bfda1fSAndroid Build Coastguard Worker if (node == NULL || (nid != node->nid))
135*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
136*59bfda1fSAndroid Build Coastguard Worker
137*59bfda1fSAndroid Build Coastguard Worker /* Decrease link count */
138*59bfda1fSAndroid Build Coastguard Worker node->links = node->links - 1;
139*59bfda1fSAndroid Build Coastguard Worker node->actual_links++;
140*59bfda1fSAndroid Build Coastguard Worker
141*59bfda1fSAndroid Build Coastguard Worker /* if link count becomes one, remove the node */
142*59bfda1fSAndroid Build Coastguard Worker if (node->links == 1) {
143*59bfda1fSAndroid Build Coastguard Worker if (fsck->hard_link_list_head == node)
144*59bfda1fSAndroid Build Coastguard Worker fsck->hard_link_list_head = node->next;
145*59bfda1fSAndroid Build Coastguard Worker else
146*59bfda1fSAndroid Build Coastguard Worker prev->next = node->next;
147*59bfda1fSAndroid Build Coastguard Worker free(node);
148*59bfda1fSAndroid Build Coastguard Worker }
149*59bfda1fSAndroid Build Coastguard Worker return 0;
150*59bfda1fSAndroid Build Coastguard Worker }
151*59bfda1fSAndroid Build Coastguard Worker
is_valid_ssa_node_blk(struct f2fs_sb_info * sbi,u32 nid,u32 blk_addr)152*59bfda1fSAndroid Build Coastguard Worker static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid,
153*59bfda1fSAndroid Build Coastguard Worker u32 blk_addr)
154*59bfda1fSAndroid Build Coastguard Worker {
155*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
156*59bfda1fSAndroid Build Coastguard Worker struct f2fs_summary_block *sum_blk;
157*59bfda1fSAndroid Build Coastguard Worker struct f2fs_summary *sum_entry;
158*59bfda1fSAndroid Build Coastguard Worker struct seg_entry * se;
159*59bfda1fSAndroid Build Coastguard Worker u32 segno, offset;
160*59bfda1fSAndroid Build Coastguard Worker int need_fix = 0, ret = 0;
161*59bfda1fSAndroid Build Coastguard Worker int type;
162*59bfda1fSAndroid Build Coastguard Worker
163*59bfda1fSAndroid Build Coastguard Worker if (get_sb(feature) & F2FS_FEATURE_RO)
164*59bfda1fSAndroid Build Coastguard Worker return 0;
165*59bfda1fSAndroid Build Coastguard Worker
166*59bfda1fSAndroid Build Coastguard Worker segno = GET_SEGNO(sbi, blk_addr);
167*59bfda1fSAndroid Build Coastguard Worker offset = OFFSET_IN_SEG(sbi, blk_addr);
168*59bfda1fSAndroid Build Coastguard Worker
169*59bfda1fSAndroid Build Coastguard Worker sum_blk = get_sum_block(sbi, segno, &type);
170*59bfda1fSAndroid Build Coastguard Worker
171*59bfda1fSAndroid Build Coastguard Worker if (type != SEG_TYPE_NODE && type != SEG_TYPE_CUR_NODE) {
172*59bfda1fSAndroid Build Coastguard Worker /* can't fix current summary, then drop the block */
173*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on || type < 0) {
174*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Summary footer is not for node segment");
175*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
176*59bfda1fSAndroid Build Coastguard Worker goto out;
177*59bfda1fSAndroid Build Coastguard Worker }
178*59bfda1fSAndroid Build Coastguard Worker
179*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
180*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, segno);
181*59bfda1fSAndroid Build Coastguard Worker if(IS_NODESEG(se->type)) {
182*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Summary footer indicates a node segment: 0x%x", segno);
183*59bfda1fSAndroid Build Coastguard Worker F2FS_SUMMARY_BLOCK_FOOTER(sum_blk)->entry_type = SUM_TYPE_NODE;
184*59bfda1fSAndroid Build Coastguard Worker } else {
185*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
186*59bfda1fSAndroid Build Coastguard Worker goto out;
187*59bfda1fSAndroid Build Coastguard Worker }
188*59bfda1fSAndroid Build Coastguard Worker }
189*59bfda1fSAndroid Build Coastguard Worker
190*59bfda1fSAndroid Build Coastguard Worker sum_entry = &(sum_blk->entries[offset]);
191*59bfda1fSAndroid Build Coastguard Worker
192*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(sum_entry->nid) != nid) {
193*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on || type < 0) {
194*59bfda1fSAndroid Build Coastguard Worker DBG(0, "nid [0x%x]\n", nid);
195*59bfda1fSAndroid Build Coastguard Worker DBG(0, "target blk_addr [0x%x]\n", blk_addr);
196*59bfda1fSAndroid Build Coastguard Worker DBG(0, "summary blk_addr [0x%x]\n",
197*59bfda1fSAndroid Build Coastguard Worker GET_SUM_BLKADDR(sbi,
198*59bfda1fSAndroid Build Coastguard Worker GET_SEGNO(sbi, blk_addr)));
199*59bfda1fSAndroid Build Coastguard Worker DBG(0, "seg no / offset [0x%x / 0x%x]\n",
200*59bfda1fSAndroid Build Coastguard Worker GET_SEGNO(sbi, blk_addr),
201*59bfda1fSAndroid Build Coastguard Worker OFFSET_IN_SEG(sbi, blk_addr));
202*59bfda1fSAndroid Build Coastguard Worker DBG(0, "summary_entry.nid [0x%x]\n",
203*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(sum_entry->nid));
204*59bfda1fSAndroid Build Coastguard Worker DBG(0, "--> node block's nid [0x%x]\n", nid);
205*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Invalid node seg summary\n");
206*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
207*59bfda1fSAndroid Build Coastguard Worker } else {
208*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Set node summary 0x%x -> [0x%x] [0x%x]",
209*59bfda1fSAndroid Build Coastguard Worker segno, nid, blk_addr);
210*59bfda1fSAndroid Build Coastguard Worker sum_entry->nid = cpu_to_le32(nid);
211*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
212*59bfda1fSAndroid Build Coastguard Worker }
213*59bfda1fSAndroid Build Coastguard Worker }
214*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable()) {
215*59bfda1fSAndroid Build Coastguard Worker u64 ssa_blk;
216*59bfda1fSAndroid Build Coastguard Worker int ret2;
217*59bfda1fSAndroid Build Coastguard Worker
218*59bfda1fSAndroid Build Coastguard Worker ssa_blk = GET_SUM_BLKADDR(sbi, segno);
219*59bfda1fSAndroid Build Coastguard Worker ret2 = dev_write_block(sum_blk, ssa_blk, WRITE_LIFE_NONE);
220*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret2 >= 0);
221*59bfda1fSAndroid Build Coastguard Worker }
222*59bfda1fSAndroid Build Coastguard Worker out:
223*59bfda1fSAndroid Build Coastguard Worker if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
224*59bfda1fSAndroid Build Coastguard Worker type == SEG_TYPE_MAX)
225*59bfda1fSAndroid Build Coastguard Worker free(sum_blk);
226*59bfda1fSAndroid Build Coastguard Worker return ret;
227*59bfda1fSAndroid Build Coastguard Worker }
228*59bfda1fSAndroid Build Coastguard Worker
is_valid_summary(struct f2fs_sb_info * sbi,struct f2fs_summary * sum,u32 blk_addr)229*59bfda1fSAndroid Build Coastguard Worker static int is_valid_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
230*59bfda1fSAndroid Build Coastguard Worker u32 blk_addr)
231*59bfda1fSAndroid Build Coastguard Worker {
232*59bfda1fSAndroid Build Coastguard Worker u16 ofs_in_node = le16_to_cpu(sum->ofs_in_node);
233*59bfda1fSAndroid Build Coastguard Worker u32 nid = le32_to_cpu(sum->nid);
234*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk = NULL;
235*59bfda1fSAndroid Build Coastguard Worker __le32 target_blk_addr;
236*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
237*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
238*59bfda1fSAndroid Build Coastguard Worker
239*59bfda1fSAndroid Build Coastguard Worker node_blk = (struct f2fs_node *)calloc(F2FS_BLKSIZE, 1);
240*59bfda1fSAndroid Build Coastguard Worker ASSERT(node_blk != NULL);
241*59bfda1fSAndroid Build Coastguard Worker
242*59bfda1fSAndroid Build Coastguard Worker if (!IS_VALID_NID(sbi, nid))
243*59bfda1fSAndroid Build Coastguard Worker goto out;
244*59bfda1fSAndroid Build Coastguard Worker
245*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
246*59bfda1fSAndroid Build Coastguard Worker
247*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC))
248*59bfda1fSAndroid Build Coastguard Worker goto out;
249*59bfda1fSAndroid Build Coastguard Worker
250*59bfda1fSAndroid Build Coastguard Worker /* read node_block */
251*59bfda1fSAndroid Build Coastguard Worker ret = dev_read_block(node_blk, ni.blk_addr);
252*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
253*59bfda1fSAndroid Build Coastguard Worker
254*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid) != nid)
255*59bfda1fSAndroid Build Coastguard Worker goto out;
256*59bfda1fSAndroid Build Coastguard Worker
257*59bfda1fSAndroid Build Coastguard Worker /* check its block address */
258*59bfda1fSAndroid Build Coastguard Worker if (IS_INODE(node_blk)) {
259*59bfda1fSAndroid Build Coastguard Worker int ofs = get_extra_isize(node_blk);
260*59bfda1fSAndroid Build Coastguard Worker
261*59bfda1fSAndroid Build Coastguard Worker if (ofs + ofs_in_node >= DEF_ADDRS_PER_INODE)
262*59bfda1fSAndroid Build Coastguard Worker goto out;
263*59bfda1fSAndroid Build Coastguard Worker target_blk_addr = node_blk->i.i_addr[ofs + ofs_in_node];
264*59bfda1fSAndroid Build Coastguard Worker } else {
265*59bfda1fSAndroid Build Coastguard Worker if (ofs_in_node >= DEF_ADDRS_PER_BLOCK)
266*59bfda1fSAndroid Build Coastguard Worker goto out;
267*59bfda1fSAndroid Build Coastguard Worker target_blk_addr = node_blk->dn.addr[ofs_in_node];
268*59bfda1fSAndroid Build Coastguard Worker }
269*59bfda1fSAndroid Build Coastguard Worker
270*59bfda1fSAndroid Build Coastguard Worker if (blk_addr == le32_to_cpu(target_blk_addr))
271*59bfda1fSAndroid Build Coastguard Worker ret = 1;
272*59bfda1fSAndroid Build Coastguard Worker out:
273*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
274*59bfda1fSAndroid Build Coastguard Worker return ret;
275*59bfda1fSAndroid Build Coastguard Worker }
276*59bfda1fSAndroid Build Coastguard Worker
is_valid_ssa_data_blk(struct f2fs_sb_info * sbi,u32 blk_addr,u32 parent_nid,u16 idx_in_node,u8 version)277*59bfda1fSAndroid Build Coastguard Worker static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
278*59bfda1fSAndroid Build Coastguard Worker u32 parent_nid, u16 idx_in_node, u8 version)
279*59bfda1fSAndroid Build Coastguard Worker {
280*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
281*59bfda1fSAndroid Build Coastguard Worker struct f2fs_summary_block *sum_blk;
282*59bfda1fSAndroid Build Coastguard Worker struct f2fs_summary *sum_entry;
283*59bfda1fSAndroid Build Coastguard Worker struct seg_entry * se;
284*59bfda1fSAndroid Build Coastguard Worker u32 segno, offset;
285*59bfda1fSAndroid Build Coastguard Worker int need_fix = 0, ret = 0;
286*59bfda1fSAndroid Build Coastguard Worker int type;
287*59bfda1fSAndroid Build Coastguard Worker
288*59bfda1fSAndroid Build Coastguard Worker if (get_sb(feature) & F2FS_FEATURE_RO)
289*59bfda1fSAndroid Build Coastguard Worker return 0;
290*59bfda1fSAndroid Build Coastguard Worker
291*59bfda1fSAndroid Build Coastguard Worker segno = GET_SEGNO(sbi, blk_addr);
292*59bfda1fSAndroid Build Coastguard Worker offset = OFFSET_IN_SEG(sbi, blk_addr);
293*59bfda1fSAndroid Build Coastguard Worker
294*59bfda1fSAndroid Build Coastguard Worker sum_blk = get_sum_block(sbi, segno, &type);
295*59bfda1fSAndroid Build Coastguard Worker
296*59bfda1fSAndroid Build Coastguard Worker if (type != SEG_TYPE_DATA && type != SEG_TYPE_CUR_DATA) {
297*59bfda1fSAndroid Build Coastguard Worker /* can't fix current summary, then drop the block */
298*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on || type < 0) {
299*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Summary footer is not for data segment");
300*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
301*59bfda1fSAndroid Build Coastguard Worker goto out;
302*59bfda1fSAndroid Build Coastguard Worker }
303*59bfda1fSAndroid Build Coastguard Worker
304*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
305*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, segno);
306*59bfda1fSAndroid Build Coastguard Worker if (IS_DATASEG(se->type)) {
307*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Summary footer indicates a data segment: 0x%x", segno);
308*59bfda1fSAndroid Build Coastguard Worker F2FS_SUMMARY_BLOCK_FOOTER(sum_blk)->entry_type = SUM_TYPE_DATA;
309*59bfda1fSAndroid Build Coastguard Worker } else {
310*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
311*59bfda1fSAndroid Build Coastguard Worker goto out;
312*59bfda1fSAndroid Build Coastguard Worker }
313*59bfda1fSAndroid Build Coastguard Worker }
314*59bfda1fSAndroid Build Coastguard Worker
315*59bfda1fSAndroid Build Coastguard Worker sum_entry = &(sum_blk->entries[offset]);
316*59bfda1fSAndroid Build Coastguard Worker
317*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(sum_entry->nid) != parent_nid ||
318*59bfda1fSAndroid Build Coastguard Worker sum_entry->version != version ||
319*59bfda1fSAndroid Build Coastguard Worker le16_to_cpu(sum_entry->ofs_in_node) != idx_in_node) {
320*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on || type < 0) {
321*59bfda1fSAndroid Build Coastguard Worker DBG(0, "summary_entry.nid [0x%x]\n",
322*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(sum_entry->nid));
323*59bfda1fSAndroid Build Coastguard Worker DBG(0, "summary_entry.version [0x%x]\n",
324*59bfda1fSAndroid Build Coastguard Worker sum_entry->version);
325*59bfda1fSAndroid Build Coastguard Worker DBG(0, "summary_entry.ofs_in_node [0x%x]\n",
326*59bfda1fSAndroid Build Coastguard Worker le16_to_cpu(sum_entry->ofs_in_node));
327*59bfda1fSAndroid Build Coastguard Worker DBG(0, "parent nid [0x%x]\n",
328*59bfda1fSAndroid Build Coastguard Worker parent_nid);
329*59bfda1fSAndroid Build Coastguard Worker DBG(0, "version from nat [0x%x]\n", version);
330*59bfda1fSAndroid Build Coastguard Worker DBG(0, "idx in parent node [0x%x]\n",
331*59bfda1fSAndroid Build Coastguard Worker idx_in_node);
332*59bfda1fSAndroid Build Coastguard Worker
333*59bfda1fSAndroid Build Coastguard Worker DBG(0, "Target data block addr [0x%x]\n", blk_addr);
334*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Invalid data seg summary\n");
335*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
336*59bfda1fSAndroid Build Coastguard Worker } else if (is_valid_summary(sbi, sum_entry, blk_addr)) {
337*59bfda1fSAndroid Build Coastguard Worker /* delete wrong index */
338*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
339*59bfda1fSAndroid Build Coastguard Worker } else {
340*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Set data summary 0x%x -> [0x%x] [0x%x] [0x%x]",
341*59bfda1fSAndroid Build Coastguard Worker segno, parent_nid, version, idx_in_node);
342*59bfda1fSAndroid Build Coastguard Worker sum_entry->nid = cpu_to_le32(parent_nid);
343*59bfda1fSAndroid Build Coastguard Worker sum_entry->version = version;
344*59bfda1fSAndroid Build Coastguard Worker sum_entry->ofs_in_node = cpu_to_le16(idx_in_node);
345*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
346*59bfda1fSAndroid Build Coastguard Worker }
347*59bfda1fSAndroid Build Coastguard Worker }
348*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable()) {
349*59bfda1fSAndroid Build Coastguard Worker u64 ssa_blk;
350*59bfda1fSAndroid Build Coastguard Worker int ret2;
351*59bfda1fSAndroid Build Coastguard Worker
352*59bfda1fSAndroid Build Coastguard Worker ssa_blk = GET_SUM_BLKADDR(sbi, segno);
353*59bfda1fSAndroid Build Coastguard Worker ret2 = dev_write_block(sum_blk, ssa_blk, WRITE_LIFE_NONE);
354*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret2 >= 0);
355*59bfda1fSAndroid Build Coastguard Worker }
356*59bfda1fSAndroid Build Coastguard Worker out:
357*59bfda1fSAndroid Build Coastguard Worker if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
358*59bfda1fSAndroid Build Coastguard Worker type == SEG_TYPE_MAX)
359*59bfda1fSAndroid Build Coastguard Worker free(sum_blk);
360*59bfda1fSAndroid Build Coastguard Worker return ret;
361*59bfda1fSAndroid Build Coastguard Worker }
362*59bfda1fSAndroid Build Coastguard Worker
__check_inode_mode(u32 nid,enum FILE_TYPE ftype,u16 mode)363*59bfda1fSAndroid Build Coastguard Worker static int __check_inode_mode(u32 nid, enum FILE_TYPE ftype, u16 mode)
364*59bfda1fSAndroid Build Coastguard Worker {
365*59bfda1fSAndroid Build Coastguard Worker if (ftype >= F2FS_FT_MAX)
366*59bfda1fSAndroid Build Coastguard Worker return 0;
367*59bfda1fSAndroid Build Coastguard Worker /* f2fs_iget will return -EIO if mode is not valid file type */
368*59bfda1fSAndroid Build Coastguard Worker if (!S_ISLNK(mode) && !S_ISREG(mode) && !S_ISDIR(mode) &&
369*59bfda1fSAndroid Build Coastguard Worker !S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode) &&
370*59bfda1fSAndroid Build Coastguard Worker !S_ISSOCK(mode)) {
371*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("inode [0x%x] unknown file type i_mode [0x%x]",
372*59bfda1fSAndroid Build Coastguard Worker nid, mode);
373*59bfda1fSAndroid Build Coastguard Worker return -1;
374*59bfda1fSAndroid Build Coastguard Worker }
375*59bfda1fSAndroid Build Coastguard Worker
376*59bfda1fSAndroid Build Coastguard Worker if (S_ISLNK(mode) && ftype != F2FS_FT_SYMLINK)
377*59bfda1fSAndroid Build Coastguard Worker goto err;
378*59bfda1fSAndroid Build Coastguard Worker if (S_ISREG(mode) && ftype != F2FS_FT_REG_FILE)
379*59bfda1fSAndroid Build Coastguard Worker goto err;
380*59bfda1fSAndroid Build Coastguard Worker if (S_ISDIR(mode) && ftype != F2FS_FT_DIR)
381*59bfda1fSAndroid Build Coastguard Worker goto err;
382*59bfda1fSAndroid Build Coastguard Worker if (S_ISCHR(mode) && ftype != F2FS_FT_CHRDEV)
383*59bfda1fSAndroid Build Coastguard Worker goto err;
384*59bfda1fSAndroid Build Coastguard Worker if (S_ISBLK(mode) && ftype != F2FS_FT_BLKDEV)
385*59bfda1fSAndroid Build Coastguard Worker goto err;
386*59bfda1fSAndroid Build Coastguard Worker if (S_ISFIFO(mode) && ftype != F2FS_FT_FIFO)
387*59bfda1fSAndroid Build Coastguard Worker goto err;
388*59bfda1fSAndroid Build Coastguard Worker if (S_ISSOCK(mode) && ftype != F2FS_FT_SOCK)
389*59bfda1fSAndroid Build Coastguard Worker goto err;
390*59bfda1fSAndroid Build Coastguard Worker return 0;
391*59bfda1fSAndroid Build Coastguard Worker err:
392*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("inode [0x%x] mismatch i_mode [0x%x vs. 0x%x]",
393*59bfda1fSAndroid Build Coastguard Worker nid, ftype, mode);
394*59bfda1fSAndroid Build Coastguard Worker return -1;
395*59bfda1fSAndroid Build Coastguard Worker }
396*59bfda1fSAndroid Build Coastguard Worker
sanity_check_nat(struct f2fs_sb_info * sbi,u32 nid,struct node_info * ni)397*59bfda1fSAndroid Build Coastguard Worker static int sanity_check_nat(struct f2fs_sb_info *sbi, u32 nid,
398*59bfda1fSAndroid Build Coastguard Worker struct node_info *ni)
399*59bfda1fSAndroid Build Coastguard Worker {
400*59bfda1fSAndroid Build Coastguard Worker if (!IS_VALID_NID(sbi, nid)) {
401*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid is not valid. [0x%x]", nid);
402*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
403*59bfda1fSAndroid Build Coastguard Worker }
404*59bfda1fSAndroid Build Coastguard Worker
405*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, ni);
406*59bfda1fSAndroid Build Coastguard Worker if (ni->ino == 0) {
407*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid[0x%x] ino is 0", nid);
408*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
409*59bfda1fSAndroid Build Coastguard Worker }
410*59bfda1fSAndroid Build Coastguard Worker
411*59bfda1fSAndroid Build Coastguard Worker if (!is_valid_data_blkaddr(ni->blk_addr)) {
412*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid->blk_addr is 0x%x. [0x%x]", ni->blk_addr, nid);
413*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
414*59bfda1fSAndroid Build Coastguard Worker }
415*59bfda1fSAndroid Build Coastguard Worker
416*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_is_valid_blkaddr(sbi, ni->blk_addr, DATA_GENERIC)) {
417*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("blkaddress is not valid. [0x%x]", ni->blk_addr);
418*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
419*59bfda1fSAndroid Build Coastguard Worker }
420*59bfda1fSAndroid Build Coastguard Worker
421*59bfda1fSAndroid Build Coastguard Worker return 0;
422*59bfda1fSAndroid Build Coastguard Worker }
423*59bfda1fSAndroid Build Coastguard Worker
fsck_sanity_check_nat(struct f2fs_sb_info * sbi,u32 nid)424*59bfda1fSAndroid Build Coastguard Worker int fsck_sanity_check_nat(struct f2fs_sb_info *sbi, u32 nid)
425*59bfda1fSAndroid Build Coastguard Worker {
426*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
427*59bfda1fSAndroid Build Coastguard Worker
428*59bfda1fSAndroid Build Coastguard Worker return sanity_check_nat(sbi, nid, &ni);
429*59bfda1fSAndroid Build Coastguard Worker }
430*59bfda1fSAndroid Build Coastguard Worker
sanity_check_nid(struct f2fs_sb_info * sbi,u32 nid,struct f2fs_node * node_blk,enum FILE_TYPE ftype,enum NODE_TYPE ntype,struct node_info * ni)431*59bfda1fSAndroid Build Coastguard Worker static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
432*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk,
433*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype, enum NODE_TYPE ntype,
434*59bfda1fSAndroid Build Coastguard Worker struct node_info *ni)
435*59bfda1fSAndroid Build Coastguard Worker {
436*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
437*59bfda1fSAndroid Build Coastguard Worker int ret;
438*59bfda1fSAndroid Build Coastguard Worker
439*59bfda1fSAndroid Build Coastguard Worker ret = sanity_check_nat(sbi, nid, ni);
440*59bfda1fSAndroid Build Coastguard Worker if (ret)
441*59bfda1fSAndroid Build Coastguard Worker return ret;
442*59bfda1fSAndroid Build Coastguard Worker
443*59bfda1fSAndroid Build Coastguard Worker ret = dev_read_block(node_blk, ni->blk_addr);
444*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
445*59bfda1fSAndroid Build Coastguard Worker
446*59bfda1fSAndroid Build Coastguard Worker if (ntype == TYPE_INODE &&
447*59bfda1fSAndroid Build Coastguard Worker F2FS_NODE_FOOTER(node_blk)->nid != F2FS_NODE_FOOTER(node_blk)->ino) {
448*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid[0x%x] footer.nid[0x%x] footer.ino[0x%x]",
449*59bfda1fSAndroid Build Coastguard Worker nid, le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid),
450*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino));
451*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
452*59bfda1fSAndroid Build Coastguard Worker }
453*59bfda1fSAndroid Build Coastguard Worker if (ni->ino != le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino)) {
454*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid[0x%x] nat_entry->ino[0x%x] footer.ino[0x%x]",
455*59bfda1fSAndroid Build Coastguard Worker nid, ni->ino, le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino));
456*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
457*59bfda1fSAndroid Build Coastguard Worker }
458*59bfda1fSAndroid Build Coastguard Worker if (ntype != TYPE_INODE && IS_INODE(node_blk)) {
459*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid[0x%x] footer.nid[0x%x] footer.ino[0x%x]",
460*59bfda1fSAndroid Build Coastguard Worker nid, le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid),
461*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino));
462*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
463*59bfda1fSAndroid Build Coastguard Worker }
464*59bfda1fSAndroid Build Coastguard Worker
465*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid) != nid) {
466*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]",
467*59bfda1fSAndroid Build Coastguard Worker nid, ni->blk_addr,
468*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid));
469*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
470*59bfda1fSAndroid Build Coastguard Worker }
471*59bfda1fSAndroid Build Coastguard Worker
472*59bfda1fSAndroid Build Coastguard Worker if (ntype == TYPE_XATTR) {
473*59bfda1fSAndroid Build Coastguard Worker u32 flag = le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->flag);
474*59bfda1fSAndroid Build Coastguard Worker
475*59bfda1fSAndroid Build Coastguard Worker if ((flag >> OFFSET_BIT_SHIFT) != XATTR_NODE_OFFSET) {
476*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("xnid[0x%x] has wrong ofs:[0x%x]",
477*59bfda1fSAndroid Build Coastguard Worker nid, flag);
478*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
479*59bfda1fSAndroid Build Coastguard Worker }
480*59bfda1fSAndroid Build Coastguard Worker }
481*59bfda1fSAndroid Build Coastguard Worker
482*59bfda1fSAndroid Build Coastguard Worker if ((ntype == TYPE_INODE && ftype == F2FS_FT_DIR) ||
483*59bfda1fSAndroid Build Coastguard Worker (ntype == TYPE_XATTR && ftype == F2FS_FT_XATTR)) {
484*59bfda1fSAndroid Build Coastguard Worker /* not included '.' & '..' */
485*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_main_bitmap(sbi, ni->blk_addr) != 0) {
486*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Duplicated node blk. nid[0x%x][0x%x]\n",
487*59bfda1fSAndroid Build Coastguard Worker nid, ni->blk_addr);
488*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
489*59bfda1fSAndroid Build Coastguard Worker }
490*59bfda1fSAndroid Build Coastguard Worker }
491*59bfda1fSAndroid Build Coastguard Worker
492*59bfda1fSAndroid Build Coastguard Worker /* this if only from fix_hard_links */
493*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_MAX)
494*59bfda1fSAndroid Build Coastguard Worker return 0;
495*59bfda1fSAndroid Build Coastguard Worker
496*59bfda1fSAndroid Build Coastguard Worker if (ntype == TYPE_INODE &&
497*59bfda1fSAndroid Build Coastguard Worker __check_inode_mode(nid, ftype, le16_to_cpu(node_blk->i.i_mode)))
498*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
499*59bfda1fSAndroid Build Coastguard Worker
500*59bfda1fSAndroid Build Coastguard Worker /* workaround to fix later */
501*59bfda1fSAndroid Build Coastguard Worker if (ftype != F2FS_FT_ORPHAN ||
502*59bfda1fSAndroid Build Coastguard Worker f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) {
503*59bfda1fSAndroid Build Coastguard Worker f2fs_clear_bit(nid, fsck->nat_area_bitmap);
504*59bfda1fSAndroid Build Coastguard Worker /* avoid reusing nid when reconnecting files */
505*59bfda1fSAndroid Build Coastguard Worker f2fs_set_bit(nid, NM_I(sbi)->nid_bitmap);
506*59bfda1fSAndroid Build Coastguard Worker } else
507*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n",
508*59bfda1fSAndroid Build Coastguard Worker nid);
509*59bfda1fSAndroid Build Coastguard Worker
510*59bfda1fSAndroid Build Coastguard Worker if (is_valid_ssa_node_blk(sbi, nid, ni->blk_addr)) {
511*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("summary node block is not valid. [0x%x]", nid);
512*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
513*59bfda1fSAndroid Build Coastguard Worker }
514*59bfda1fSAndroid Build Coastguard Worker
515*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_sit_bitmap(sbi, ni->blk_addr) == 0)
516*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]",
517*59bfda1fSAndroid Build Coastguard Worker ni->blk_addr);
518*59bfda1fSAndroid Build Coastguard Worker
519*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
520*59bfda1fSAndroid Build Coastguard Worker
521*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_blk_cnt++;
522*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_node_cnt++;
523*59bfda1fSAndroid Build Coastguard Worker
524*59bfda1fSAndroid Build Coastguard Worker /* Progress report */
525*59bfda1fSAndroid Build Coastguard Worker if (!c.show_file_map && sbi->total_valid_node_count > 1000) {
526*59bfda1fSAndroid Build Coastguard Worker unsigned int p10 = sbi->total_valid_node_count / 10;
527*59bfda1fSAndroid Build Coastguard Worker
528*59bfda1fSAndroid Build Coastguard Worker if (++sbi->fsck->chk.checked_node_cnt % p10)
529*59bfda1fSAndroid Build Coastguard Worker return 0;
530*59bfda1fSAndroid Build Coastguard Worker
531*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Check node %"PRIu64" / %u (%.2f%%)\n",
532*59bfda1fSAndroid Build Coastguard Worker sbi->fsck->chk.checked_node_cnt,
533*59bfda1fSAndroid Build Coastguard Worker sbi->total_valid_node_count,
534*59bfda1fSAndroid Build Coastguard Worker 10 * (float)sbi->fsck->chk.checked_node_cnt /
535*59bfda1fSAndroid Build Coastguard Worker p10);
536*59bfda1fSAndroid Build Coastguard Worker }
537*59bfda1fSAndroid Build Coastguard Worker }
538*59bfda1fSAndroid Build Coastguard Worker return 0;
539*59bfda1fSAndroid Build Coastguard Worker }
540*59bfda1fSAndroid Build Coastguard Worker
fsck_sanity_check_nid(struct f2fs_sb_info * sbi,u32 nid,enum FILE_TYPE ftype,enum NODE_TYPE ntype)541*59bfda1fSAndroid Build Coastguard Worker int fsck_sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
542*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype, enum NODE_TYPE ntype)
543*59bfda1fSAndroid Build Coastguard Worker {
544*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk = NULL;
545*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
546*59bfda1fSAndroid Build Coastguard Worker int ret;
547*59bfda1fSAndroid Build Coastguard Worker
548*59bfda1fSAndroid Build Coastguard Worker node_blk = (struct f2fs_node *)calloc(F2FS_BLKSIZE, 1);
549*59bfda1fSAndroid Build Coastguard Worker ASSERT(node_blk != NULL);
550*59bfda1fSAndroid Build Coastguard Worker
551*59bfda1fSAndroid Build Coastguard Worker ret = sanity_check_nid(sbi, nid, node_blk, ftype, ntype, &ni);
552*59bfda1fSAndroid Build Coastguard Worker
553*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
554*59bfda1fSAndroid Build Coastguard Worker return ret;
555*59bfda1fSAndroid Build Coastguard Worker }
556*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_xattr_blk(struct f2fs_sb_info * sbi,u32 ino,u32 x_nid,u32 * blk_cnt)557*59bfda1fSAndroid Build Coastguard Worker static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino,
558*59bfda1fSAndroid Build Coastguard Worker u32 x_nid, u32 *blk_cnt)
559*59bfda1fSAndroid Build Coastguard Worker {
560*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk = NULL;
561*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
562*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
563*59bfda1fSAndroid Build Coastguard Worker
564*59bfda1fSAndroid Build Coastguard Worker if (x_nid == 0x0)
565*59bfda1fSAndroid Build Coastguard Worker return 0;
566*59bfda1fSAndroid Build Coastguard Worker
567*59bfda1fSAndroid Build Coastguard Worker node_blk = (struct f2fs_node *)calloc(F2FS_BLKSIZE, 1);
568*59bfda1fSAndroid Build Coastguard Worker ASSERT(node_blk != NULL);
569*59bfda1fSAndroid Build Coastguard Worker
570*59bfda1fSAndroid Build Coastguard Worker /* Sanity check */
571*59bfda1fSAndroid Build Coastguard Worker if (sanity_check_nid(sbi, x_nid, node_blk,
572*59bfda1fSAndroid Build Coastguard Worker F2FS_FT_XATTR, TYPE_XATTR, &ni)) {
573*59bfda1fSAndroid Build Coastguard Worker ret = -EINVAL;
574*59bfda1fSAndroid Build Coastguard Worker goto out;
575*59bfda1fSAndroid Build Coastguard Worker }
576*59bfda1fSAndroid Build Coastguard Worker
577*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
578*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, ni.blk_addr, CURSEG_COLD_NODE);
579*59bfda1fSAndroid Build Coastguard Worker DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid);
580*59bfda1fSAndroid Build Coastguard Worker out:
581*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
582*59bfda1fSAndroid Build Coastguard Worker return ret;
583*59bfda1fSAndroid Build Coastguard Worker }
584*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_node_blk(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,u32 nid,enum FILE_TYPE ftype,enum NODE_TYPE ntype,u32 * blk_cnt,struct f2fs_compr_blk_cnt * cbc,struct child_info * child)585*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
586*59bfda1fSAndroid Build Coastguard Worker u32 nid, enum FILE_TYPE ftype, enum NODE_TYPE ntype,
587*59bfda1fSAndroid Build Coastguard Worker u32 *blk_cnt, struct f2fs_compr_blk_cnt *cbc,
588*59bfda1fSAndroid Build Coastguard Worker struct child_info *child)
589*59bfda1fSAndroid Build Coastguard Worker {
590*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
591*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk = NULL;
592*59bfda1fSAndroid Build Coastguard Worker
593*59bfda1fSAndroid Build Coastguard Worker node_blk = (struct f2fs_node *)calloc(F2FS_BLKSIZE, 1);
594*59bfda1fSAndroid Build Coastguard Worker ASSERT(node_blk != NULL);
595*59bfda1fSAndroid Build Coastguard Worker
596*59bfda1fSAndroid Build Coastguard Worker if (sanity_check_nid(sbi, nid, node_blk, ftype, ntype, &ni))
597*59bfda1fSAndroid Build Coastguard Worker goto err;
598*59bfda1fSAndroid Build Coastguard Worker
599*59bfda1fSAndroid Build Coastguard Worker if (ntype == TYPE_INODE) {
600*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
601*59bfda1fSAndroid Build Coastguard Worker
602*59bfda1fSAndroid Build Coastguard Worker fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, cbc,
603*59bfda1fSAndroid Build Coastguard Worker &ni, child);
604*59bfda1fSAndroid Build Coastguard Worker quota_add_inode_usage(fsck->qctx, nid, &node_blk->i);
605*59bfda1fSAndroid Build Coastguard Worker } else {
606*59bfda1fSAndroid Build Coastguard Worker switch (ntype) {
607*59bfda1fSAndroid Build Coastguard Worker case TYPE_DIRECT_NODE:
608*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, ni.blk_addr,
609*59bfda1fSAndroid Build Coastguard Worker CURSEG_WARM_NODE);
610*59bfda1fSAndroid Build Coastguard Worker fsck_chk_dnode_blk(sbi, inode, nid, ftype, node_blk,
611*59bfda1fSAndroid Build Coastguard Worker blk_cnt, cbc, child, &ni);
612*59bfda1fSAndroid Build Coastguard Worker break;
613*59bfda1fSAndroid Build Coastguard Worker case TYPE_INDIRECT_NODE:
614*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, ni.blk_addr,
615*59bfda1fSAndroid Build Coastguard Worker CURSEG_COLD_NODE);
616*59bfda1fSAndroid Build Coastguard Worker fsck_chk_idnode_blk(sbi, inode, ftype, node_blk,
617*59bfda1fSAndroid Build Coastguard Worker blk_cnt, cbc, child);
618*59bfda1fSAndroid Build Coastguard Worker break;
619*59bfda1fSAndroid Build Coastguard Worker case TYPE_DOUBLE_INDIRECT_NODE:
620*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, ni.blk_addr,
621*59bfda1fSAndroid Build Coastguard Worker CURSEG_COLD_NODE);
622*59bfda1fSAndroid Build Coastguard Worker fsck_chk_didnode_blk(sbi, inode, ftype, node_blk,
623*59bfda1fSAndroid Build Coastguard Worker blk_cnt, cbc, child);
624*59bfda1fSAndroid Build Coastguard Worker break;
625*59bfda1fSAndroid Build Coastguard Worker default:
626*59bfda1fSAndroid Build Coastguard Worker ASSERT(0);
627*59bfda1fSAndroid Build Coastguard Worker }
628*59bfda1fSAndroid Build Coastguard Worker }
629*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
630*59bfda1fSAndroid Build Coastguard Worker return 0;
631*59bfda1fSAndroid Build Coastguard Worker err:
632*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
633*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
634*59bfda1fSAndroid Build Coastguard Worker }
635*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_root_inode(struct f2fs_sb_info * sbi)636*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_root_inode(struct f2fs_sb_info *sbi)
637*59bfda1fSAndroid Build Coastguard Worker {
638*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk;
639*59bfda1fSAndroid Build Coastguard Worker int segment_count = SM_I(sbi)->main_segments;
640*59bfda1fSAndroid Build Coastguard Worker int segno;
641*59bfda1fSAndroid Build Coastguard Worker bool valid_bitmap = true;
642*59bfda1fSAndroid Build Coastguard Worker block_t last_blkaddr = NULL_ADDR;
643*59bfda1fSAndroid Build Coastguard Worker nid_t root_ino = sbi->root_ino_num;
644*59bfda1fSAndroid Build Coastguard Worker u64 last_ctime = 0;
645*59bfda1fSAndroid Build Coastguard Worker u32 last_ctime_nsec = 0;
646*59bfda1fSAndroid Build Coastguard Worker int ret = -EINVAL;
647*59bfda1fSAndroid Build Coastguard Worker
648*59bfda1fSAndroid Build Coastguard Worker node_blk = calloc(F2FS_BLKSIZE, 1);
649*59bfda1fSAndroid Build Coastguard Worker ASSERT(node_blk);
650*59bfda1fSAndroid Build Coastguard Worker
651*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: root inode is corrupted, search and relink it\n");
652*59bfda1fSAndroid Build Coastguard Worker
653*59bfda1fSAndroid Build Coastguard Worker retry:
654*59bfda1fSAndroid Build Coastguard Worker for (segno = 0; segno < segment_count; segno++) {
655*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se = get_seg_entry(sbi, segno);
656*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr = START_BLOCK(sbi, segno);
657*59bfda1fSAndroid Build Coastguard Worker int ret;
658*59bfda1fSAndroid Build Coastguard Worker int i;
659*59bfda1fSAndroid Build Coastguard Worker
660*59bfda1fSAndroid Build Coastguard Worker if (IS_DATASEG(se->type))
661*59bfda1fSAndroid Build Coastguard Worker continue;
662*59bfda1fSAndroid Build Coastguard Worker
663*59bfda1fSAndroid Build Coastguard Worker dev_readahead(blkaddr << F2FS_BLKSIZE_BITS,
664*59bfda1fSAndroid Build Coastguard Worker sbi->blocks_per_seg << F2FS_BLKSIZE_BITS);
665*59bfda1fSAndroid Build Coastguard Worker
666*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < sbi->blocks_per_seg; i++, blkaddr++) {
667*59bfda1fSAndroid Build Coastguard Worker if (valid_bitmap ^ is_sit_bitmap_set(sbi, blkaddr))
668*59bfda1fSAndroid Build Coastguard Worker continue;
669*59bfda1fSAndroid Build Coastguard Worker
670*59bfda1fSAndroid Build Coastguard Worker ret = dev_read_block(node_blk, blkaddr);
671*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
672*59bfda1fSAndroid Build Coastguard Worker
673*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino) !=
674*59bfda1fSAndroid Build Coastguard Worker root_ino ||
675*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid) !=
676*59bfda1fSAndroid Build Coastguard Worker root_ino)
677*59bfda1fSAndroid Build Coastguard Worker continue;
678*59bfda1fSAndroid Build Coastguard Worker
679*59bfda1fSAndroid Build Coastguard Worker if (!IS_INODE(node_blk))
680*59bfda1fSAndroid Build Coastguard Worker continue;
681*59bfda1fSAndroid Build Coastguard Worker
682*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(node_blk->i.i_generation) ||
683*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(node_blk->i.i_namelen))
684*59bfda1fSAndroid Build Coastguard Worker continue;
685*59bfda1fSAndroid Build Coastguard Worker break;
686*59bfda1fSAndroid Build Coastguard Worker }
687*59bfda1fSAndroid Build Coastguard Worker
688*59bfda1fSAndroid Build Coastguard Worker if (i == sbi->blocks_per_seg)
689*59bfda1fSAndroid Build Coastguard Worker continue;
690*59bfda1fSAndroid Build Coastguard Worker
691*59bfda1fSAndroid Build Coastguard Worker if (valid_bitmap) {
692*59bfda1fSAndroid Build Coastguard Worker last_blkaddr = blkaddr;
693*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: possible root inode blkaddr: 0x%x\n",
694*59bfda1fSAndroid Build Coastguard Worker last_blkaddr);
695*59bfda1fSAndroid Build Coastguard Worker goto fix;
696*59bfda1fSAndroid Build Coastguard Worker }
697*59bfda1fSAndroid Build Coastguard Worker
698*59bfda1fSAndroid Build Coastguard Worker if (last_blkaddr == NULL_ADDR)
699*59bfda1fSAndroid Build Coastguard Worker goto init;
700*59bfda1fSAndroid Build Coastguard Worker if (le64_to_cpu(node_blk->i.i_ctime) < last_ctime)
701*59bfda1fSAndroid Build Coastguard Worker continue;
702*59bfda1fSAndroid Build Coastguard Worker if (le64_to_cpu(node_blk->i.i_ctime) == last_ctime &&
703*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(node_blk->i.i_ctime_nsec) <=
704*59bfda1fSAndroid Build Coastguard Worker last_ctime_nsec)
705*59bfda1fSAndroid Build Coastguard Worker continue;
706*59bfda1fSAndroid Build Coastguard Worker init:
707*59bfda1fSAndroid Build Coastguard Worker last_blkaddr = blkaddr;
708*59bfda1fSAndroid Build Coastguard Worker last_ctime = le64_to_cpu(node_blk->i.i_ctime);
709*59bfda1fSAndroid Build Coastguard Worker last_ctime_nsec = le32_to_cpu(node_blk->i.i_ctime_nsec);
710*59bfda1fSAndroid Build Coastguard Worker
711*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: possible root inode blkaddr: %u\n",
712*59bfda1fSAndroid Build Coastguard Worker last_blkaddr);
713*59bfda1fSAndroid Build Coastguard Worker }
714*59bfda1fSAndroid Build Coastguard Worker
715*59bfda1fSAndroid Build Coastguard Worker if (valid_bitmap) {
716*59bfda1fSAndroid Build Coastguard Worker valid_bitmap = false;
717*59bfda1fSAndroid Build Coastguard Worker goto retry;
718*59bfda1fSAndroid Build Coastguard Worker }
719*59bfda1fSAndroid Build Coastguard Worker fix:
720*59bfda1fSAndroid Build Coastguard Worker if (!last_blkaddr) {
721*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: there is no valid root inode\n");
722*59bfda1fSAndroid Build Coastguard Worker } else if (c.fix_on) {
723*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
724*59bfda1fSAndroid Build Coastguard Worker
725*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Relink root inode, blkaddr: 0x%x", last_blkaddr);
726*59bfda1fSAndroid Build Coastguard Worker update_nat_blkaddr(sbi, root_ino, root_ino, last_blkaddr);
727*59bfda1fSAndroid Build Coastguard Worker
728*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(root_ino, fsck->nat_area_bitmap))
729*59bfda1fSAndroid Build Coastguard Worker f2fs_clear_bit(root_ino, fsck->nat_area_bitmap);
730*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_nat_entry_cnt++;
731*59bfda1fSAndroid Build Coastguard Worker
732*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_test_sit_bitmap(sbi, last_blkaddr))
733*59bfda1fSAndroid Build Coastguard Worker f2fs_set_sit_bitmap(sbi, last_blkaddr);
734*59bfda1fSAndroid Build Coastguard Worker ret = 0;
735*59bfda1fSAndroid Build Coastguard Worker }
736*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
737*59bfda1fSAndroid Build Coastguard Worker return ret;
738*59bfda1fSAndroid Build Coastguard Worker }
739*59bfda1fSAndroid Build Coastguard Worker
get_extent_info(struct extent_info * ext,struct f2fs_extent * i_ext)740*59bfda1fSAndroid Build Coastguard Worker static inline void get_extent_info(struct extent_info *ext,
741*59bfda1fSAndroid Build Coastguard Worker struct f2fs_extent *i_ext)
742*59bfda1fSAndroid Build Coastguard Worker {
743*59bfda1fSAndroid Build Coastguard Worker ext->fofs = le32_to_cpu(i_ext->fofs);
744*59bfda1fSAndroid Build Coastguard Worker ext->blk = le32_to_cpu(i_ext->blk_addr);
745*59bfda1fSAndroid Build Coastguard Worker ext->len = le32_to_cpu(i_ext->len);
746*59bfda1fSAndroid Build Coastguard Worker }
747*59bfda1fSAndroid Build Coastguard Worker
check_extent_info(struct child_info * child,block_t blkaddr,int last)748*59bfda1fSAndroid Build Coastguard Worker static void check_extent_info(struct child_info *child,
749*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr, int last)
750*59bfda1fSAndroid Build Coastguard Worker {
751*59bfda1fSAndroid Build Coastguard Worker struct extent_info *ei = &child->ei;
752*59bfda1fSAndroid Build Coastguard Worker u32 pgofs = child->pgofs;
753*59bfda1fSAndroid Build Coastguard Worker int is_hole = 0;
754*59bfda1fSAndroid Build Coastguard Worker
755*59bfda1fSAndroid Build Coastguard Worker if (!ei->len)
756*59bfda1fSAndroid Build Coastguard Worker return;
757*59bfda1fSAndroid Build Coastguard Worker
758*59bfda1fSAndroid Build Coastguard Worker if (child->state & FSCK_UNMATCHED_EXTENT)
759*59bfda1fSAndroid Build Coastguard Worker return;
760*59bfda1fSAndroid Build Coastguard Worker
761*59bfda1fSAndroid Build Coastguard Worker if ((child->state & FSCK_INLINE_INODE) && ei->len)
762*59bfda1fSAndroid Build Coastguard Worker goto unmatched;
763*59bfda1fSAndroid Build Coastguard Worker
764*59bfda1fSAndroid Build Coastguard Worker if (last) {
765*59bfda1fSAndroid Build Coastguard Worker /* hole exist in the back of extent */
766*59bfda1fSAndroid Build Coastguard Worker if (child->last_blk != ei->blk + ei->len - 1)
767*59bfda1fSAndroid Build Coastguard Worker child->state |= FSCK_UNMATCHED_EXTENT;
768*59bfda1fSAndroid Build Coastguard Worker return;
769*59bfda1fSAndroid Build Coastguard Worker }
770*59bfda1fSAndroid Build Coastguard Worker
771*59bfda1fSAndroid Build Coastguard Worker if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR)
772*59bfda1fSAndroid Build Coastguard Worker is_hole = 1;
773*59bfda1fSAndroid Build Coastguard Worker
774*59bfda1fSAndroid Build Coastguard Worker if (pgofs >= ei->fofs && pgofs < ei->fofs + ei->len) {
775*59bfda1fSAndroid Build Coastguard Worker /* unmatched blkaddr */
776*59bfda1fSAndroid Build Coastguard Worker if (is_hole || (blkaddr != pgofs - ei->fofs + ei->blk))
777*59bfda1fSAndroid Build Coastguard Worker goto unmatched;
778*59bfda1fSAndroid Build Coastguard Worker
779*59bfda1fSAndroid Build Coastguard Worker if (!child->last_blk) {
780*59bfda1fSAndroid Build Coastguard Worker /* hole exists in the front of extent */
781*59bfda1fSAndroid Build Coastguard Worker if (pgofs != ei->fofs)
782*59bfda1fSAndroid Build Coastguard Worker goto unmatched;
783*59bfda1fSAndroid Build Coastguard Worker } else if (child->last_blk + 1 != blkaddr) {
784*59bfda1fSAndroid Build Coastguard Worker /* hole exists in the middle of extent */
785*59bfda1fSAndroid Build Coastguard Worker goto unmatched;
786*59bfda1fSAndroid Build Coastguard Worker }
787*59bfda1fSAndroid Build Coastguard Worker child->last_blk = blkaddr;
788*59bfda1fSAndroid Build Coastguard Worker return;
789*59bfda1fSAndroid Build Coastguard Worker }
790*59bfda1fSAndroid Build Coastguard Worker
791*59bfda1fSAndroid Build Coastguard Worker if (is_hole)
792*59bfda1fSAndroid Build Coastguard Worker return;
793*59bfda1fSAndroid Build Coastguard Worker
794*59bfda1fSAndroid Build Coastguard Worker if (blkaddr < ei->blk || blkaddr >= ei->blk + ei->len)
795*59bfda1fSAndroid Build Coastguard Worker return;
796*59bfda1fSAndroid Build Coastguard Worker /* unmatched file offset */
797*59bfda1fSAndroid Build Coastguard Worker unmatched:
798*59bfda1fSAndroid Build Coastguard Worker child->state |= FSCK_UNMATCHED_EXTENT;
799*59bfda1fSAndroid Build Coastguard Worker }
800*59bfda1fSAndroid Build Coastguard Worker
fsck_reada_node_block(struct f2fs_sb_info * sbi,u32 nid)801*59bfda1fSAndroid Build Coastguard Worker void fsck_reada_node_block(struct f2fs_sb_info *sbi, u32 nid)
802*59bfda1fSAndroid Build Coastguard Worker {
803*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
804*59bfda1fSAndroid Build Coastguard Worker
805*59bfda1fSAndroid Build Coastguard Worker if (nid != 0 && IS_VALID_NID(sbi, nid)) {
806*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
807*59bfda1fSAndroid Build Coastguard Worker if (f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC))
808*59bfda1fSAndroid Build Coastguard Worker dev_reada_block(ni.blk_addr);
809*59bfda1fSAndroid Build Coastguard Worker }
810*59bfda1fSAndroid Build Coastguard Worker }
811*59bfda1fSAndroid Build Coastguard Worker
fsck_reada_all_direct_node_blocks(struct f2fs_sb_info * sbi,struct f2fs_node * node_blk)812*59bfda1fSAndroid Build Coastguard Worker void fsck_reada_all_direct_node_blocks(struct f2fs_sb_info *sbi,
813*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk)
814*59bfda1fSAndroid Build Coastguard Worker {
815*59bfda1fSAndroid Build Coastguard Worker int i;
816*59bfda1fSAndroid Build Coastguard Worker
817*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NIDS_PER_BLOCK; i++) {
818*59bfda1fSAndroid Build Coastguard Worker u32 nid = le32_to_cpu(node_blk->in.nid[i]);
819*59bfda1fSAndroid Build Coastguard Worker
820*59bfda1fSAndroid Build Coastguard Worker fsck_reada_node_block(sbi, nid);
821*59bfda1fSAndroid Build Coastguard Worker }
822*59bfda1fSAndroid Build Coastguard Worker }
823*59bfda1fSAndroid Build Coastguard Worker
is_zeroed(const u8 * p,size_t size)824*59bfda1fSAndroid Build Coastguard Worker static bool is_zeroed(const u8 *p, size_t size)
825*59bfda1fSAndroid Build Coastguard Worker {
826*59bfda1fSAndroid Build Coastguard Worker size_t i;
827*59bfda1fSAndroid Build Coastguard Worker
828*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < size; i++) {
829*59bfda1fSAndroid Build Coastguard Worker if (p[i])
830*59bfda1fSAndroid Build Coastguard Worker return false;
831*59bfda1fSAndroid Build Coastguard Worker }
832*59bfda1fSAndroid Build Coastguard Worker return true;
833*59bfda1fSAndroid Build Coastguard Worker }
834*59bfda1fSAndroid Build Coastguard Worker
chk_extended_attributes(struct f2fs_sb_info * sbi,u32 nid,struct f2fs_node * inode)835*59bfda1fSAndroid Build Coastguard Worker int chk_extended_attributes(struct f2fs_sb_info *sbi, u32 nid,
836*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *inode)
837*59bfda1fSAndroid Build Coastguard Worker {
838*59bfda1fSAndroid Build Coastguard Worker void *xattr;
839*59bfda1fSAndroid Build Coastguard Worker void *last_base_addr;
840*59bfda1fSAndroid Build Coastguard Worker struct f2fs_xattr_entry *ent;
841*59bfda1fSAndroid Build Coastguard Worker __u32 xattr_size = XATTR_SIZE(&inode->i);
842*59bfda1fSAndroid Build Coastguard Worker bool need_fix = false;
843*59bfda1fSAndroid Build Coastguard Worker
844*59bfda1fSAndroid Build Coastguard Worker if (xattr_size == 0)
845*59bfda1fSAndroid Build Coastguard Worker return 0;
846*59bfda1fSAndroid Build Coastguard Worker
847*59bfda1fSAndroid Build Coastguard Worker xattr = read_all_xattrs(sbi, inode, false);
848*59bfda1fSAndroid Build Coastguard Worker ASSERT(xattr);
849*59bfda1fSAndroid Build Coastguard Worker
850*59bfda1fSAndroid Build Coastguard Worker last_base_addr = (void *)xattr + xattr_size;
851*59bfda1fSAndroid Build Coastguard Worker
852*59bfda1fSAndroid Build Coastguard Worker list_for_each_xattr(ent, xattr) {
853*59bfda1fSAndroid Build Coastguard Worker if ((void *)(ent) + sizeof(__u32) > last_base_addr ||
854*59bfda1fSAndroid Build Coastguard Worker (void *)XATTR_NEXT_ENTRY(ent) > last_base_addr) {
855*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] last xattr entry (offset: %lx) "
856*59bfda1fSAndroid Build Coastguard Worker "crosses the boundary",
857*59bfda1fSAndroid Build Coastguard Worker nid, (long int)((void *)ent - xattr));
858*59bfda1fSAndroid Build Coastguard Worker need_fix = true;
859*59bfda1fSAndroid Build Coastguard Worker break;
860*59bfda1fSAndroid Build Coastguard Worker }
861*59bfda1fSAndroid Build Coastguard Worker }
862*59bfda1fSAndroid Build Coastguard Worker if (!need_fix &&
863*59bfda1fSAndroid Build Coastguard Worker !is_zeroed((u8 *)ent, (u8 *)last_base_addr - (u8 *)ent)) {
864*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] nonzero bytes in xattr space after "
865*59bfda1fSAndroid Build Coastguard Worker "end of list", nid);
866*59bfda1fSAndroid Build Coastguard Worker need_fix = true;
867*59bfda1fSAndroid Build Coastguard Worker }
868*59bfda1fSAndroid Build Coastguard Worker if (need_fix && c.fix_on) {
869*59bfda1fSAndroid Build Coastguard Worker memset(ent, 0, (u8 *)last_base_addr - (u8 *)ent);
870*59bfda1fSAndroid Build Coastguard Worker write_all_xattrs(sbi, inode, xattr_size, xattr);
871*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] nullify wrong xattr entries", nid);
872*59bfda1fSAndroid Build Coastguard Worker free(xattr);
873*59bfda1fSAndroid Build Coastguard Worker return 1;
874*59bfda1fSAndroid Build Coastguard Worker }
875*59bfda1fSAndroid Build Coastguard Worker free(xattr);
876*59bfda1fSAndroid Build Coastguard Worker return 0;
877*59bfda1fSAndroid Build Coastguard Worker }
878*59bfda1fSAndroid Build Coastguard Worker
879*59bfda1fSAndroid Build Coastguard Worker /* start with valid nid and blkaddr */
fsck_chk_inode_blk(struct f2fs_sb_info * sbi,u32 nid,enum FILE_TYPE ftype,struct f2fs_node * node_blk,u32 * blk_cnt,struct f2fs_compr_blk_cnt * cbc,struct node_info * ni,struct child_info * child_d)880*59bfda1fSAndroid Build Coastguard Worker void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
881*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype, struct f2fs_node *node_blk,
882*59bfda1fSAndroid Build Coastguard Worker u32 *blk_cnt, struct f2fs_compr_blk_cnt *cbc,
883*59bfda1fSAndroid Build Coastguard Worker struct node_info *ni, struct child_info *child_d)
884*59bfda1fSAndroid Build Coastguard Worker {
885*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
886*59bfda1fSAndroid Build Coastguard Worker struct child_info child;
887*59bfda1fSAndroid Build Coastguard Worker enum NODE_TYPE ntype;
888*59bfda1fSAndroid Build Coastguard Worker u32 i_links = le32_to_cpu(node_blk->i.i_links);
889*59bfda1fSAndroid Build Coastguard Worker u64 i_size = le64_to_cpu(node_blk->i.i_size);
890*59bfda1fSAndroid Build Coastguard Worker u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks);
891*59bfda1fSAndroid Build Coastguard Worker bool compr_supported = c.feature & F2FS_FEATURE_COMPRESSION;
892*59bfda1fSAndroid Build Coastguard Worker u32 i_flags = le32_to_cpu(node_blk->i.i_flags);
893*59bfda1fSAndroid Build Coastguard Worker bool compressed = i_flags & F2FS_COMPR_FL;
894*59bfda1fSAndroid Build Coastguard Worker bool compr_rel = node_blk->i.i_inline & F2FS_COMPRESS_RELEASED;
895*59bfda1fSAndroid Build Coastguard Worker u64 i_compr_blocks = le64_to_cpu(node_blk->i.i_compr_blocks);
896*59bfda1fSAndroid Build Coastguard Worker nid_t i_xattr_nid = le32_to_cpu(node_blk->i.i_xattr_nid);
897*59bfda1fSAndroid Build Coastguard Worker int ofs;
898*59bfda1fSAndroid Build Coastguard Worker char *en;
899*59bfda1fSAndroid Build Coastguard Worker u32 namelen;
900*59bfda1fSAndroid Build Coastguard Worker unsigned int addrs, idx = 0;
901*59bfda1fSAndroid Build Coastguard Worker unsigned short i_gc_failures;
902*59bfda1fSAndroid Build Coastguard Worker int need_fix = 0;
903*59bfda1fSAndroid Build Coastguard Worker int ret;
904*59bfda1fSAndroid Build Coastguard Worker u32 cluster_size = 1 << node_blk->i.i_log_cluster_size;
905*59bfda1fSAndroid Build Coastguard Worker bool is_aliasing = IS_DEVICE_ALIASING(&node_blk->i);
906*59bfda1fSAndroid Build Coastguard Worker
907*59bfda1fSAndroid Build Coastguard Worker if (!compressed)
908*59bfda1fSAndroid Build Coastguard Worker goto check_next;
909*59bfda1fSAndroid Build Coastguard Worker
910*59bfda1fSAndroid Build Coastguard Worker if (!compr_supported || (node_blk->i.i_inline & F2FS_INLINE_DATA)) {
911*59bfda1fSAndroid Build Coastguard Worker /*
912*59bfda1fSAndroid Build Coastguard Worker * The 'compression' flag in i_flags affects the traverse of
913*59bfda1fSAndroid Build Coastguard Worker * the node tree. Thus, it must be fixed unconditionally
914*59bfda1fSAndroid Build Coastguard Worker * in the memory (node_blk).
915*59bfda1fSAndroid Build Coastguard Worker */
916*59bfda1fSAndroid Build Coastguard Worker i_flags &= ~F2FS_COMPR_FL;
917*59bfda1fSAndroid Build Coastguard Worker compressed = false;
918*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
919*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
920*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_flags=0x%x -> 0x%x",
921*59bfda1fSAndroid Build Coastguard Worker nid, node_blk->i.i_flags, i_flags);
922*59bfda1fSAndroid Build Coastguard Worker }
923*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_flags = cpu_to_le32(i_flags);
924*59bfda1fSAndroid Build Coastguard Worker }
925*59bfda1fSAndroid Build Coastguard Worker check_next:
926*59bfda1fSAndroid Build Coastguard Worker memset(&child, 0, sizeof(child));
927*59bfda1fSAndroid Build Coastguard Worker child.links = 2;
928*59bfda1fSAndroid Build Coastguard Worker child.p_ino = nid;
929*59bfda1fSAndroid Build Coastguard Worker child.pp_ino = le32_to_cpu(node_blk->i.i_pino);
930*59bfda1fSAndroid Build Coastguard Worker child.dir_level = node_blk->i.i_dir_level;
931*59bfda1fSAndroid Build Coastguard Worker
932*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0)
933*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_inode_cnt++;
934*59bfda1fSAndroid Build Coastguard Worker
935*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_DIR) {
936*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, ni->blk_addr, CURSEG_HOT_NODE);
937*59bfda1fSAndroid Build Coastguard Worker namelen = le32_to_cpu(node_blk->i.i_namelen);
938*59bfda1fSAndroid Build Coastguard Worker if (namelen > F2FS_NAME_LEN)
939*59bfda1fSAndroid Build Coastguard Worker namelen = F2FS_NAME_LEN;
940*59bfda1fSAndroid Build Coastguard Worker memcpy(child.p_name, node_blk->i.i_name, namelen);
941*59bfda1fSAndroid Build Coastguard Worker } else {
942*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
943*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, ni->blk_addr,
944*59bfda1fSAndroid Build Coastguard Worker CURSEG_WARM_NODE);
945*59bfda1fSAndroid Build Coastguard Worker if (i_links > 1 && ftype != F2FS_FT_ORPHAN &&
946*59bfda1fSAndroid Build Coastguard Worker !is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
947*59bfda1fSAndroid Build Coastguard Worker /* First time. Create new hard link node */
948*59bfda1fSAndroid Build Coastguard Worker add_into_hard_link_list(sbi, nid, i_links);
949*59bfda1fSAndroid Build Coastguard Worker fsck->chk.multi_hard_link_files++;
950*59bfda1fSAndroid Build Coastguard Worker }
951*59bfda1fSAndroid Build Coastguard Worker } else {
952*59bfda1fSAndroid Build Coastguard Worker DBG(3, "[0x%x] has hard links [0x%x]\n", nid, i_links);
953*59bfda1fSAndroid Build Coastguard Worker if (find_and_dec_hard_link_list(sbi, nid)) {
954*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] needs more i_links=0x%x",
955*59bfda1fSAndroid Build Coastguard Worker nid, i_links);
956*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
957*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_links =
958*59bfda1fSAndroid Build Coastguard Worker cpu_to_le32(i_links + 1);
959*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
960*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("File: 0x%x "
961*59bfda1fSAndroid Build Coastguard Worker "i_links= 0x%x -> 0x%x",
962*59bfda1fSAndroid Build Coastguard Worker nid, i_links, i_links + 1);
963*59bfda1fSAndroid Build Coastguard Worker }
964*59bfda1fSAndroid Build Coastguard Worker goto skip_blkcnt_fix;
965*59bfda1fSAndroid Build Coastguard Worker }
966*59bfda1fSAndroid Build Coastguard Worker /* No need to go deep into the node */
967*59bfda1fSAndroid Build Coastguard Worker return;
968*59bfda1fSAndroid Build Coastguard Worker }
969*59bfda1fSAndroid Build Coastguard Worker }
970*59bfda1fSAndroid Build Coastguard Worker
971*59bfda1fSAndroid Build Coastguard Worker /* readahead xattr node block */
972*59bfda1fSAndroid Build Coastguard Worker fsck_reada_node_block(sbi, i_xattr_nid);
973*59bfda1fSAndroid Build Coastguard Worker
974*59bfda1fSAndroid Build Coastguard Worker if (fsck_chk_xattr_blk(sbi, nid, i_xattr_nid, blk_cnt)) {
975*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
976*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_xattr_nid = 0;
977*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
978*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Remove xattr block: 0x%x, x_nid = 0x%x",
979*59bfda1fSAndroid Build Coastguard Worker nid, i_xattr_nid);
980*59bfda1fSAndroid Build Coastguard Worker }
981*59bfda1fSAndroid Build Coastguard Worker }
982*59bfda1fSAndroid Build Coastguard Worker
983*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV ||
984*59bfda1fSAndroid Build Coastguard Worker ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK)
985*59bfda1fSAndroid Build Coastguard Worker goto check;
986*59bfda1fSAndroid Build Coastguard Worker
987*59bfda1fSAndroid Build Coastguard Worker /* init extent info */
988*59bfda1fSAndroid Build Coastguard Worker get_extent_info(&child.ei, &node_blk->i.i_ext);
989*59bfda1fSAndroid Build Coastguard Worker child.last_blk = 0;
990*59bfda1fSAndroid Build Coastguard Worker
991*59bfda1fSAndroid Build Coastguard Worker if (f2fs_has_extra_isize(&node_blk->i)) {
992*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_EXTRA_ATTR) {
993*59bfda1fSAndroid Build Coastguard Worker unsigned int isize =
994*59bfda1fSAndroid Build Coastguard Worker le16_to_cpu(node_blk->i.i_extra_isize);
995*59bfda1fSAndroid Build Coastguard Worker if (isize > 4 * DEF_ADDRS_PER_INODE) {
996*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong i_extra_isize=0x%x",
997*59bfda1fSAndroid Build Coastguard Worker nid, isize);
998*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
999*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("ino[0x%x] recover i_extra_isize "
1000*59bfda1fSAndroid Build Coastguard Worker "from %u to %u",
1001*59bfda1fSAndroid Build Coastguard Worker nid, isize,
1002*59bfda1fSAndroid Build Coastguard Worker calc_extra_isize());
1003*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_extra_isize =
1004*59bfda1fSAndroid Build Coastguard Worker cpu_to_le16(calc_extra_isize());
1005*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1006*59bfda1fSAndroid Build Coastguard Worker }
1007*59bfda1fSAndroid Build Coastguard Worker }
1008*59bfda1fSAndroid Build Coastguard Worker } else {
1009*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong extra_attr flag", nid);
1010*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1011*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("ino[0x%x] remove F2FS_EXTRA_ATTR "
1012*59bfda1fSAndroid Build Coastguard Worker "flag in i_inline:%u",
1013*59bfda1fSAndroid Build Coastguard Worker nid, node_blk->i.i_inline);
1014*59bfda1fSAndroid Build Coastguard Worker /* we don't support tuning F2FS_FEATURE_EXTRA_ATTR now */
1015*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_inline &= ~F2FS_EXTRA_ATTR;
1016*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1017*59bfda1fSAndroid Build Coastguard Worker }
1018*59bfda1fSAndroid Build Coastguard Worker }
1019*59bfda1fSAndroid Build Coastguard Worker
1020*59bfda1fSAndroid Build Coastguard Worker if ((c.feature & F2FS_FEATURE_FLEXIBLE_INLINE_XATTR) &&
1021*59bfda1fSAndroid Build Coastguard Worker (node_blk->i.i_inline & F2FS_INLINE_XATTR)) {
1022*59bfda1fSAndroid Build Coastguard Worker unsigned int inline_size =
1023*59bfda1fSAndroid Build Coastguard Worker le16_to_cpu(node_blk->i.i_inline_xattr_size);
1024*59bfda1fSAndroid Build Coastguard Worker
1025*59bfda1fSAndroid Build Coastguard Worker if (!inline_size ||
1026*59bfda1fSAndroid Build Coastguard Worker inline_size > MAX_INLINE_XATTR_SIZE) {
1027*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong inline_xattr_size:%u",
1028*59bfda1fSAndroid Build Coastguard Worker nid, inline_size);
1029*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1030*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("ino[0x%x] recover inline xattr size "
1031*59bfda1fSAndroid Build Coastguard Worker "from %u to %u",
1032*59bfda1fSAndroid Build Coastguard Worker nid, inline_size,
1033*59bfda1fSAndroid Build Coastguard Worker DEFAULT_INLINE_XATTR_ADDRS);
1034*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_inline_xattr_size =
1035*59bfda1fSAndroid Build Coastguard Worker cpu_to_le16(DEFAULT_INLINE_XATTR_ADDRS);
1036*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1037*59bfda1fSAndroid Build Coastguard Worker }
1038*59bfda1fSAndroid Build Coastguard Worker }
1039*59bfda1fSAndroid Build Coastguard Worker }
1040*59bfda1fSAndroid Build Coastguard Worker }
1041*59bfda1fSAndroid Build Coastguard Worker ofs = get_extra_isize(node_blk);
1042*59bfda1fSAndroid Build Coastguard Worker
1043*59bfda1fSAndroid Build Coastguard Worker if ((node_blk->i.i_flags & cpu_to_le32(F2FS_CASEFOLD_FL)) &&
1044*59bfda1fSAndroid Build Coastguard Worker (!S_ISDIR(le16_to_cpu(node_blk->i.i_mode)) ||
1045*59bfda1fSAndroid Build Coastguard Worker !(c.feature & F2FS_FEATURE_CASEFOLD))) {
1046*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] unexpected casefold flag", nid);
1047*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1048*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("ino[0x%x] clear casefold flag", nid);
1049*59bfda1fSAndroid Build Coastguard Worker i_flags &= ~F2FS_CASEFOLD_FL;
1050*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_flags = cpu_to_le32(i_flags);
1051*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1052*59bfda1fSAndroid Build Coastguard Worker }
1053*59bfda1fSAndroid Build Coastguard Worker }
1054*59bfda1fSAndroid Build Coastguard Worker
1055*59bfda1fSAndroid Build Coastguard Worker if (chk_extended_attributes(sbi, nid, node_blk))
1056*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1057*59bfda1fSAndroid Build Coastguard Worker
1058*59bfda1fSAndroid Build Coastguard Worker if ((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
1059*59bfda1fSAndroid Build Coastguard Worker unsigned int inline_size = MAX_INLINE_DATA(node_blk);
1060*59bfda1fSAndroid Build Coastguard Worker if (cur_qtype != -1)
1061*59bfda1fSAndroid Build Coastguard Worker qf_szchk_type[cur_qtype] = QF_SZCHK_INLINE;
1062*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs]);
1063*59bfda1fSAndroid Build Coastguard Worker
1064*59bfda1fSAndroid Build Coastguard Worker if (blkaddr != NULL_ADDR) {
1065*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong inline reserve blkaddr:%u",
1066*59bfda1fSAndroid Build Coastguard Worker nid, blkaddr);
1067*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1068*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("inline_data has wrong 0'th block = %x",
1069*59bfda1fSAndroid Build Coastguard Worker blkaddr);
1070*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_addr[ofs] = NULL_ADDR;
1071*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
1072*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1073*59bfda1fSAndroid Build Coastguard Worker }
1074*59bfda1fSAndroid Build Coastguard Worker }
1075*59bfda1fSAndroid Build Coastguard Worker if (i_size > inline_size) {
1076*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong inline size:%lu",
1077*59bfda1fSAndroid Build Coastguard Worker nid, (unsigned long)i_size);
1078*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1079*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_size = cpu_to_le64(inline_size);
1080*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("inline_data has wrong i_size %lu",
1081*59bfda1fSAndroid Build Coastguard Worker (unsigned long)i_size);
1082*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1083*59bfda1fSAndroid Build Coastguard Worker }
1084*59bfda1fSAndroid Build Coastguard Worker }
1085*59bfda1fSAndroid Build Coastguard Worker if (!(node_blk->i.i_inline & F2FS_DATA_EXIST)) {
1086*59bfda1fSAndroid Build Coastguard Worker if (!is_zeroed(inline_data_addr(node_blk),
1087*59bfda1fSAndroid Build Coastguard Worker MAX_INLINE_DATA(node_blk))) {
1088*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] junk inline data", nid);
1089*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1090*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("inline_data has DATA_EXIST");
1091*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_inline |= F2FS_DATA_EXIST;
1092*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1093*59bfda1fSAndroid Build Coastguard Worker }
1094*59bfda1fSAndroid Build Coastguard Worker }
1095*59bfda1fSAndroid Build Coastguard Worker }
1096*59bfda1fSAndroid Build Coastguard Worker DBG(3, "ino[0x%x] has inline data!\n", nid);
1097*59bfda1fSAndroid Build Coastguard Worker child.state |= FSCK_INLINE_INODE;
1098*59bfda1fSAndroid Build Coastguard Worker goto check;
1099*59bfda1fSAndroid Build Coastguard Worker }
1100*59bfda1fSAndroid Build Coastguard Worker
1101*59bfda1fSAndroid Build Coastguard Worker if ((node_blk->i.i_inline & F2FS_INLINE_DENTRY)) {
1102*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs]);
1103*59bfda1fSAndroid Build Coastguard Worker
1104*59bfda1fSAndroid Build Coastguard Worker DBG(3, "ino[0x%x] has inline dentry!\n", nid);
1105*59bfda1fSAndroid Build Coastguard Worker if (blkaddr != 0) {
1106*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong inline reserve blkaddr:%u",
1107*59bfda1fSAndroid Build Coastguard Worker nid, blkaddr);
1108*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1109*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("inline_dentry has wrong 0'th block = %x",
1110*59bfda1fSAndroid Build Coastguard Worker blkaddr);
1111*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_addr[ofs] = NULL_ADDR;
1112*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
1113*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1114*59bfda1fSAndroid Build Coastguard Worker }
1115*59bfda1fSAndroid Build Coastguard Worker }
1116*59bfda1fSAndroid Build Coastguard Worker
1117*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_inline_dentries(sbi, node_blk, &child);
1118*59bfda1fSAndroid Build Coastguard Worker if (ret < 0) {
1119*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on)
1120*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1121*59bfda1fSAndroid Build Coastguard Worker }
1122*59bfda1fSAndroid Build Coastguard Worker child.state |= FSCK_INLINE_INODE;
1123*59bfda1fSAndroid Build Coastguard Worker goto check;
1124*59bfda1fSAndroid Build Coastguard Worker }
1125*59bfda1fSAndroid Build Coastguard Worker
1126*59bfda1fSAndroid Build Coastguard Worker /* check data blocks in inode */
1127*59bfda1fSAndroid Build Coastguard Worker addrs = ADDRS_PER_INODE(&node_blk->i);
1128*59bfda1fSAndroid Build Coastguard Worker if (cur_qtype != -1) {
1129*59bfda1fSAndroid Build Coastguard Worker u64 addrs_per_blk = (u64)ADDRS_PER_BLOCK(&node_blk->i);
1130*59bfda1fSAndroid Build Coastguard Worker qf_szchk_type[cur_qtype] = QF_SZCHK_REGFILE;
1131*59bfda1fSAndroid Build Coastguard Worker qf_maxsize[cur_qtype] = (u64)(addrs + 2 * addrs_per_blk +
1132*59bfda1fSAndroid Build Coastguard Worker 2 * addrs_per_blk * NIDS_PER_BLOCK +
1133*59bfda1fSAndroid Build Coastguard Worker addrs_per_blk * NIDS_PER_BLOCK *
1134*59bfda1fSAndroid Build Coastguard Worker NIDS_PER_BLOCK) * F2FS_BLKSIZE;
1135*59bfda1fSAndroid Build Coastguard Worker }
1136*59bfda1fSAndroid Build Coastguard Worker
1137*59bfda1fSAndroid Build Coastguard Worker if (is_aliasing) {
1138*59bfda1fSAndroid Build Coastguard Worker struct extent_info ei;
1139*59bfda1fSAndroid Build Coastguard Worker
1140*59bfda1fSAndroid Build Coastguard Worker get_extent_info(&ei, &node_blk->i.i_ext);
1141*59bfda1fSAndroid Build Coastguard Worker for (idx = 0; idx < ei.len; idx++, child.pgofs++) {
1142*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr = ei.blk + idx;
1143*59bfda1fSAndroid Build Coastguard Worker
1144*59bfda1fSAndroid Build Coastguard Worker /* check extent info */
1145*59bfda1fSAndroid Build Coastguard Worker check_extent_info(&child, blkaddr, 0);
1146*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_data_blk(sbi, &node_blk->i, blkaddr,
1147*59bfda1fSAndroid Build Coastguard Worker &child, (i_blocks == *blk_cnt), ftype, nid,
1148*59bfda1fSAndroid Build Coastguard Worker idx, ni->version, node_blk);
1149*59bfda1fSAndroid Build Coastguard Worker if (!ret) {
1150*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1151*59bfda1fSAndroid Build Coastguard Worker if (cur_qtype != -1)
1152*59bfda1fSAndroid Build Coastguard Worker qf_last_blkofs[cur_qtype] = child.pgofs;
1153*59bfda1fSAndroid Build Coastguard Worker } else if (c.fix_on) {
1154*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_ext.len = cpu_to_le32(idx);
1155*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1156*59bfda1fSAndroid Build Coastguard Worker break;
1157*59bfda1fSAndroid Build Coastguard Worker }
1158*59bfda1fSAndroid Build Coastguard Worker }
1159*59bfda1fSAndroid Build Coastguard Worker
1160*59bfda1fSAndroid Build Coastguard Worker goto check;
1161*59bfda1fSAndroid Build Coastguard Worker }
1162*59bfda1fSAndroid Build Coastguard Worker
1163*59bfda1fSAndroid Build Coastguard Worker for (idx = 0; idx < addrs; idx++, child.pgofs++) {
1164*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs + idx]);
1165*59bfda1fSAndroid Build Coastguard Worker
1166*59bfda1fSAndroid Build Coastguard Worker /* check extent info */
1167*59bfda1fSAndroid Build Coastguard Worker check_extent_info(&child, blkaddr, 0);
1168*59bfda1fSAndroid Build Coastguard Worker
1169*59bfda1fSAndroid Build Coastguard Worker if (blkaddr == NULL_ADDR)
1170*59bfda1fSAndroid Build Coastguard Worker continue;
1171*59bfda1fSAndroid Build Coastguard Worker if (blkaddr == COMPRESS_ADDR) {
1172*59bfda1fSAndroid Build Coastguard Worker if (!compressed || (child.pgofs &
1173*59bfda1fSAndroid Build Coastguard Worker (cluster_size - 1)) != 0) {
1174*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1175*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_addr[ofs + idx] =
1176*59bfda1fSAndroid Build Coastguard Worker NULL_ADDR;
1177*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1178*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_addr[%d] = NULL_ADDR",
1179*59bfda1fSAndroid Build Coastguard Worker nid, ofs + idx);
1180*59bfda1fSAndroid Build Coastguard Worker }
1181*59bfda1fSAndroid Build Coastguard Worker continue;
1182*59bfda1fSAndroid Build Coastguard Worker }
1183*59bfda1fSAndroid Build Coastguard Worker if (!compr_rel) {
1184*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_blk_cnt++;
1185*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1186*59bfda1fSAndroid Build Coastguard Worker cbc->cheader_pgofs = child.pgofs;
1187*59bfda1fSAndroid Build Coastguard Worker cbc->cnt++;
1188*59bfda1fSAndroid Build Coastguard Worker }
1189*59bfda1fSAndroid Build Coastguard Worker continue;
1190*59bfda1fSAndroid Build Coastguard Worker }
1191*59bfda1fSAndroid Build Coastguard Worker if (!compr_rel && blkaddr == NEW_ADDR &&
1192*59bfda1fSAndroid Build Coastguard Worker child.pgofs - cbc->cheader_pgofs < cluster_size)
1193*59bfda1fSAndroid Build Coastguard Worker cbc->cnt++;
1194*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_data_blk(sbi,
1195*59bfda1fSAndroid Build Coastguard Worker &node_blk->i,
1196*59bfda1fSAndroid Build Coastguard Worker blkaddr,
1197*59bfda1fSAndroid Build Coastguard Worker &child, (i_blocks == *blk_cnt),
1198*59bfda1fSAndroid Build Coastguard Worker ftype, nid, idx, ni->version,
1199*59bfda1fSAndroid Build Coastguard Worker node_blk);
1200*59bfda1fSAndroid Build Coastguard Worker if (blkaddr != le32_to_cpu(node_blk->i.i_addr[ofs + idx]))
1201*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1202*59bfda1fSAndroid Build Coastguard Worker if (!ret) {
1203*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1204*59bfda1fSAndroid Build Coastguard Worker if (cur_qtype != -1 && blkaddr != NEW_ADDR)
1205*59bfda1fSAndroid Build Coastguard Worker qf_last_blkofs[cur_qtype] = child.pgofs;
1206*59bfda1fSAndroid Build Coastguard Worker } else if (c.fix_on) {
1207*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_addr[ofs + idx] = NULL_ADDR;
1208*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1209*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_addr[%d] = NULL_ADDR", nid, ofs + idx);
1210*59bfda1fSAndroid Build Coastguard Worker }
1211*59bfda1fSAndroid Build Coastguard Worker }
1212*59bfda1fSAndroid Build Coastguard Worker
1213*59bfda1fSAndroid Build Coastguard Worker /* readahead node blocks */
1214*59bfda1fSAndroid Build Coastguard Worker for (idx = 0; idx < 5; idx++) {
1215*59bfda1fSAndroid Build Coastguard Worker u32 nid = le32_to_cpu(F2FS_INODE_I_NID(&node_blk->i, idx));
1216*59bfda1fSAndroid Build Coastguard Worker fsck_reada_node_block(sbi, nid);
1217*59bfda1fSAndroid Build Coastguard Worker }
1218*59bfda1fSAndroid Build Coastguard Worker
1219*59bfda1fSAndroid Build Coastguard Worker /* check node blocks in inode */
1220*59bfda1fSAndroid Build Coastguard Worker for (idx = 0; idx < 5; idx++) {
1221*59bfda1fSAndroid Build Coastguard Worker nid_t i_nid = le32_to_cpu(F2FS_INODE_I_NID(&node_blk->i, idx));
1222*59bfda1fSAndroid Build Coastguard Worker
1223*59bfda1fSAndroid Build Coastguard Worker if (idx == 0 || idx == 1)
1224*59bfda1fSAndroid Build Coastguard Worker ntype = TYPE_DIRECT_NODE;
1225*59bfda1fSAndroid Build Coastguard Worker else if (idx == 2 || idx == 3)
1226*59bfda1fSAndroid Build Coastguard Worker ntype = TYPE_INDIRECT_NODE;
1227*59bfda1fSAndroid Build Coastguard Worker else if (idx == 4)
1228*59bfda1fSAndroid Build Coastguard Worker ntype = TYPE_DOUBLE_INDIRECT_NODE;
1229*59bfda1fSAndroid Build Coastguard Worker else
1230*59bfda1fSAndroid Build Coastguard Worker ASSERT(0);
1231*59bfda1fSAndroid Build Coastguard Worker
1232*59bfda1fSAndroid Build Coastguard Worker if (i_nid == 0x0)
1233*59bfda1fSAndroid Build Coastguard Worker goto skip;
1234*59bfda1fSAndroid Build Coastguard Worker
1235*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_node_blk(sbi, &node_blk->i, i_nid,
1236*59bfda1fSAndroid Build Coastguard Worker ftype, ntype, blk_cnt, cbc, &child);
1237*59bfda1fSAndroid Build Coastguard Worker if (!ret) {
1238*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1239*59bfda1fSAndroid Build Coastguard Worker } else if (ret == -EINVAL) {
1240*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1241*59bfda1fSAndroid Build Coastguard Worker F2FS_INODE_I_NID(&node_blk->i, idx) = 0;
1242*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1243*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_nid[%d] = 0", nid, idx);
1244*59bfda1fSAndroid Build Coastguard Worker }
1245*59bfda1fSAndroid Build Coastguard Worker skip:
1246*59bfda1fSAndroid Build Coastguard Worker if (ntype == TYPE_DIRECT_NODE)
1247*59bfda1fSAndroid Build Coastguard Worker child.pgofs += ADDRS_PER_BLOCK(&node_blk->i);
1248*59bfda1fSAndroid Build Coastguard Worker else if (ntype == TYPE_INDIRECT_NODE)
1249*59bfda1fSAndroid Build Coastguard Worker child.pgofs += ADDRS_PER_BLOCK(&node_blk->i) *
1250*59bfda1fSAndroid Build Coastguard Worker NIDS_PER_BLOCK;
1251*59bfda1fSAndroid Build Coastguard Worker else
1252*59bfda1fSAndroid Build Coastguard Worker child.pgofs += ADDRS_PER_BLOCK(&node_blk->i) *
1253*59bfda1fSAndroid Build Coastguard Worker NIDS_PER_BLOCK * NIDS_PER_BLOCK;
1254*59bfda1fSAndroid Build Coastguard Worker }
1255*59bfda1fSAndroid Build Coastguard Worker
1256*59bfda1fSAndroid Build Coastguard Worker }
1257*59bfda1fSAndroid Build Coastguard Worker
1258*59bfda1fSAndroid Build Coastguard Worker check:
1259*59bfda1fSAndroid Build Coastguard Worker /* check uncovered range in the back of extent */
1260*59bfda1fSAndroid Build Coastguard Worker check_extent_info(&child, 0, 1);
1261*59bfda1fSAndroid Build Coastguard Worker
1262*59bfda1fSAndroid Build Coastguard Worker if (child.state & FSCK_UNMATCHED_EXTENT) {
1263*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x has wrong ext: [pgofs:%u, blk:%u, len:%u]",
1264*59bfda1fSAndroid Build Coastguard Worker nid, child.ei.fofs, child.ei.blk, child.ei.len);
1265*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on)
1266*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1267*59bfda1fSAndroid Build Coastguard Worker }
1268*59bfda1fSAndroid Build Coastguard Worker
1269*59bfda1fSAndroid Build Coastguard Worker if (i_blocks != *blk_cnt) {
1270*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x has i_blocks: 0x%08"PRIx64", "
1271*59bfda1fSAndroid Build Coastguard Worker "but has 0x%x blocks",
1272*59bfda1fSAndroid Build Coastguard Worker nid, i_blocks, *blk_cnt);
1273*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1274*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
1275*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1276*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_blocks=0x%08"PRIx64" -> 0x%x",
1277*59bfda1fSAndroid Build Coastguard Worker nid, i_blocks, *blk_cnt);
1278*59bfda1fSAndroid Build Coastguard Worker }
1279*59bfda1fSAndroid Build Coastguard Worker }
1280*59bfda1fSAndroid Build Coastguard Worker
1281*59bfda1fSAndroid Build Coastguard Worker if (compressed && i_compr_blocks != cbc->cnt) {
1282*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1283*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_compr_blocks = cpu_to_le64(cbc->cnt);
1284*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1285*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_compr_blocks=0x%08"PRIx64" -> 0x%x",
1286*59bfda1fSAndroid Build Coastguard Worker nid, i_compr_blocks, cbc->cnt);
1287*59bfda1fSAndroid Build Coastguard Worker }
1288*59bfda1fSAndroid Build Coastguard Worker }
1289*59bfda1fSAndroid Build Coastguard Worker
1290*59bfda1fSAndroid Build Coastguard Worker skip_blkcnt_fix:
1291*59bfda1fSAndroid Build Coastguard Worker en = malloc(F2FS_PRINT_NAMELEN);
1292*59bfda1fSAndroid Build Coastguard Worker ASSERT(en);
1293*59bfda1fSAndroid Build Coastguard Worker
1294*59bfda1fSAndroid Build Coastguard Worker namelen = le32_to_cpu(node_blk->i.i_namelen);
1295*59bfda1fSAndroid Build Coastguard Worker if (namelen > F2FS_NAME_LEN) {
1296*59bfda1fSAndroid Build Coastguard Worker if (child_d && child_d->i_namelen <= F2FS_NAME_LEN) {
1297*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x has i_namelen: 0x%x, "
1298*59bfda1fSAndroid Build Coastguard Worker "but has %d characters for name",
1299*59bfda1fSAndroid Build Coastguard Worker nid, namelen, child_d->i_namelen);
1300*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1301*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] i_namelen=0x%x -> 0x%x", nid, namelen,
1302*59bfda1fSAndroid Build Coastguard Worker child_d->i_namelen);
1303*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_namelen = cpu_to_le32(child_d->i_namelen);
1304*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1305*59bfda1fSAndroid Build Coastguard Worker }
1306*59bfda1fSAndroid Build Coastguard Worker namelen = child_d->i_namelen;
1307*59bfda1fSAndroid Build Coastguard Worker } else
1308*59bfda1fSAndroid Build Coastguard Worker namelen = F2FS_NAME_LEN;
1309*59bfda1fSAndroid Build Coastguard Worker }
1310*59bfda1fSAndroid Build Coastguard Worker pretty_print_filename(node_blk->i.i_name, namelen, en,
1311*59bfda1fSAndroid Build Coastguard Worker file_enc_name(&node_blk->i));
1312*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_ORPHAN)
1313*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Orphan Inode: 0x%x [%s] i_blocks: %u\n\n",
1314*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino),
1315*59bfda1fSAndroid Build Coastguard Worker en, (u32)i_blocks);
1316*59bfda1fSAndroid Build Coastguard Worker
1317*59bfda1fSAndroid Build Coastguard Worker if (is_qf_ino(F2FS_RAW_SUPER(sbi), nid))
1318*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Quota Inode: 0x%x [%s] i_blocks: %u\n\n",
1319*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino),
1320*59bfda1fSAndroid Build Coastguard Worker en, (u32)i_blocks);
1321*59bfda1fSAndroid Build Coastguard Worker
1322*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_DIR) {
1323*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Directory Inode: 0x%x [%s] depth: %d has %d files\n\n",
1324*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino), en,
1325*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(node_blk->i.i_current_depth),
1326*59bfda1fSAndroid Build Coastguard Worker child.files);
1327*59bfda1fSAndroid Build Coastguard Worker
1328*59bfda1fSAndroid Build Coastguard Worker if (i_links != child.links) {
1329*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x i_links: %u, real links: %u",
1330*59bfda1fSAndroid Build Coastguard Worker nid, i_links, child.links);
1331*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1332*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_links = cpu_to_le32(child.links);
1333*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1334*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Dir: 0x%x i_links= 0x%x -> 0x%x",
1335*59bfda1fSAndroid Build Coastguard Worker nid, i_links, child.links);
1336*59bfda1fSAndroid Build Coastguard Worker }
1337*59bfda1fSAndroid Build Coastguard Worker }
1338*59bfda1fSAndroid Build Coastguard Worker if (child.dot == 0 || child.dotdot == 0) {
1339*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x has no '.' and/or '..' dirents, dot: %u, dotdot: %u",
1340*59bfda1fSAndroid Build Coastguard Worker nid, child.dot, child.dotdot);
1341*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1342*59bfda1fSAndroid Build Coastguard Worker umode_t mode = le16_to_cpu(node_blk->i.i_mode);
1343*59bfda1fSAndroid Build Coastguard Worker
1344*59bfda1fSAndroid Build Coastguard Worker ret = convert_inline_dentry(sbi, node_blk,
1345*59bfda1fSAndroid Build Coastguard Worker &ni->blk_addr);
1346*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("convert inline dentry ino: %u, pino: %u, ret: %d",
1347*59bfda1fSAndroid Build Coastguard Worker nid, child_d->p_ino, ret);
1348*59bfda1fSAndroid Build Coastguard Worker if (ret)
1349*59bfda1fSAndroid Build Coastguard Worker goto skip_dot_fix;
1350*59bfda1fSAndroid Build Coastguard Worker
1351*59bfda1fSAndroid Build Coastguard Worker if (child.dot == 0) {
1352*59bfda1fSAndroid Build Coastguard Worker char *name = ".";
1353*59bfda1fSAndroid Build Coastguard Worker
1354*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_add_link(sbi, node_blk,
1355*59bfda1fSAndroid Build Coastguard Worker (const unsigned char *)name,
1356*59bfda1fSAndroid Build Coastguard Worker 1, nid, map_de_type(mode),
1357*59bfda1fSAndroid Build Coastguard Worker &ni->blk_addr, 0);
1358*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("add missing '%s' dirent in ino: %u, pino: %u, ret:%d",
1359*59bfda1fSAndroid Build Coastguard Worker name, nid, child_d->p_ino, ret);
1360*59bfda1fSAndroid Build Coastguard Worker if (ret)
1361*59bfda1fSAndroid Build Coastguard Worker goto skip_dot_fix;
1362*59bfda1fSAndroid Build Coastguard Worker }
1363*59bfda1fSAndroid Build Coastguard Worker
1364*59bfda1fSAndroid Build Coastguard Worker if (child.dotdot == 0) {
1365*59bfda1fSAndroid Build Coastguard Worker char *name = "..";
1366*59bfda1fSAndroid Build Coastguard Worker
1367*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_add_link(sbi, node_blk,
1368*59bfda1fSAndroid Build Coastguard Worker (const unsigned char *)name,
1369*59bfda1fSAndroid Build Coastguard Worker 2, child_d->p_ino,
1370*59bfda1fSAndroid Build Coastguard Worker map_de_type(mode),
1371*59bfda1fSAndroid Build Coastguard Worker &ni->blk_addr, 0);
1372*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("add missing '%s' dirent in ino: %u, pino: %u, ret:%d",
1373*59bfda1fSAndroid Build Coastguard Worker name, nid, child_d->p_ino, ret);
1374*59bfda1fSAndroid Build Coastguard Worker if (ret)
1375*59bfda1fSAndroid Build Coastguard Worker goto skip_dot_fix;
1376*59bfda1fSAndroid Build Coastguard Worker }
1377*59bfda1fSAndroid Build Coastguard Worker
1378*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1379*59bfda1fSAndroid Build Coastguard Worker }
1380*59bfda1fSAndroid Build Coastguard Worker }
1381*59bfda1fSAndroid Build Coastguard Worker }
1382*59bfda1fSAndroid Build Coastguard Worker skip_dot_fix:
1383*59bfda1fSAndroid Build Coastguard Worker
1384*59bfda1fSAndroid Build Coastguard Worker i_gc_failures = le16_to_cpu(node_blk->i.i_gc_failures);
1385*59bfda1fSAndroid Build Coastguard Worker
1386*59bfda1fSAndroid Build Coastguard Worker /*
1387*59bfda1fSAndroid Build Coastguard Worker * old kernel initialized i_gc_failures as 0x01, in preen mode 2,
1388*59bfda1fSAndroid Build Coastguard Worker * let's skip repairing.
1389*59bfda1fSAndroid Build Coastguard Worker */
1390*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_REG_FILE && i_gc_failures &&
1391*59bfda1fSAndroid Build Coastguard Worker (c.preen_mode != PREEN_MODE_2 || i_gc_failures != 0x01)) {
1392*59bfda1fSAndroid Build Coastguard Worker
1393*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Regular Inode: 0x%x [%s] depth: %d\n\n",
1394*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino), en,
1395*59bfda1fSAndroid Build Coastguard Worker i_gc_failures);
1396*59bfda1fSAndroid Build Coastguard Worker
1397*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1398*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_gc_failures = cpu_to_le16(0);
1399*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1400*59bfda1fSAndroid Build Coastguard Worker INFO_MSG("Regular: 0x%x reset i_gc_failures from 0x%x to 0x00",
1401*59bfda1fSAndroid Build Coastguard Worker nid, i_gc_failures);
1402*59bfda1fSAndroid Build Coastguard Worker }
1403*59bfda1fSAndroid Build Coastguard Worker }
1404*59bfda1fSAndroid Build Coastguard Worker
1405*59bfda1fSAndroid Build Coastguard Worker free(en);
1406*59bfda1fSAndroid Build Coastguard Worker
1407*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_SYMLINK && i_size == 0 &&
1408*59bfda1fSAndroid Build Coastguard Worker i_blocks == (i_xattr_nid ? 3 : 2)) {
1409*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_size = cpu_to_le64(F2FS_BLKSIZE);
1410*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1411*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Symlink: recover 0x%x with i_size=%lu",
1412*59bfda1fSAndroid Build Coastguard Worker nid, (unsigned long)F2FS_BLKSIZE);
1413*59bfda1fSAndroid Build Coastguard Worker }
1414*59bfda1fSAndroid Build Coastguard Worker
1415*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_ORPHAN && i_links) {
1416*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u",
1417*59bfda1fSAndroid Build Coastguard Worker nid, i_links);
1418*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1419*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_links = 0;
1420*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1421*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("ino: 0x%x orphan_inode, i_links= 0x%x -> 0",
1422*59bfda1fSAndroid Build Coastguard Worker nid, i_links);
1423*59bfda1fSAndroid Build Coastguard Worker }
1424*59bfda1fSAndroid Build Coastguard Worker }
1425*59bfda1fSAndroid Build Coastguard Worker
1426*59bfda1fSAndroid Build Coastguard Worker /* drop extent information to avoid potential wrong access */
1427*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable() && !is_aliasing)
1428*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_ext.len = 0;
1429*59bfda1fSAndroid Build Coastguard Worker
1430*59bfda1fSAndroid Build Coastguard Worker if ((c.feature & F2FS_FEATURE_INODE_CHKSUM) &&
1431*59bfda1fSAndroid Build Coastguard Worker f2fs_has_extra_isize(&node_blk->i)) {
1432*59bfda1fSAndroid Build Coastguard Worker __u32 provided, calculated;
1433*59bfda1fSAndroid Build Coastguard Worker
1434*59bfda1fSAndroid Build Coastguard Worker provided = le32_to_cpu(node_blk->i.i_inode_checksum);
1435*59bfda1fSAndroid Build Coastguard Worker calculated = f2fs_inode_chksum(node_blk);
1436*59bfda1fSAndroid Build Coastguard Worker
1437*59bfda1fSAndroid Build Coastguard Worker if (provided != calculated) {
1438*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("ino: 0x%x chksum:0x%x, but calculated one is: 0x%x",
1439*59bfda1fSAndroid Build Coastguard Worker nid, provided, calculated);
1440*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1441*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_inode_checksum =
1442*59bfda1fSAndroid Build Coastguard Worker cpu_to_le32(calculated);
1443*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1444*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("ino: 0x%x recover, i_inode_checksum= 0x%x -> 0x%x",
1445*59bfda1fSAndroid Build Coastguard Worker nid, provided, calculated);
1446*59bfda1fSAndroid Build Coastguard Worker }
1447*59bfda1fSAndroid Build Coastguard Worker }
1448*59bfda1fSAndroid Build Coastguard Worker }
1449*59bfda1fSAndroid Build Coastguard Worker
1450*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable()) {
1451*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, node_blk, &ni->blk_addr, NULL);
1452*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
1453*59bfda1fSAndroid Build Coastguard Worker }
1454*59bfda1fSAndroid Build Coastguard Worker }
1455*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_dnode_blk(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,u32 nid,enum FILE_TYPE ftype,struct f2fs_node * node_blk,u32 * blk_cnt,struct f2fs_compr_blk_cnt * cbc,struct child_info * child,struct node_info * ni)1456*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
1457*59bfda1fSAndroid Build Coastguard Worker u32 nid, enum FILE_TYPE ftype, struct f2fs_node *node_blk,
1458*59bfda1fSAndroid Build Coastguard Worker u32 *blk_cnt, struct f2fs_compr_blk_cnt *cbc,
1459*59bfda1fSAndroid Build Coastguard Worker struct child_info *child, struct node_info *ni)
1460*59bfda1fSAndroid Build Coastguard Worker {
1461*59bfda1fSAndroid Build Coastguard Worker int idx, ret;
1462*59bfda1fSAndroid Build Coastguard Worker int need_fix = 0;
1463*59bfda1fSAndroid Build Coastguard Worker child->p_ino = nid;
1464*59bfda1fSAndroid Build Coastguard Worker child->pp_ino = le32_to_cpu(inode->i_pino);
1465*59bfda1fSAndroid Build Coastguard Worker u32 i_flags = le32_to_cpu(inode->i_flags);
1466*59bfda1fSAndroid Build Coastguard Worker bool compressed = i_flags & F2FS_COMPR_FL;
1467*59bfda1fSAndroid Build Coastguard Worker bool compr_rel = inode->i_inline & F2FS_COMPRESS_RELEASED;
1468*59bfda1fSAndroid Build Coastguard Worker u32 cluster_size = 1 << inode->i_log_cluster_size;
1469*59bfda1fSAndroid Build Coastguard Worker
1470*59bfda1fSAndroid Build Coastguard Worker for (idx = 0; idx < ADDRS_PER_BLOCK(inode); idx++, child->pgofs++) {
1471*59bfda1fSAndroid Build Coastguard Worker block_t blkaddr = le32_to_cpu(node_blk->dn.addr[idx]);
1472*59bfda1fSAndroid Build Coastguard Worker
1473*59bfda1fSAndroid Build Coastguard Worker check_extent_info(child, blkaddr, 0);
1474*59bfda1fSAndroid Build Coastguard Worker
1475*59bfda1fSAndroid Build Coastguard Worker if (blkaddr == NULL_ADDR)
1476*59bfda1fSAndroid Build Coastguard Worker continue;
1477*59bfda1fSAndroid Build Coastguard Worker if (blkaddr == COMPRESS_ADDR) {
1478*59bfda1fSAndroid Build Coastguard Worker if (!compressed || (child->pgofs &
1479*59bfda1fSAndroid Build Coastguard Worker (cluster_size - 1)) != 0) {
1480*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1481*59bfda1fSAndroid Build Coastguard Worker node_blk->dn.addr[idx] = NULL_ADDR;
1482*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1483*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] dn.addr[%d] = 0", nid,
1484*59bfda1fSAndroid Build Coastguard Worker idx);
1485*59bfda1fSAndroid Build Coastguard Worker }
1486*59bfda1fSAndroid Build Coastguard Worker continue;
1487*59bfda1fSAndroid Build Coastguard Worker }
1488*59bfda1fSAndroid Build Coastguard Worker if (!compr_rel) {
1489*59bfda1fSAndroid Build Coastguard Worker F2FS_FSCK(sbi)->chk.valid_blk_cnt++;
1490*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1491*59bfda1fSAndroid Build Coastguard Worker cbc->cheader_pgofs = child->pgofs;
1492*59bfda1fSAndroid Build Coastguard Worker cbc->cnt++;
1493*59bfda1fSAndroid Build Coastguard Worker }
1494*59bfda1fSAndroid Build Coastguard Worker continue;
1495*59bfda1fSAndroid Build Coastguard Worker }
1496*59bfda1fSAndroid Build Coastguard Worker if (!compr_rel && blkaddr == NEW_ADDR && child->pgofs -
1497*59bfda1fSAndroid Build Coastguard Worker cbc->cheader_pgofs < cluster_size)
1498*59bfda1fSAndroid Build Coastguard Worker cbc->cnt++;
1499*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_data_blk(sbi, inode, blkaddr, child,
1500*59bfda1fSAndroid Build Coastguard Worker le64_to_cpu(inode->i_blocks) == *blk_cnt, ftype,
1501*59bfda1fSAndroid Build Coastguard Worker nid, idx, ni->version, node_blk);
1502*59bfda1fSAndroid Build Coastguard Worker if (blkaddr != le32_to_cpu(node_blk->dn.addr[idx]))
1503*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1504*59bfda1fSAndroid Build Coastguard Worker if (!ret) {
1505*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1506*59bfda1fSAndroid Build Coastguard Worker if (cur_qtype != -1 && blkaddr != NEW_ADDR)
1507*59bfda1fSAndroid Build Coastguard Worker qf_last_blkofs[cur_qtype] = child->pgofs;
1508*59bfda1fSAndroid Build Coastguard Worker } else if (c.fix_on) {
1509*59bfda1fSAndroid Build Coastguard Worker node_blk->dn.addr[idx] = NULL_ADDR;
1510*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1511*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] dn.addr[%d] = 0", nid, idx);
1512*59bfda1fSAndroid Build Coastguard Worker }
1513*59bfda1fSAndroid Build Coastguard Worker }
1514*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable()) {
1515*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, node_blk, &ni->blk_addr, NULL);
1516*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
1517*59bfda1fSAndroid Build Coastguard Worker }
1518*59bfda1fSAndroid Build Coastguard Worker return 0;
1519*59bfda1fSAndroid Build Coastguard Worker }
1520*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_idnode_blk(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,enum FILE_TYPE ftype,struct f2fs_node * node_blk,u32 * blk_cnt,struct f2fs_compr_blk_cnt * cbc,struct child_info * child)1521*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
1522*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt,
1523*59bfda1fSAndroid Build Coastguard Worker struct f2fs_compr_blk_cnt *cbc, struct child_info *child)
1524*59bfda1fSAndroid Build Coastguard Worker {
1525*59bfda1fSAndroid Build Coastguard Worker int need_fix = 0, ret;
1526*59bfda1fSAndroid Build Coastguard Worker int i = 0;
1527*59bfda1fSAndroid Build Coastguard Worker
1528*59bfda1fSAndroid Build Coastguard Worker fsck_reada_all_direct_node_blocks(sbi, node_blk);
1529*59bfda1fSAndroid Build Coastguard Worker
1530*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NIDS_PER_BLOCK; i++) {
1531*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(node_blk->in.nid[i]) == 0x0)
1532*59bfda1fSAndroid Build Coastguard Worker goto skip;
1533*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_node_blk(sbi, inode,
1534*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(node_blk->in.nid[i]),
1535*59bfda1fSAndroid Build Coastguard Worker ftype, TYPE_DIRECT_NODE, blk_cnt,
1536*59bfda1fSAndroid Build Coastguard Worker cbc, child);
1537*59bfda1fSAndroid Build Coastguard Worker if (!ret)
1538*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1539*59bfda1fSAndroid Build Coastguard Worker else if (ret == -EINVAL) {
1540*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on)
1541*59bfda1fSAndroid Build Coastguard Worker printf("should delete in.nid[i] = 0;\n");
1542*59bfda1fSAndroid Build Coastguard Worker else {
1543*59bfda1fSAndroid Build Coastguard Worker node_blk->in.nid[i] = 0;
1544*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1545*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Set indirect node 0x%x -> 0", i);
1546*59bfda1fSAndroid Build Coastguard Worker }
1547*59bfda1fSAndroid Build Coastguard Worker skip:
1548*59bfda1fSAndroid Build Coastguard Worker child->pgofs += ADDRS_PER_BLOCK(inode);
1549*59bfda1fSAndroid Build Coastguard Worker }
1550*59bfda1fSAndroid Build Coastguard Worker }
1551*59bfda1fSAndroid Build Coastguard Worker
1552*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable()) {
1553*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
1554*59bfda1fSAndroid Build Coastguard Worker nid_t nid = le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid);
1555*59bfda1fSAndroid Build Coastguard Worker
1556*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
1557*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, node_blk, &ni.blk_addr, NULL);
1558*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
1559*59bfda1fSAndroid Build Coastguard Worker }
1560*59bfda1fSAndroid Build Coastguard Worker
1561*59bfda1fSAndroid Build Coastguard Worker return 0;
1562*59bfda1fSAndroid Build Coastguard Worker }
1563*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_didnode_blk(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,enum FILE_TYPE ftype,struct f2fs_node * node_blk,u32 * blk_cnt,struct f2fs_compr_blk_cnt * cbc,struct child_info * child)1564*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
1565*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt,
1566*59bfda1fSAndroid Build Coastguard Worker struct f2fs_compr_blk_cnt *cbc, struct child_info *child)
1567*59bfda1fSAndroid Build Coastguard Worker {
1568*59bfda1fSAndroid Build Coastguard Worker int i = 0;
1569*59bfda1fSAndroid Build Coastguard Worker int need_fix = 0, ret = 0;
1570*59bfda1fSAndroid Build Coastguard Worker
1571*59bfda1fSAndroid Build Coastguard Worker fsck_reada_all_direct_node_blocks(sbi, node_blk);
1572*59bfda1fSAndroid Build Coastguard Worker
1573*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NIDS_PER_BLOCK; i++) {
1574*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(node_blk->in.nid[i]) == 0x0)
1575*59bfda1fSAndroid Build Coastguard Worker goto skip;
1576*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_node_blk(sbi, inode,
1577*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(node_blk->in.nid[i]),
1578*59bfda1fSAndroid Build Coastguard Worker ftype, TYPE_INDIRECT_NODE, blk_cnt, cbc, child);
1579*59bfda1fSAndroid Build Coastguard Worker if (!ret)
1580*59bfda1fSAndroid Build Coastguard Worker *blk_cnt = *blk_cnt + 1;
1581*59bfda1fSAndroid Build Coastguard Worker else if (ret == -EINVAL) {
1582*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on)
1583*59bfda1fSAndroid Build Coastguard Worker printf("should delete in.nid[i] = 0;\n");
1584*59bfda1fSAndroid Build Coastguard Worker else {
1585*59bfda1fSAndroid Build Coastguard Worker node_blk->in.nid[i] = 0;
1586*59bfda1fSAndroid Build Coastguard Worker need_fix = 1;
1587*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Set double indirect node 0x%x -> 0", i);
1588*59bfda1fSAndroid Build Coastguard Worker }
1589*59bfda1fSAndroid Build Coastguard Worker skip:
1590*59bfda1fSAndroid Build Coastguard Worker child->pgofs += ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK;
1591*59bfda1fSAndroid Build Coastguard Worker }
1592*59bfda1fSAndroid Build Coastguard Worker }
1593*59bfda1fSAndroid Build Coastguard Worker
1594*59bfda1fSAndroid Build Coastguard Worker if (need_fix && f2fs_dev_is_writable()) {
1595*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
1596*59bfda1fSAndroid Build Coastguard Worker nid_t nid = le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->nid);
1597*59bfda1fSAndroid Build Coastguard Worker
1598*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
1599*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, node_blk, &ni.blk_addr, NULL);
1600*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
1601*59bfda1fSAndroid Build Coastguard Worker }
1602*59bfda1fSAndroid Build Coastguard Worker
1603*59bfda1fSAndroid Build Coastguard Worker return 0;
1604*59bfda1fSAndroid Build Coastguard Worker }
1605*59bfda1fSAndroid Build Coastguard Worker
1606*59bfda1fSAndroid Build Coastguard Worker static const char *lookup_table =
1607*59bfda1fSAndroid Build Coastguard Worker "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
1608*59bfda1fSAndroid Build Coastguard Worker
1609*59bfda1fSAndroid Build Coastguard Worker /**
1610*59bfda1fSAndroid Build Coastguard Worker * base64_encode() -
1611*59bfda1fSAndroid Build Coastguard Worker *
1612*59bfda1fSAndroid Build Coastguard Worker * Encodes the input string using characters from the set [A-Za-z0-9+,].
1613*59bfda1fSAndroid Build Coastguard Worker * The encoded string is roughly 4/3 times the size of the input string.
1614*59bfda1fSAndroid Build Coastguard Worker */
base64_encode(const u8 * src,int len,char * dst)1615*59bfda1fSAndroid Build Coastguard Worker static int base64_encode(const u8 *src, int len, char *dst)
1616*59bfda1fSAndroid Build Coastguard Worker {
1617*59bfda1fSAndroid Build Coastguard Worker int i, bits = 0, ac = 0;
1618*59bfda1fSAndroid Build Coastguard Worker char *cp = dst;
1619*59bfda1fSAndroid Build Coastguard Worker
1620*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < len; i++) {
1621*59bfda1fSAndroid Build Coastguard Worker ac += src[i] << bits;
1622*59bfda1fSAndroid Build Coastguard Worker bits += 8;
1623*59bfda1fSAndroid Build Coastguard Worker do {
1624*59bfda1fSAndroid Build Coastguard Worker *cp++ = lookup_table[ac & 0x3f];
1625*59bfda1fSAndroid Build Coastguard Worker ac >>= 6;
1626*59bfda1fSAndroid Build Coastguard Worker bits -= 6;
1627*59bfda1fSAndroid Build Coastguard Worker } while (bits >= 6);
1628*59bfda1fSAndroid Build Coastguard Worker }
1629*59bfda1fSAndroid Build Coastguard Worker if (bits)
1630*59bfda1fSAndroid Build Coastguard Worker *cp++ = lookup_table[ac & 0x3f];
1631*59bfda1fSAndroid Build Coastguard Worker return cp - dst;
1632*59bfda1fSAndroid Build Coastguard Worker }
1633*59bfda1fSAndroid Build Coastguard Worker
pretty_print_filename(const u8 * raw_name,u32 len,char out[F2FS_PRINT_NAMELEN],int enc_name)1634*59bfda1fSAndroid Build Coastguard Worker void pretty_print_filename(const u8 *raw_name, u32 len,
1635*59bfda1fSAndroid Build Coastguard Worker char out[F2FS_PRINT_NAMELEN], int enc_name)
1636*59bfda1fSAndroid Build Coastguard Worker {
1637*59bfda1fSAndroid Build Coastguard Worker len = min(len, (u32)F2FS_NAME_LEN);
1638*59bfda1fSAndroid Build Coastguard Worker
1639*59bfda1fSAndroid Build Coastguard Worker if (enc_name)
1640*59bfda1fSAndroid Build Coastguard Worker len = base64_encode(raw_name, len, out);
1641*59bfda1fSAndroid Build Coastguard Worker else
1642*59bfda1fSAndroid Build Coastguard Worker memcpy(out, raw_name, len);
1643*59bfda1fSAndroid Build Coastguard Worker out[len] = 0;
1644*59bfda1fSAndroid Build Coastguard Worker }
1645*59bfda1fSAndroid Build Coastguard Worker
print_dentry(struct f2fs_sb_info * sbi,__u8 * name,u8 * bitmap,struct f2fs_dir_entry * dentry,int max,int idx,int last_blk,int enc_name)1646*59bfda1fSAndroid Build Coastguard Worker static void print_dentry(struct f2fs_sb_info *sbi, __u8 *name,
1647*59bfda1fSAndroid Build Coastguard Worker u8 *bitmap, struct f2fs_dir_entry *dentry,
1648*59bfda1fSAndroid Build Coastguard Worker int max, int idx, int last_blk, int enc_name)
1649*59bfda1fSAndroid Build Coastguard Worker {
1650*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
1651*59bfda1fSAndroid Build Coastguard Worker u32 depth = fsck->dentry_depth;
1652*59bfda1fSAndroid Build Coastguard Worker int last_de = 0;
1653*59bfda1fSAndroid Build Coastguard Worker int next_idx = 0;
1654*59bfda1fSAndroid Build Coastguard Worker u32 name_len;
1655*59bfda1fSAndroid Build Coastguard Worker unsigned int i;
1656*59bfda1fSAndroid Build Coastguard Worker int bit_offset;
1657*59bfda1fSAndroid Build Coastguard Worker char new[F2FS_PRINT_NAMELEN];
1658*59bfda1fSAndroid Build Coastguard Worker
1659*59bfda1fSAndroid Build Coastguard Worker if (!c.show_dentry && !c.show_file_map)
1660*59bfda1fSAndroid Build Coastguard Worker return;
1661*59bfda1fSAndroid Build Coastguard Worker
1662*59bfda1fSAndroid Build Coastguard Worker name_len = le16_to_cpu(dentry[idx].name_len);
1663*59bfda1fSAndroid Build Coastguard Worker next_idx = idx + (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
1664*59bfda1fSAndroid Build Coastguard Worker
1665*59bfda1fSAndroid Build Coastguard Worker bit_offset = find_next_bit_le(bitmap, max, next_idx);
1666*59bfda1fSAndroid Build Coastguard Worker if (bit_offset >= max && last_blk)
1667*59bfda1fSAndroid Build Coastguard Worker last_de = 1;
1668*59bfda1fSAndroid Build Coastguard Worker
1669*59bfda1fSAndroid Build Coastguard Worker if (tree_mark_size <= depth) {
1670*59bfda1fSAndroid Build Coastguard Worker tree_mark_size *= 2;
1671*59bfda1fSAndroid Build Coastguard Worker ASSERT(tree_mark_size != 0);
1672*59bfda1fSAndroid Build Coastguard Worker tree_mark = realloc(tree_mark, tree_mark_size);
1673*59bfda1fSAndroid Build Coastguard Worker ASSERT(tree_mark != NULL);
1674*59bfda1fSAndroid Build Coastguard Worker }
1675*59bfda1fSAndroid Build Coastguard Worker
1676*59bfda1fSAndroid Build Coastguard Worker if (last_de)
1677*59bfda1fSAndroid Build Coastguard Worker tree_mark[depth] = '`';
1678*59bfda1fSAndroid Build Coastguard Worker else
1679*59bfda1fSAndroid Build Coastguard Worker tree_mark[depth] = '|';
1680*59bfda1fSAndroid Build Coastguard Worker
1681*59bfda1fSAndroid Build Coastguard Worker if (tree_mark[depth - 1] == '`')
1682*59bfda1fSAndroid Build Coastguard Worker tree_mark[depth - 1] = ' ';
1683*59bfda1fSAndroid Build Coastguard Worker
1684*59bfda1fSAndroid Build Coastguard Worker pretty_print_filename(name, name_len, new, enc_name);
1685*59bfda1fSAndroid Build Coastguard Worker
1686*59bfda1fSAndroid Build Coastguard Worker if (c.show_file_map) {
1687*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry *d = fsck->dentry;
1688*59bfda1fSAndroid Build Coastguard Worker
1689*59bfda1fSAndroid Build Coastguard Worker if (dentry[idx].file_type != F2FS_FT_REG_FILE)
1690*59bfda1fSAndroid Build Coastguard Worker return;
1691*59bfda1fSAndroid Build Coastguard Worker
1692*59bfda1fSAndroid Build Coastguard Worker while (d) {
1693*59bfda1fSAndroid Build Coastguard Worker if (d->depth > 1)
1694*59bfda1fSAndroid Build Coastguard Worker printf("/%s", d->name);
1695*59bfda1fSAndroid Build Coastguard Worker d = d->next;
1696*59bfda1fSAndroid Build Coastguard Worker }
1697*59bfda1fSAndroid Build Coastguard Worker printf("/%s", new);
1698*59bfda1fSAndroid Build Coastguard Worker if (dump_node(sbi, le32_to_cpu(dentry[idx].ino), 0, NULL, 0, 0, NULL))
1699*59bfda1fSAndroid Build Coastguard Worker printf("\33[2K\r");
1700*59bfda1fSAndroid Build Coastguard Worker } else {
1701*59bfda1fSAndroid Build Coastguard Worker for (i = 1; i < depth; i++)
1702*59bfda1fSAndroid Build Coastguard Worker printf("%c ", tree_mark[i]);
1703*59bfda1fSAndroid Build Coastguard Worker
1704*59bfda1fSAndroid Build Coastguard Worker printf("%c-- %s <ino = 0x%x>, <encrypted (%d)>\n",
1705*59bfda1fSAndroid Build Coastguard Worker last_de ? '`' : '|',
1706*59bfda1fSAndroid Build Coastguard Worker new, le32_to_cpu(dentry[idx].ino),
1707*59bfda1fSAndroid Build Coastguard Worker enc_name);
1708*59bfda1fSAndroid Build Coastguard Worker }
1709*59bfda1fSAndroid Build Coastguard Worker }
1710*59bfda1fSAndroid Build Coastguard Worker
f2fs_check_hash_code(int encoding,int casefolded,struct f2fs_dir_entry * dentry,const unsigned char * name,u32 len,int enc_name)1711*59bfda1fSAndroid Build Coastguard Worker static int f2fs_check_hash_code(int encoding, int casefolded,
1712*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dir_entry *dentry,
1713*59bfda1fSAndroid Build Coastguard Worker const unsigned char *name, u32 len, int enc_name)
1714*59bfda1fSAndroid Build Coastguard Worker {
1715*59bfda1fSAndroid Build Coastguard Worker /* Casefolded Encrypted names require a key to compute siphash */
1716*59bfda1fSAndroid Build Coastguard Worker if (enc_name && casefolded)
1717*59bfda1fSAndroid Build Coastguard Worker return 0;
1718*59bfda1fSAndroid Build Coastguard Worker
1719*59bfda1fSAndroid Build Coastguard Worker f2fs_hash_t hash_code = f2fs_dentry_hash(encoding, casefolded, name, len);
1720*59bfda1fSAndroid Build Coastguard Worker /* fix hash_code made by old buggy code */
1721*59bfda1fSAndroid Build Coastguard Worker if (dentry->hash_code != hash_code) {
1722*59bfda1fSAndroid Build Coastguard Worker char new[F2FS_PRINT_NAMELEN];
1723*59bfda1fSAndroid Build Coastguard Worker
1724*59bfda1fSAndroid Build Coastguard Worker pretty_print_filename(name, len, new, enc_name);
1725*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Mismatch hash_code for \"%s\" [%x:%x]",
1726*59bfda1fSAndroid Build Coastguard Worker new, le32_to_cpu(dentry->hash_code),
1727*59bfda1fSAndroid Build Coastguard Worker hash_code);
1728*59bfda1fSAndroid Build Coastguard Worker dentry->hash_code = cpu_to_le32(hash_code);
1729*59bfda1fSAndroid Build Coastguard Worker return 1;
1730*59bfda1fSAndroid Build Coastguard Worker }
1731*59bfda1fSAndroid Build Coastguard Worker return 0;
1732*59bfda1fSAndroid Build Coastguard Worker }
1733*59bfda1fSAndroid Build Coastguard Worker
1734*59bfda1fSAndroid Build Coastguard Worker
__get_current_level(int dir_level,u32 pgofs)1735*59bfda1fSAndroid Build Coastguard Worker static int __get_current_level(int dir_level, u32 pgofs)
1736*59bfda1fSAndroid Build Coastguard Worker {
1737*59bfda1fSAndroid Build Coastguard Worker unsigned int bidx = 0;
1738*59bfda1fSAndroid Build Coastguard Worker int i;
1739*59bfda1fSAndroid Build Coastguard Worker
1740*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < MAX_DIR_HASH_DEPTH; i++) {
1741*59bfda1fSAndroid Build Coastguard Worker bidx += dir_buckets(i, dir_level) * bucket_blocks(i);
1742*59bfda1fSAndroid Build Coastguard Worker if (bidx > pgofs)
1743*59bfda1fSAndroid Build Coastguard Worker break;
1744*59bfda1fSAndroid Build Coastguard Worker }
1745*59bfda1fSAndroid Build Coastguard Worker return i;
1746*59bfda1fSAndroid Build Coastguard Worker }
1747*59bfda1fSAndroid Build Coastguard Worker
f2fs_check_dirent_position(const struct f2fs_dir_entry * dentry,const char * printable_name,u32 pgofs,u8 dir_level,u32 pino)1748*59bfda1fSAndroid Build Coastguard Worker static int f2fs_check_dirent_position(const struct f2fs_dir_entry *dentry,
1749*59bfda1fSAndroid Build Coastguard Worker const char *printable_name,
1750*59bfda1fSAndroid Build Coastguard Worker u32 pgofs, u8 dir_level, u32 pino)
1751*59bfda1fSAndroid Build Coastguard Worker {
1752*59bfda1fSAndroid Build Coastguard Worker unsigned int nbucket, nblock;
1753*59bfda1fSAndroid Build Coastguard Worker unsigned int bidx, end_block;
1754*59bfda1fSAndroid Build Coastguard Worker int level;
1755*59bfda1fSAndroid Build Coastguard Worker
1756*59bfda1fSAndroid Build Coastguard Worker level = __get_current_level(dir_level, pgofs);
1757*59bfda1fSAndroid Build Coastguard Worker
1758*59bfda1fSAndroid Build Coastguard Worker nbucket = dir_buckets(level, dir_level);
1759*59bfda1fSAndroid Build Coastguard Worker nblock = bucket_blocks(level);
1760*59bfda1fSAndroid Build Coastguard Worker
1761*59bfda1fSAndroid Build Coastguard Worker bidx = dir_block_index(level, dir_level,
1762*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry->hash_code) % nbucket);
1763*59bfda1fSAndroid Build Coastguard Worker end_block = bidx + nblock;
1764*59bfda1fSAndroid Build Coastguard Worker
1765*59bfda1fSAndroid Build Coastguard Worker if (pgofs >= bidx && pgofs < end_block)
1766*59bfda1fSAndroid Build Coastguard Worker return 0;
1767*59bfda1fSAndroid Build Coastguard Worker
1768*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Wrong position of dirent pino:%u, name:%s, level:%d, "
1769*59bfda1fSAndroid Build Coastguard Worker "dir_level:%d, pgofs:%u, correct range:[%u, %u]\n",
1770*59bfda1fSAndroid Build Coastguard Worker pino, printable_name, level, dir_level, pgofs, bidx,
1771*59bfda1fSAndroid Build Coastguard Worker end_block - 1);
1772*59bfda1fSAndroid Build Coastguard Worker return 1;
1773*59bfda1fSAndroid Build Coastguard Worker }
1774*59bfda1fSAndroid Build Coastguard Worker
__chk_dots_dentries(struct f2fs_sb_info * sbi,int casefolded,struct f2fs_dir_entry * dentry,struct child_info * child,u8 * name,int len,__u8 (* filename)[F2FS_SLOT_LEN],int enc_name)1775*59bfda1fSAndroid Build Coastguard Worker static int __chk_dots_dentries(struct f2fs_sb_info *sbi,
1776*59bfda1fSAndroid Build Coastguard Worker int casefolded,
1777*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dir_entry *dentry,
1778*59bfda1fSAndroid Build Coastguard Worker struct child_info *child,
1779*59bfda1fSAndroid Build Coastguard Worker u8 *name, int len,
1780*59bfda1fSAndroid Build Coastguard Worker __u8 (*filename)[F2FS_SLOT_LEN],
1781*59bfda1fSAndroid Build Coastguard Worker int enc_name)
1782*59bfda1fSAndroid Build Coastguard Worker {
1783*59bfda1fSAndroid Build Coastguard Worker int fixed = 0;
1784*59bfda1fSAndroid Build Coastguard Worker
1785*59bfda1fSAndroid Build Coastguard Worker if ((name[0] == '.' && len == 1)) {
1786*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(dentry->ino) != child->p_ino) {
1787*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Bad inode number[0x%x] for '.', parent_ino is [0x%x]\n",
1788*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry->ino), child->p_ino);
1789*59bfda1fSAndroid Build Coastguard Worker dentry->ino = cpu_to_le32(child->p_ino);
1790*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1791*59bfda1fSAndroid Build Coastguard Worker }
1792*59bfda1fSAndroid Build Coastguard Worker }
1793*59bfda1fSAndroid Build Coastguard Worker
1794*59bfda1fSAndroid Build Coastguard Worker if (name[0] == '.' && name[1] == '.' && len == 2) {
1795*59bfda1fSAndroid Build Coastguard Worker if (child->p_ino == F2FS_ROOT_INO(sbi)) {
1796*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(dentry->ino) != F2FS_ROOT_INO(sbi)) {
1797*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Bad inode number[0x%x] for '..'\n",
1798*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry->ino));
1799*59bfda1fSAndroid Build Coastguard Worker dentry->ino = cpu_to_le32(F2FS_ROOT_INO(sbi));
1800*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1801*59bfda1fSAndroid Build Coastguard Worker }
1802*59bfda1fSAndroid Build Coastguard Worker } else if (le32_to_cpu(dentry->ino) != child->pp_ino) {
1803*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Bad inode number[0x%x] for '..', parent parent ino is [0x%x]\n",
1804*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry->ino), child->pp_ino);
1805*59bfda1fSAndroid Build Coastguard Worker dentry->ino = cpu_to_le32(child->pp_ino);
1806*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1807*59bfda1fSAndroid Build Coastguard Worker }
1808*59bfda1fSAndroid Build Coastguard Worker }
1809*59bfda1fSAndroid Build Coastguard Worker
1810*59bfda1fSAndroid Build Coastguard Worker if (f2fs_check_hash_code(get_encoding(sbi), casefolded, dentry, name, len, enc_name))
1811*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1812*59bfda1fSAndroid Build Coastguard Worker
1813*59bfda1fSAndroid Build Coastguard Worker if (name[len] != '\0') {
1814*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("'.' is not NULL terminated\n");
1815*59bfda1fSAndroid Build Coastguard Worker name[len] = '\0';
1816*59bfda1fSAndroid Build Coastguard Worker memcpy(*filename, name, len);
1817*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1818*59bfda1fSAndroid Build Coastguard Worker }
1819*59bfda1fSAndroid Build Coastguard Worker return fixed;
1820*59bfda1fSAndroid Build Coastguard Worker }
1821*59bfda1fSAndroid Build Coastguard Worker
nullify_dentry(struct f2fs_dir_entry * dentry,int offs,__u8 (* filename)[F2FS_SLOT_LEN],u8 ** bitmap)1822*59bfda1fSAndroid Build Coastguard Worker static void nullify_dentry(struct f2fs_dir_entry *dentry, int offs,
1823*59bfda1fSAndroid Build Coastguard Worker __u8 (*filename)[F2FS_SLOT_LEN], u8 **bitmap)
1824*59bfda1fSAndroid Build Coastguard Worker {
1825*59bfda1fSAndroid Build Coastguard Worker memset(dentry, 0, sizeof(struct f2fs_dir_entry));
1826*59bfda1fSAndroid Build Coastguard Worker test_and_clear_bit_le(offs, *bitmap);
1827*59bfda1fSAndroid Build Coastguard Worker memset(*filename, 0, F2FS_SLOT_LEN);
1828*59bfda1fSAndroid Build Coastguard Worker }
1829*59bfda1fSAndroid Build Coastguard Worker
__chk_dentries(struct f2fs_sb_info * sbi,int casefolded,struct child_info * child,u8 * bitmap,struct f2fs_dir_entry * dentry,__u8 (* filenames)[F2FS_SLOT_LEN],int max,int last_blk,int enc_name)1830*59bfda1fSAndroid Build Coastguard Worker static int __chk_dentries(struct f2fs_sb_info *sbi, int casefolded,
1831*59bfda1fSAndroid Build Coastguard Worker struct child_info *child,
1832*59bfda1fSAndroid Build Coastguard Worker u8 *bitmap, struct f2fs_dir_entry *dentry,
1833*59bfda1fSAndroid Build Coastguard Worker __u8 (*filenames)[F2FS_SLOT_LEN],
1834*59bfda1fSAndroid Build Coastguard Worker int max, int last_blk, int enc_name)
1835*59bfda1fSAndroid Build Coastguard Worker {
1836*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
1837*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype;
1838*59bfda1fSAndroid Build Coastguard Worker int dentries = 0;
1839*59bfda1fSAndroid Build Coastguard Worker u32 blk_cnt;
1840*59bfda1fSAndroid Build Coastguard Worker struct f2fs_compr_blk_cnt cbc;
1841*59bfda1fSAndroid Build Coastguard Worker u8 *name;
1842*59bfda1fSAndroid Build Coastguard Worker char en[F2FS_PRINT_NAMELEN];
1843*59bfda1fSAndroid Build Coastguard Worker u16 name_len;
1844*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
1845*59bfda1fSAndroid Build Coastguard Worker int fixed = 0;
1846*59bfda1fSAndroid Build Coastguard Worker int i, slots;
1847*59bfda1fSAndroid Build Coastguard Worker
1848*59bfda1fSAndroid Build Coastguard Worker /* readahead inode blocks */
1849*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < max; i++) {
1850*59bfda1fSAndroid Build Coastguard Worker u32 ino;
1851*59bfda1fSAndroid Build Coastguard Worker
1852*59bfda1fSAndroid Build Coastguard Worker if (test_bit_le(i, bitmap) == 0)
1853*59bfda1fSAndroid Build Coastguard Worker continue;
1854*59bfda1fSAndroid Build Coastguard Worker
1855*59bfda1fSAndroid Build Coastguard Worker ino = le32_to_cpu(dentry[i].ino);
1856*59bfda1fSAndroid Build Coastguard Worker
1857*59bfda1fSAndroid Build Coastguard Worker if (IS_VALID_NID(sbi, ino)) {
1858*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
1859*59bfda1fSAndroid Build Coastguard Worker
1860*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, ino, &ni);
1861*59bfda1fSAndroid Build Coastguard Worker if (f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
1862*59bfda1fSAndroid Build Coastguard Worker DATA_GENERIC)) {
1863*59bfda1fSAndroid Build Coastguard Worker dev_reada_block(ni.blk_addr);
1864*59bfda1fSAndroid Build Coastguard Worker name_len = le16_to_cpu(dentry[i].name_len);
1865*59bfda1fSAndroid Build Coastguard Worker if (name_len > 0)
1866*59bfda1fSAndroid Build Coastguard Worker i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN - 1;
1867*59bfda1fSAndroid Build Coastguard Worker }
1868*59bfda1fSAndroid Build Coastguard Worker }
1869*59bfda1fSAndroid Build Coastguard Worker }
1870*59bfda1fSAndroid Build Coastguard Worker
1871*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < max;) {
1872*59bfda1fSAndroid Build Coastguard Worker if (test_bit_le(i, bitmap) == 0) {
1873*59bfda1fSAndroid Build Coastguard Worker i++;
1874*59bfda1fSAndroid Build Coastguard Worker continue;
1875*59bfda1fSAndroid Build Coastguard Worker }
1876*59bfda1fSAndroid Build Coastguard Worker if (!IS_VALID_NID(sbi, le32_to_cpu(dentry[i].ino))) {
1877*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Bad dentry 0x%x with invalid NID/ino 0x%x",
1878*59bfda1fSAndroid Build Coastguard Worker i, le32_to_cpu(dentry[i].ino));
1879*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1880*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Clear bad dentry 0x%x with bad ino 0x%x",
1881*59bfda1fSAndroid Build Coastguard Worker i, le32_to_cpu(dentry[i].ino));
1882*59bfda1fSAndroid Build Coastguard Worker test_and_clear_bit_le(i, bitmap);
1883*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1884*59bfda1fSAndroid Build Coastguard Worker }
1885*59bfda1fSAndroid Build Coastguard Worker i++;
1886*59bfda1fSAndroid Build Coastguard Worker continue;
1887*59bfda1fSAndroid Build Coastguard Worker }
1888*59bfda1fSAndroid Build Coastguard Worker
1889*59bfda1fSAndroid Build Coastguard Worker ftype = dentry[i].file_type;
1890*59bfda1fSAndroid Build Coastguard Worker if ((ftype <= F2FS_FT_UNKNOWN || ftype > F2FS_FT_LAST_FILE_TYPE)) {
1891*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Bad dentry 0x%x with unexpected ftype 0x%x",
1892*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry[i].ino), ftype);
1893*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1894*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Clear bad dentry 0x%x with bad ftype 0x%x",
1895*59bfda1fSAndroid Build Coastguard Worker i, ftype);
1896*59bfda1fSAndroid Build Coastguard Worker test_and_clear_bit_le(i, bitmap);
1897*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1898*59bfda1fSAndroid Build Coastguard Worker }
1899*59bfda1fSAndroid Build Coastguard Worker i++;
1900*59bfda1fSAndroid Build Coastguard Worker continue;
1901*59bfda1fSAndroid Build Coastguard Worker }
1902*59bfda1fSAndroid Build Coastguard Worker
1903*59bfda1fSAndroid Build Coastguard Worker name_len = le16_to_cpu(dentry[i].name_len);
1904*59bfda1fSAndroid Build Coastguard Worker
1905*59bfda1fSAndroid Build Coastguard Worker if (name_len == 0 || name_len > F2FS_NAME_LEN) {
1906*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Bad dentry 0x%x with invalid name_len", i);
1907*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1908*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Clear bad dentry 0x%x", i);
1909*59bfda1fSAndroid Build Coastguard Worker test_and_clear_bit_le(i, bitmap);
1910*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1911*59bfda1fSAndroid Build Coastguard Worker }
1912*59bfda1fSAndroid Build Coastguard Worker i++;
1913*59bfda1fSAndroid Build Coastguard Worker continue;
1914*59bfda1fSAndroid Build Coastguard Worker }
1915*59bfda1fSAndroid Build Coastguard Worker name = calloc(name_len + 1, 1);
1916*59bfda1fSAndroid Build Coastguard Worker ASSERT(name);
1917*59bfda1fSAndroid Build Coastguard Worker
1918*59bfda1fSAndroid Build Coastguard Worker memcpy(name, filenames[i], name_len);
1919*59bfda1fSAndroid Build Coastguard Worker slots = (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
1920*59bfda1fSAndroid Build Coastguard Worker
1921*59bfda1fSAndroid Build Coastguard Worker /* Becareful. 'dentry.file_type' is not imode. */
1922*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_DIR) {
1923*59bfda1fSAndroid Build Coastguard Worker enum dot_type dot_type = NON_DOT;
1924*59bfda1fSAndroid Build Coastguard Worker
1925*59bfda1fSAndroid Build Coastguard Worker if (name[0] == '.' && name_len == 1)
1926*59bfda1fSAndroid Build Coastguard Worker dot_type = TYPE_DOT;
1927*59bfda1fSAndroid Build Coastguard Worker else if (name[0] == '.' && name[1] == '.' &&
1928*59bfda1fSAndroid Build Coastguard Worker name_len == 2)
1929*59bfda1fSAndroid Build Coastguard Worker dot_type = TYPE_DOTDOT;
1930*59bfda1fSAndroid Build Coastguard Worker
1931*59bfda1fSAndroid Build Coastguard Worker if (dot_type != NON_DOT) {
1932*59bfda1fSAndroid Build Coastguard Worker bool need_del = false;
1933*59bfda1fSAndroid Build Coastguard Worker
1934*59bfda1fSAndroid Build Coastguard Worker DBG(3, "i:%u, dot_type:%u, ino:%u, p:%u, pp:%u\n",
1935*59bfda1fSAndroid Build Coastguard Worker i, dot_type, dentry[i].ino,
1936*59bfda1fSAndroid Build Coastguard Worker child->p_ino, child->pp_ino);
1937*59bfda1fSAndroid Build Coastguard Worker
1938*59bfda1fSAndroid Build Coastguard Worker ret = __chk_dots_dentries(sbi, casefolded,
1939*59bfda1fSAndroid Build Coastguard Worker &dentry[i], child, name, name_len,
1940*59bfda1fSAndroid Build Coastguard Worker &filenames[i], enc_name);
1941*59bfda1fSAndroid Build Coastguard Worker if (ret)
1942*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1943*59bfda1fSAndroid Build Coastguard Worker
1944*59bfda1fSAndroid Build Coastguard Worker if (dot_type == TYPE_DOT) {
1945*59bfda1fSAndroid Build Coastguard Worker if (child->dot == 0)
1946*59bfda1fSAndroid Build Coastguard Worker child->dot++;
1947*59bfda1fSAndroid Build Coastguard Worker else
1948*59bfda1fSAndroid Build Coastguard Worker need_del = true;
1949*59bfda1fSAndroid Build Coastguard Worker } else if (dot_type == TYPE_DOTDOT) {
1950*59bfda1fSAndroid Build Coastguard Worker if (child->dotdot == 0)
1951*59bfda1fSAndroid Build Coastguard Worker child->dotdot++;
1952*59bfda1fSAndroid Build Coastguard Worker else
1953*59bfda1fSAndroid Build Coastguard Worker need_del = true;
1954*59bfda1fSAndroid Build Coastguard Worker }
1955*59bfda1fSAndroid Build Coastguard Worker
1956*59bfda1fSAndroid Build Coastguard Worker if (need_del) {
1957*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("More than one '%s', should delete the extra one, i: %u, ino:%u",
1958*59bfda1fSAndroid Build Coastguard Worker dot_type == TYPE_DOT ? "." : "..",
1959*59bfda1fSAndroid Build Coastguard Worker i, dentry[i].ino);
1960*59bfda1fSAndroid Build Coastguard Worker nullify_dentry(&dentry[i], i,
1961*59bfda1fSAndroid Build Coastguard Worker &filenames[i], &bitmap);
1962*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1963*59bfda1fSAndroid Build Coastguard Worker }
1964*59bfda1fSAndroid Build Coastguard Worker
1965*59bfda1fSAndroid Build Coastguard Worker i++;
1966*59bfda1fSAndroid Build Coastguard Worker free(name);
1967*59bfda1fSAndroid Build Coastguard Worker continue;
1968*59bfda1fSAndroid Build Coastguard Worker }
1969*59bfda1fSAndroid Build Coastguard Worker }
1970*59bfda1fSAndroid Build Coastguard Worker
1971*59bfda1fSAndroid Build Coastguard Worker if (f2fs_check_hash_code(get_encoding(sbi), casefolded, dentry + i, name, name_len, enc_name))
1972*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1973*59bfda1fSAndroid Build Coastguard Worker
1974*59bfda1fSAndroid Build Coastguard Worker pretty_print_filename(name, name_len, en, enc_name);
1975*59bfda1fSAndroid Build Coastguard Worker
1976*59bfda1fSAndroid Build Coastguard Worker if (max == NR_DENTRY_IN_BLOCK) {
1977*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_check_dirent_position(dentry + i, en,
1978*59bfda1fSAndroid Build Coastguard Worker child->pgofs, child->dir_level,
1979*59bfda1fSAndroid Build Coastguard Worker child->p_ino);
1980*59bfda1fSAndroid Build Coastguard Worker if (ret) {
1981*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
1982*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Clear bad dentry 0x%x", i);
1983*59bfda1fSAndroid Build Coastguard Worker test_and_clear_bit_le(i, bitmap);
1984*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
1985*59bfda1fSAndroid Build Coastguard Worker }
1986*59bfda1fSAndroid Build Coastguard Worker i++;
1987*59bfda1fSAndroid Build Coastguard Worker free(name);
1988*59bfda1fSAndroid Build Coastguard Worker continue;
1989*59bfda1fSAndroid Build Coastguard Worker }
1990*59bfda1fSAndroid Build Coastguard Worker }
1991*59bfda1fSAndroid Build Coastguard Worker
1992*59bfda1fSAndroid Build Coastguard Worker DBG(1, "[%3u]-[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n",
1993*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth, i, en, name_len,
1994*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry[i].ino),
1995*59bfda1fSAndroid Build Coastguard Worker dentry[i].file_type);
1996*59bfda1fSAndroid Build Coastguard Worker
1997*59bfda1fSAndroid Build Coastguard Worker print_dentry(sbi, name, bitmap,
1998*59bfda1fSAndroid Build Coastguard Worker dentry, max, i, last_blk, enc_name);
1999*59bfda1fSAndroid Build Coastguard Worker
2000*59bfda1fSAndroid Build Coastguard Worker blk_cnt = 1;
2001*59bfda1fSAndroid Build Coastguard Worker cbc.cnt = 0;
2002*59bfda1fSAndroid Build Coastguard Worker cbc.cheader_pgofs = CHEADER_PGOFS_NONE;
2003*59bfda1fSAndroid Build Coastguard Worker child->i_namelen = name_len;
2004*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_node_blk(sbi,
2005*59bfda1fSAndroid Build Coastguard Worker NULL, le32_to_cpu(dentry[i].ino),
2006*59bfda1fSAndroid Build Coastguard Worker ftype, TYPE_INODE, &blk_cnt, &cbc, child);
2007*59bfda1fSAndroid Build Coastguard Worker
2008*59bfda1fSAndroid Build Coastguard Worker if (ret && c.fix_on) {
2009*59bfda1fSAndroid Build Coastguard Worker int j;
2010*59bfda1fSAndroid Build Coastguard Worker
2011*59bfda1fSAndroid Build Coastguard Worker for (j = 0; j < slots; j++)
2012*59bfda1fSAndroid Build Coastguard Worker test_and_clear_bit_le(i + j, bitmap);
2013*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Unlink [0x%x] - %s len[0x%x], type[0x%x]",
2014*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(dentry[i].ino),
2015*59bfda1fSAndroid Build Coastguard Worker en, name_len,
2016*59bfda1fSAndroid Build Coastguard Worker dentry[i].file_type);
2017*59bfda1fSAndroid Build Coastguard Worker fixed = 1;
2018*59bfda1fSAndroid Build Coastguard Worker } else if (ret == 0) {
2019*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_DIR)
2020*59bfda1fSAndroid Build Coastguard Worker child->links++;
2021*59bfda1fSAndroid Build Coastguard Worker dentries++;
2022*59bfda1fSAndroid Build Coastguard Worker child->files++;
2023*59bfda1fSAndroid Build Coastguard Worker }
2024*59bfda1fSAndroid Build Coastguard Worker
2025*59bfda1fSAndroid Build Coastguard Worker i += slots;
2026*59bfda1fSAndroid Build Coastguard Worker free(name);
2027*59bfda1fSAndroid Build Coastguard Worker }
2028*59bfda1fSAndroid Build Coastguard Worker return fixed ? -1 : dentries;
2029*59bfda1fSAndroid Build Coastguard Worker }
2030*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_inline_dentries(struct f2fs_sb_info * sbi,struct f2fs_node * node_blk,struct child_info * child)2031*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
2032*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk, struct child_info *child)
2033*59bfda1fSAndroid Build Coastguard Worker {
2034*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2035*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry *cur_dentry = fsck->dentry_end;
2036*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry *new_dentry;
2037*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry_ptr d;
2038*59bfda1fSAndroid Build Coastguard Worker void *inline_dentry;
2039*59bfda1fSAndroid Build Coastguard Worker int dentries;
2040*59bfda1fSAndroid Build Coastguard Worker
2041*59bfda1fSAndroid Build Coastguard Worker inline_dentry = inline_data_addr(node_blk);
2042*59bfda1fSAndroid Build Coastguard Worker ASSERT(inline_dentry != NULL);
2043*59bfda1fSAndroid Build Coastguard Worker
2044*59bfda1fSAndroid Build Coastguard Worker make_dentry_ptr(&d, node_blk, inline_dentry, 2);
2045*59bfda1fSAndroid Build Coastguard Worker
2046*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth++;
2047*59bfda1fSAndroid Build Coastguard Worker new_dentry = calloc(sizeof(struct f2fs_dentry), 1);
2048*59bfda1fSAndroid Build Coastguard Worker ASSERT(new_dentry != NULL);
2049*59bfda1fSAndroid Build Coastguard Worker
2050*59bfda1fSAndroid Build Coastguard Worker new_dentry->depth = fsck->dentry_depth;
2051*59bfda1fSAndroid Build Coastguard Worker memcpy(new_dentry->name, child->p_name, F2FS_NAME_LEN);
2052*59bfda1fSAndroid Build Coastguard Worker cur_dentry->next = new_dentry;
2053*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_end = new_dentry;
2054*59bfda1fSAndroid Build Coastguard Worker
2055*59bfda1fSAndroid Build Coastguard Worker dentries = __chk_dentries(sbi, IS_CASEFOLDED(&node_blk->i), child,
2056*59bfda1fSAndroid Build Coastguard Worker d.bitmap, d.dentry, d.filename, d.max, 1,
2057*59bfda1fSAndroid Build Coastguard Worker file_is_encrypt(&node_blk->i));// pass through
2058*59bfda1fSAndroid Build Coastguard Worker if (dentries < 0) {
2059*59bfda1fSAndroid Build Coastguard Worker DBG(1, "[%3d] Inline Dentry Block Fixed hash_codes\n\n",
2060*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth);
2061*59bfda1fSAndroid Build Coastguard Worker } else {
2062*59bfda1fSAndroid Build Coastguard Worker DBG(1, "[%3d] Inline Dentry Block Done : "
2063*59bfda1fSAndroid Build Coastguard Worker "dentries:%d in %d slots (len:%d)\n\n",
2064*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth, dentries,
2065*59bfda1fSAndroid Build Coastguard Worker d.max, F2FS_NAME_LEN);
2066*59bfda1fSAndroid Build Coastguard Worker }
2067*59bfda1fSAndroid Build Coastguard Worker fsck->dentry = cur_dentry;
2068*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_end = cur_dentry;
2069*59bfda1fSAndroid Build Coastguard Worker cur_dentry->next = NULL;
2070*59bfda1fSAndroid Build Coastguard Worker free(new_dentry);
2071*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth--;
2072*59bfda1fSAndroid Build Coastguard Worker return dentries;
2073*59bfda1fSAndroid Build Coastguard Worker }
2074*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_dentry_blk(struct f2fs_sb_info * sbi,int casefolded,u32 blk_addr,struct child_info * child,int last_blk,int enc_name,struct f2fs_node * node_blk)2075*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, int casefolded, u32 blk_addr,
2076*59bfda1fSAndroid Build Coastguard Worker struct child_info *child, int last_blk, int enc_name,
2077*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk)
2078*59bfda1fSAndroid Build Coastguard Worker {
2079*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2080*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry_block *de_blk;
2081*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry *cur_dentry = fsck->dentry_end;
2082*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry *new_dentry;
2083*59bfda1fSAndroid Build Coastguard Worker int dentries, ret;
2084*59bfda1fSAndroid Build Coastguard Worker
2085*59bfda1fSAndroid Build Coastguard Worker de_blk = (struct f2fs_dentry_block *)calloc(F2FS_BLKSIZE, 1);
2086*59bfda1fSAndroid Build Coastguard Worker ASSERT(de_blk != NULL);
2087*59bfda1fSAndroid Build Coastguard Worker
2088*59bfda1fSAndroid Build Coastguard Worker ret = dev_read_block(de_blk, blk_addr);
2089*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2090*59bfda1fSAndroid Build Coastguard Worker
2091*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth++;
2092*59bfda1fSAndroid Build Coastguard Worker new_dentry = calloc(sizeof(struct f2fs_dentry), 1);
2093*59bfda1fSAndroid Build Coastguard Worker ASSERT(new_dentry != NULL);
2094*59bfda1fSAndroid Build Coastguard Worker new_dentry->depth = fsck->dentry_depth;
2095*59bfda1fSAndroid Build Coastguard Worker memcpy(new_dentry->name, child->p_name, F2FS_NAME_LEN);
2096*59bfda1fSAndroid Build Coastguard Worker cur_dentry->next = new_dentry;
2097*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_end = new_dentry;
2098*59bfda1fSAndroid Build Coastguard Worker
2099*59bfda1fSAndroid Build Coastguard Worker dentries = __chk_dentries(sbi, casefolded, child,
2100*59bfda1fSAndroid Build Coastguard Worker de_blk->dentry_bitmap,
2101*59bfda1fSAndroid Build Coastguard Worker F2FS_DENTRY_BLOCK_DENTRIES(de_blk), F2FS_DENTRY_BLOCK_FILENAMES(de_blk),
2102*59bfda1fSAndroid Build Coastguard Worker NR_DENTRY_IN_BLOCK, last_blk, enc_name);
2103*59bfda1fSAndroid Build Coastguard Worker
2104*59bfda1fSAndroid Build Coastguard Worker if (dentries < 0 && f2fs_dev_is_writable()) {
2105*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, de_blk, &blk_addr, node_blk);
2106*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2107*59bfda1fSAndroid Build Coastguard Worker DBG(1, "[%3d] Dentry Block [0x%x] Fixed hash_codes\n\n",
2108*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth, blk_addr);
2109*59bfda1fSAndroid Build Coastguard Worker } else {
2110*59bfda1fSAndroid Build Coastguard Worker DBG(1, "[%3d] Dentry Block [0x%x] Done : "
2111*59bfda1fSAndroid Build Coastguard Worker "dentries:%d in %d slots (len:%d)\n\n",
2112*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth, blk_addr, dentries,
2113*59bfda1fSAndroid Build Coastguard Worker NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN);
2114*59bfda1fSAndroid Build Coastguard Worker }
2115*59bfda1fSAndroid Build Coastguard Worker fsck->dentry = cur_dentry;
2116*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_end = cur_dentry;
2117*59bfda1fSAndroid Build Coastguard Worker cur_dentry->next = NULL;
2118*59bfda1fSAndroid Build Coastguard Worker free(new_dentry);
2119*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_depth--;
2120*59bfda1fSAndroid Build Coastguard Worker free(de_blk);
2121*59bfda1fSAndroid Build Coastguard Worker return 0;
2122*59bfda1fSAndroid Build Coastguard Worker }
2123*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_data_blk(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,u32 blk_addr,struct child_info * child,int last_blk,enum FILE_TYPE ftype,u32 parent_nid,u16 idx_in_node,u8 ver,struct f2fs_node * node_blk)2124*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_data_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
2125*59bfda1fSAndroid Build Coastguard Worker u32 blk_addr, struct child_info *child, int last_blk,
2126*59bfda1fSAndroid Build Coastguard Worker enum FILE_TYPE ftype, u32 parent_nid, u16 idx_in_node, u8 ver,
2127*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk)
2128*59bfda1fSAndroid Build Coastguard Worker {
2129*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2130*59bfda1fSAndroid Build Coastguard Worker int casefolded = IS_CASEFOLDED(inode);
2131*59bfda1fSAndroid Build Coastguard Worker int enc_name = file_is_encrypt(inode);
2132*59bfda1fSAndroid Build Coastguard Worker int aliasing = IS_DEVICE_ALIASING(inode);
2133*59bfda1fSAndroid Build Coastguard Worker
2134*59bfda1fSAndroid Build Coastguard Worker /* Is it reserved block? */
2135*59bfda1fSAndroid Build Coastguard Worker if (blk_addr == NEW_ADDR) {
2136*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_blk_cnt++;
2137*59bfda1fSAndroid Build Coastguard Worker return 0;
2138*59bfda1fSAndroid Build Coastguard Worker }
2139*59bfda1fSAndroid Build Coastguard Worker
2140*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_is_valid_blkaddr(sbi, blk_addr, DATA_GENERIC)) {
2141*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("blkaddress is not valid. [0x%x]", blk_addr);
2142*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2143*59bfda1fSAndroid Build Coastguard Worker }
2144*59bfda1fSAndroid Build Coastguard Worker
2145*59bfda1fSAndroid Build Coastguard Worker if (!aliasing && is_valid_ssa_data_blk(sbi, blk_addr, parent_nid,
2146*59bfda1fSAndroid Build Coastguard Worker idx_in_node, ver)) {
2147*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("summary data block is not valid. [0x%x]",
2148*59bfda1fSAndroid Build Coastguard Worker parent_nid);
2149*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2150*59bfda1fSAndroid Build Coastguard Worker }
2151*59bfda1fSAndroid Build Coastguard Worker
2152*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_sit_bitmap(sbi, blk_addr) == 0)
2153*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("SIT bitmap is 0x0. blk_addr[0x%x]", blk_addr);
2154*59bfda1fSAndroid Build Coastguard Worker
2155*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_main_bitmap(sbi, blk_addr) != 0)
2156*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Duplicated data [0x%x]. pnid[0x%x] idx[0x%x]",
2157*59bfda1fSAndroid Build Coastguard Worker blk_addr, parent_nid, idx_in_node);
2158*59bfda1fSAndroid Build Coastguard Worker
2159*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_blk_cnt++;
2160*59bfda1fSAndroid Build Coastguard Worker
2161*59bfda1fSAndroid Build Coastguard Worker if (ftype == F2FS_FT_DIR) {
2162*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_HOT_DATA);
2163*59bfda1fSAndroid Build Coastguard Worker return fsck_chk_dentry_blk(sbi, casefolded, blk_addr, child,
2164*59bfda1fSAndroid Build Coastguard Worker last_blk, enc_name, node_blk);
2165*59bfda1fSAndroid Build Coastguard Worker } else {
2166*59bfda1fSAndroid Build Coastguard Worker f2fs_set_main_bitmap(sbi, blk_addr, CURSEG_WARM_DATA);
2167*59bfda1fSAndroid Build Coastguard Worker }
2168*59bfda1fSAndroid Build Coastguard Worker return 0;
2169*59bfda1fSAndroid Build Coastguard Worker }
2170*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_orphan_node(struct f2fs_sb_info * sbi)2171*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_orphan_node(struct f2fs_sb_info *sbi)
2172*59bfda1fSAndroid Build Coastguard Worker {
2173*59bfda1fSAndroid Build Coastguard Worker u32 blk_cnt = 0;
2174*59bfda1fSAndroid Build Coastguard Worker struct f2fs_compr_blk_cnt cbc = {0, CHEADER_PGOFS_NONE};
2175*59bfda1fSAndroid Build Coastguard Worker block_t start_blk, orphan_blkaddr, i, j;
2176*59bfda1fSAndroid Build Coastguard Worker struct f2fs_orphan_block *orphan_blk, *new_blk;
2177*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
2178*59bfda1fSAndroid Build Coastguard Worker u32 entry_count;
2179*59bfda1fSAndroid Build Coastguard Worker
2180*59bfda1fSAndroid Build Coastguard Worker if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
2181*59bfda1fSAndroid Build Coastguard Worker return 0;
2182*59bfda1fSAndroid Build Coastguard Worker
2183*59bfda1fSAndroid Build Coastguard Worker start_blk = __start_cp_addr(sbi) + 1 + get_sb(cp_payload);
2184*59bfda1fSAndroid Build Coastguard Worker orphan_blkaddr = __start_sum_addr(sbi) - 1 - get_sb(cp_payload);
2185*59bfda1fSAndroid Build Coastguard Worker
2186*59bfda1fSAndroid Build Coastguard Worker f2fs_ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP);
2187*59bfda1fSAndroid Build Coastguard Worker
2188*59bfda1fSAndroid Build Coastguard Worker orphan_blk = calloc(F2FS_BLKSIZE, 1);
2189*59bfda1fSAndroid Build Coastguard Worker ASSERT(orphan_blk);
2190*59bfda1fSAndroid Build Coastguard Worker
2191*59bfda1fSAndroid Build Coastguard Worker new_blk = calloc(F2FS_BLKSIZE, 1);
2192*59bfda1fSAndroid Build Coastguard Worker ASSERT(new_blk);
2193*59bfda1fSAndroid Build Coastguard Worker
2194*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < orphan_blkaddr; i++) {
2195*59bfda1fSAndroid Build Coastguard Worker int ret = dev_read_block(orphan_blk, start_blk + i);
2196*59bfda1fSAndroid Build Coastguard Worker u32 new_entry_count = 0;
2197*59bfda1fSAndroid Build Coastguard Worker
2198*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2199*59bfda1fSAndroid Build Coastguard Worker entry_count = le32_to_cpu(F2FS_ORPHAN_BLOCK_FOOTER(orphan_blk)->entry_count);
2200*59bfda1fSAndroid Build Coastguard Worker
2201*59bfda1fSAndroid Build Coastguard Worker for (j = 0; j < entry_count; j++) {
2202*59bfda1fSAndroid Build Coastguard Worker nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
2203*59bfda1fSAndroid Build Coastguard Worker DBG(1, "[%3d] ino [0x%x]\n", i, ino);
2204*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
2205*59bfda1fSAndroid Build Coastguard Worker blk_cnt = 1;
2206*59bfda1fSAndroid Build Coastguard Worker cbc.cnt = 0;
2207*59bfda1fSAndroid Build Coastguard Worker cbc.cheader_pgofs = CHEADER_PGOFS_NONE;
2208*59bfda1fSAndroid Build Coastguard Worker
2209*59bfda1fSAndroid Build Coastguard Worker if (c.preen_mode == PREEN_MODE_1 && !c.fix_on) {
2210*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, ino, &ni);
2211*59bfda1fSAndroid Build Coastguard Worker if (!IS_VALID_NID(sbi, ino) ||
2212*59bfda1fSAndroid Build Coastguard Worker !f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
2213*59bfda1fSAndroid Build Coastguard Worker DATA_GENERIC)) {
2214*59bfda1fSAndroid Build Coastguard Worker free(orphan_blk);
2215*59bfda1fSAndroid Build Coastguard Worker free(new_blk);
2216*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2217*59bfda1fSAndroid Build Coastguard Worker }
2218*59bfda1fSAndroid Build Coastguard Worker
2219*59bfda1fSAndroid Build Coastguard Worker continue;
2220*59bfda1fSAndroid Build Coastguard Worker }
2221*59bfda1fSAndroid Build Coastguard Worker
2222*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_node_blk(sbi, NULL, ino,
2223*59bfda1fSAndroid Build Coastguard Worker F2FS_FT_ORPHAN, TYPE_INODE, &blk_cnt,
2224*59bfda1fSAndroid Build Coastguard Worker &cbc, NULL);
2225*59bfda1fSAndroid Build Coastguard Worker if (!ret)
2226*59bfda1fSAndroid Build Coastguard Worker new_blk->ino[new_entry_count++] =
2227*59bfda1fSAndroid Build Coastguard Worker orphan_blk->ino[j];
2228*59bfda1fSAndroid Build Coastguard Worker else if (ret && c.fix_on)
2229*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("[0x%x] remove from orphan list", ino);
2230*59bfda1fSAndroid Build Coastguard Worker else if (ret)
2231*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("[0x%x] wrong orphan inode", ino);
2232*59bfda1fSAndroid Build Coastguard Worker }
2233*59bfda1fSAndroid Build Coastguard Worker if (f2fs_dev_is_writable() && c.fix_on &&
2234*59bfda1fSAndroid Build Coastguard Worker entry_count != new_entry_count) {
2235*59bfda1fSAndroid Build Coastguard Worker F2FS_ORPHAN_BLOCK_FOOTER(new_blk)->entry_count = cpu_to_le32(new_entry_count);
2236*59bfda1fSAndroid Build Coastguard Worker ret = dev_write_block(new_blk, start_blk + i,
2237*59bfda1fSAndroid Build Coastguard Worker WRITE_LIFE_NONE);
2238*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2239*59bfda1fSAndroid Build Coastguard Worker }
2240*59bfda1fSAndroid Build Coastguard Worker memset(orphan_blk, 0, F2FS_BLKSIZE);
2241*59bfda1fSAndroid Build Coastguard Worker memset(new_blk, 0, F2FS_BLKSIZE);
2242*59bfda1fSAndroid Build Coastguard Worker }
2243*59bfda1fSAndroid Build Coastguard Worker free(orphan_blk);
2244*59bfda1fSAndroid Build Coastguard Worker free(new_blk);
2245*59bfda1fSAndroid Build Coastguard Worker
2246*59bfda1fSAndroid Build Coastguard Worker return 0;
2247*59bfda1fSAndroid Build Coastguard Worker }
2248*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_quota_node(struct f2fs_sb_info * sbi)2249*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
2250*59bfda1fSAndroid Build Coastguard Worker {
2251*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
2252*59bfda1fSAndroid Build Coastguard Worker enum quota_type qtype;
2253*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
2254*59bfda1fSAndroid Build Coastguard Worker u32 blk_cnt = 0;
2255*59bfda1fSAndroid Build Coastguard Worker struct f2fs_compr_blk_cnt cbc = {0, CHEADER_PGOFS_NONE};
2256*59bfda1fSAndroid Build Coastguard Worker
2257*59bfda1fSAndroid Build Coastguard Worker for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
2258*59bfda1fSAndroid Build Coastguard Worker cur_qtype = qtype;
2259*59bfda1fSAndroid Build Coastguard Worker if (sb->qf_ino[qtype] == 0)
2260*59bfda1fSAndroid Build Coastguard Worker continue;
2261*59bfda1fSAndroid Build Coastguard Worker nid_t ino = QUOTA_INO(sb, qtype);
2262*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
2263*59bfda1fSAndroid Build Coastguard Worker
2264*59bfda1fSAndroid Build Coastguard Worker DBG(1, "qtype [%d] ino [0x%x]\n", qtype, ino);
2265*59bfda1fSAndroid Build Coastguard Worker blk_cnt = 1;
2266*59bfda1fSAndroid Build Coastguard Worker cbc.cnt = 0;
2267*59bfda1fSAndroid Build Coastguard Worker cbc.cheader_pgofs = CHEADER_PGOFS_NONE;
2268*59bfda1fSAndroid Build Coastguard Worker
2269*59bfda1fSAndroid Build Coastguard Worker if (c.preen_mode == PREEN_MODE_1 && !c.fix_on) {
2270*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, ino, &ni);
2271*59bfda1fSAndroid Build Coastguard Worker if (!IS_VALID_NID(sbi, ino) ||
2272*59bfda1fSAndroid Build Coastguard Worker !f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
2273*59bfda1fSAndroid Build Coastguard Worker DATA_GENERIC))
2274*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2275*59bfda1fSAndroid Build Coastguard Worker continue;
2276*59bfda1fSAndroid Build Coastguard Worker }
2277*59bfda1fSAndroid Build Coastguard Worker ret = fsck_chk_node_blk(sbi, NULL, ino,
2278*59bfda1fSAndroid Build Coastguard Worker F2FS_FT_REG_FILE, TYPE_INODE, &blk_cnt,
2279*59bfda1fSAndroid Build Coastguard Worker &cbc, NULL);
2280*59bfda1fSAndroid Build Coastguard Worker if (ret) {
2281*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("wrong quota inode, qtype [%d] ino [0x%x]",
2282*59bfda1fSAndroid Build Coastguard Worker qtype, ino);
2283*59bfda1fSAndroid Build Coastguard Worker qf_szchk_type[qtype] = QF_SZCHK_ERR;
2284*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on)
2285*59bfda1fSAndroid Build Coastguard Worker f2fs_rebuild_qf_inode(sbi, qtype);
2286*59bfda1fSAndroid Build Coastguard Worker }
2287*59bfda1fSAndroid Build Coastguard Worker }
2288*59bfda1fSAndroid Build Coastguard Worker cur_qtype = -1;
2289*59bfda1fSAndroid Build Coastguard Worker return ret;
2290*59bfda1fSAndroid Build Coastguard Worker }
2291*59bfda1fSAndroid Build Coastguard Worker
2292*59bfda1fSAndroid Build Coastguard Worker static void fsck_disconnect_file(struct f2fs_sb_info *sbi, nid_t ino,
2293*59bfda1fSAndroid Build Coastguard Worker bool dealloc);
2294*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_quota_files(struct f2fs_sb_info * sbi)2295*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
2296*59bfda1fSAndroid Build Coastguard Worker {
2297*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2298*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
2299*59bfda1fSAndroid Build Coastguard Worker enum quota_type qtype;
2300*59bfda1fSAndroid Build Coastguard Worker f2fs_ino_t ino;
2301*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
2302*59bfda1fSAndroid Build Coastguard Worker int needs_writeout;
2303*59bfda1fSAndroid Build Coastguard Worker
2304*59bfda1fSAndroid Build Coastguard Worker /* Return if quota feature is disabled */
2305*59bfda1fSAndroid Build Coastguard Worker if (!fsck->qctx)
2306*59bfda1fSAndroid Build Coastguard Worker return 0;
2307*59bfda1fSAndroid Build Coastguard Worker
2308*59bfda1fSAndroid Build Coastguard Worker for (qtype = 0; qtype < F2FS_MAX_QUOTAS; qtype++) {
2309*59bfda1fSAndroid Build Coastguard Worker ino = sb->qf_ino[qtype];
2310*59bfda1fSAndroid Build Coastguard Worker if (!ino)
2311*59bfda1fSAndroid Build Coastguard Worker continue;
2312*59bfda1fSAndroid Build Coastguard Worker
2313*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Checking Quota file ([%3d] ino [0x%x])\n", qtype, ino);
2314*59bfda1fSAndroid Build Coastguard Worker needs_writeout = 0;
2315*59bfda1fSAndroid Build Coastguard Worker ret = quota_compare_and_update(sbi, qtype, &needs_writeout,
2316*59bfda1fSAndroid Build Coastguard Worker c.preserve_limits);
2317*59bfda1fSAndroid Build Coastguard Worker if (ret == 0 && needs_writeout == 0) {
2318*59bfda1fSAndroid Build Coastguard Worker DBG(1, "OK\n");
2319*59bfda1fSAndroid Build Coastguard Worker continue;
2320*59bfda1fSAndroid Build Coastguard Worker }
2321*59bfda1fSAndroid Build Coastguard Worker
2322*59bfda1fSAndroid Build Coastguard Worker /* Something is wrong */
2323*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
2324*59bfda1fSAndroid Build Coastguard Worker DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
2325*59bfda1fSAndroid Build Coastguard Worker qtype, ino);
2326*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file(sbi, ino, true);
2327*59bfda1fSAndroid Build Coastguard Worker f2fs_rebuild_qf_inode(sbi, qtype);
2328*59bfda1fSAndroid Build Coastguard Worker f2fs_filesize_update(sbi, ino, 0);
2329*59bfda1fSAndroid Build Coastguard Worker ret = quota_write_inode(sbi, qtype);
2330*59bfda1fSAndroid Build Coastguard Worker if (!ret) {
2331*59bfda1fSAndroid Build Coastguard Worker c.quota_fixed = true;
2332*59bfda1fSAndroid Build Coastguard Worker DBG(1, "OK\n");
2333*59bfda1fSAndroid Build Coastguard Worker } else {
2334*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Unable to write quota file");
2335*59bfda1fSAndroid Build Coastguard Worker }
2336*59bfda1fSAndroid Build Coastguard Worker } else {
2337*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Quota file is missing or invalid"
2338*59bfda1fSAndroid Build Coastguard Worker " quota file content found.");
2339*59bfda1fSAndroid Build Coastguard Worker }
2340*59bfda1fSAndroid Build Coastguard Worker }
2341*59bfda1fSAndroid Build Coastguard Worker return ret;
2342*59bfda1fSAndroid Build Coastguard Worker }
2343*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_meta(struct f2fs_sb_info * sbi)2344*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_meta(struct f2fs_sb_info *sbi)
2345*59bfda1fSAndroid Build Coastguard Worker {
2346*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2347*59bfda1fSAndroid Build Coastguard Worker struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
2348*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
2349*59bfda1fSAndroid Build Coastguard Worker unsigned int sit_valid_segs = 0, sit_node_blks = 0;
2350*59bfda1fSAndroid Build Coastguard Worker unsigned int i;
2351*59bfda1fSAndroid Build Coastguard Worker
2352*59bfda1fSAndroid Build Coastguard Worker /* 1. check sit usage with CP: curseg is lost? */
2353*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < MAIN_SEGS(sbi); i++) {
2354*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, i);
2355*59bfda1fSAndroid Build Coastguard Worker if (se->valid_blocks != 0)
2356*59bfda1fSAndroid Build Coastguard Worker sit_valid_segs++;
2357*59bfda1fSAndroid Build Coastguard Worker else if (IS_CUR_SEGNO(sbi, i)) {
2358*59bfda1fSAndroid Build Coastguard Worker /* curseg has not been written back to device */
2359*59bfda1fSAndroid Build Coastguard Worker MSG(1, "\tInfo: curseg %u is counted in valid segs\n", i);
2360*59bfda1fSAndroid Build Coastguard Worker sit_valid_segs++;
2361*59bfda1fSAndroid Build Coastguard Worker }
2362*59bfda1fSAndroid Build Coastguard Worker if (IS_NODESEG(se->type))
2363*59bfda1fSAndroid Build Coastguard Worker sit_node_blks += se->valid_blocks;
2364*59bfda1fSAndroid Build Coastguard Worker }
2365*59bfda1fSAndroid Build Coastguard Worker if (fsck->chk.sit_free_segs + sit_valid_segs !=
2366*59bfda1fSAndroid Build Coastguard Worker get_usable_seg_count(sbi)) {
2367*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("SIT usage does not match: sit_free_segs %u, "
2368*59bfda1fSAndroid Build Coastguard Worker "sit_valid_segs %u, total_segs %u",
2369*59bfda1fSAndroid Build Coastguard Worker fsck->chk.sit_free_segs, sit_valid_segs,
2370*59bfda1fSAndroid Build Coastguard Worker get_usable_seg_count(sbi));
2371*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2372*59bfda1fSAndroid Build Coastguard Worker }
2373*59bfda1fSAndroid Build Coastguard Worker
2374*59bfda1fSAndroid Build Coastguard Worker /* 2. check node count */
2375*59bfda1fSAndroid Build Coastguard Worker if (fsck->chk.valid_nat_entry_cnt != sit_node_blks) {
2376*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("node count does not match: valid_nat_entry_cnt %u,"
2377*59bfda1fSAndroid Build Coastguard Worker " sit_node_blks %u",
2378*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_nat_entry_cnt, sit_node_blks);
2379*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2380*59bfda1fSAndroid Build Coastguard Worker }
2381*59bfda1fSAndroid Build Coastguard Worker
2382*59bfda1fSAndroid Build Coastguard Worker /* 3. check SIT with CP */
2383*59bfda1fSAndroid Build Coastguard Worker if (fsck->chk.sit_free_segs != le32_to_cpu(cp->free_segment_count)) {
2384*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("free segs does not match: sit_free_segs %u, "
2385*59bfda1fSAndroid Build Coastguard Worker "free_segment_count %u",
2386*59bfda1fSAndroid Build Coastguard Worker fsck->chk.sit_free_segs,
2387*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(cp->free_segment_count));
2388*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2389*59bfda1fSAndroid Build Coastguard Worker }
2390*59bfda1fSAndroid Build Coastguard Worker
2391*59bfda1fSAndroid Build Coastguard Worker /* 4. check NAT with CP */
2392*59bfda1fSAndroid Build Coastguard Worker if (fsck->chk.valid_nat_entry_cnt !=
2393*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(cp->valid_node_count)) {
2394*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("valid node does not match: valid_nat_entry_cnt %u,"
2395*59bfda1fSAndroid Build Coastguard Worker " valid_node_count %u",
2396*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_nat_entry_cnt,
2397*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(cp->valid_node_count));
2398*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2399*59bfda1fSAndroid Build Coastguard Worker }
2400*59bfda1fSAndroid Build Coastguard Worker
2401*59bfda1fSAndroid Build Coastguard Worker /* 4. check orphan inode simply */
2402*59bfda1fSAndroid Build Coastguard Worker if (fsck_chk_orphan_node(sbi))
2403*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2404*59bfda1fSAndroid Build Coastguard Worker
2405*59bfda1fSAndroid Build Coastguard Worker /* 5. check nat entry -- must be done before quota check */
2406*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < fsck->nr_nat_entries; i++) {
2407*59bfda1fSAndroid Build Coastguard Worker u32 blk = le32_to_cpu(fsck->entries[i].block_addr);
2408*59bfda1fSAndroid Build Coastguard Worker nid_t ino = le32_to_cpu(fsck->entries[i].ino);
2409*59bfda1fSAndroid Build Coastguard Worker
2410*59bfda1fSAndroid Build Coastguard Worker if (!blk)
2411*59bfda1fSAndroid Build Coastguard Worker /*
2412*59bfda1fSAndroid Build Coastguard Worker * skip entry whose ino is 0, otherwise, we will
2413*59bfda1fSAndroid Build Coastguard Worker * get a negative number by BLKOFF_FROM_MAIN(sbi, blk)
2414*59bfda1fSAndroid Build Coastguard Worker */
2415*59bfda1fSAndroid Build Coastguard Worker continue;
2416*59bfda1fSAndroid Build Coastguard Worker
2417*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_is_valid_blkaddr(sbi, blk, DATA_GENERIC)) {
2418*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: nat entry[ino %u block_addr 0x%x]"
2419*59bfda1fSAndroid Build Coastguard Worker " is in valid\n",
2420*59bfda1fSAndroid Build Coastguard Worker ino, blk);
2421*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2422*59bfda1fSAndroid Build Coastguard Worker }
2423*59bfda1fSAndroid Build Coastguard Worker
2424*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_test_sit_bitmap(sbi, blk)) {
2425*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: nat entry[ino %u block_addr 0x%x]"
2426*59bfda1fSAndroid Build Coastguard Worker " not find it in sit_area_bitmap\n",
2427*59bfda1fSAndroid Build Coastguard Worker ino, blk);
2428*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2429*59bfda1fSAndroid Build Coastguard Worker }
2430*59bfda1fSAndroid Build Coastguard Worker
2431*59bfda1fSAndroid Build Coastguard Worker if (!IS_VALID_NID(sbi, ino)) {
2432*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: nat_entry->ino %u exceeds the range"
2433*59bfda1fSAndroid Build Coastguard Worker " of nat entries %u\n",
2434*59bfda1fSAndroid Build Coastguard Worker ino, fsck->nr_nat_entries);
2435*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2436*59bfda1fSAndroid Build Coastguard Worker }
2437*59bfda1fSAndroid Build Coastguard Worker
2438*59bfda1fSAndroid Build Coastguard Worker if (!f2fs_test_bit(ino, fsck->nat_area_bitmap)) {
2439*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: nat_entry->ino %u is not set in"
2440*59bfda1fSAndroid Build Coastguard Worker " nat_area_bitmap\n", ino);
2441*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2442*59bfda1fSAndroid Build Coastguard Worker }
2443*59bfda1fSAndroid Build Coastguard Worker }
2444*59bfda1fSAndroid Build Coastguard Worker
2445*59bfda1fSAndroid Build Coastguard Worker /* 6. check quota inode simply */
2446*59bfda1fSAndroid Build Coastguard Worker if (fsck_chk_quota_node(sbi))
2447*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2448*59bfda1fSAndroid Build Coastguard Worker
2449*59bfda1fSAndroid Build Coastguard Worker if (fsck->nat_valid_inode_cnt != le32_to_cpu(cp->valid_inode_count)) {
2450*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("valid inode does not match: nat_valid_inode_cnt %u,"
2451*59bfda1fSAndroid Build Coastguard Worker " valid_inode_count %u",
2452*59bfda1fSAndroid Build Coastguard Worker fsck->nat_valid_inode_cnt,
2453*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(cp->valid_inode_count));
2454*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2455*59bfda1fSAndroid Build Coastguard Worker }
2456*59bfda1fSAndroid Build Coastguard Worker
2457*59bfda1fSAndroid Build Coastguard Worker return 0;
2458*59bfda1fSAndroid Build Coastguard Worker }
2459*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_checkpoint(struct f2fs_sb_info * sbi)2460*59bfda1fSAndroid Build Coastguard Worker void fsck_chk_checkpoint(struct f2fs_sb_info *sbi)
2461*59bfda1fSAndroid Build Coastguard Worker {
2462*59bfda1fSAndroid Build Coastguard Worker struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
2463*59bfda1fSAndroid Build Coastguard Worker
2464*59bfda1fSAndroid Build Coastguard Worker if (get_cp(ckpt_flags) & CP_LARGE_NAT_BITMAP_FLAG) {
2465*59bfda1fSAndroid Build Coastguard Worker if (get_cp(checksum_offset) != CP_MIN_CHKSUM_OFFSET) {
2466*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Deprecated layout of large_nat_bitmap, "
2467*59bfda1fSAndroid Build Coastguard Worker "chksum_offset:%u", get_cp(checksum_offset));
2468*59bfda1fSAndroid Build Coastguard Worker c.fix_chksum = 1;
2469*59bfda1fSAndroid Build Coastguard Worker }
2470*59bfda1fSAndroid Build Coastguard Worker }
2471*59bfda1fSAndroid Build Coastguard Worker }
2472*59bfda1fSAndroid Build Coastguard Worker
fsck_init(struct f2fs_sb_info * sbi)2473*59bfda1fSAndroid Build Coastguard Worker void fsck_init(struct f2fs_sb_info *sbi)
2474*59bfda1fSAndroid Build Coastguard Worker {
2475*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2476*59bfda1fSAndroid Build Coastguard Worker struct f2fs_sm_info *sm_i = SM_I(sbi);
2477*59bfda1fSAndroid Build Coastguard Worker
2478*59bfda1fSAndroid Build Coastguard Worker /*
2479*59bfda1fSAndroid Build Coastguard Worker * We build three bitmap for main/sit/nat so that may check consistency
2480*59bfda1fSAndroid Build Coastguard Worker * of filesystem.
2481*59bfda1fSAndroid Build Coastguard Worker * 1. main_area_bitmap will be used to check whether all blocks of main
2482*59bfda1fSAndroid Build Coastguard Worker * area is used or not.
2483*59bfda1fSAndroid Build Coastguard Worker * 2. nat_area_bitmap has bitmap information of used nid in NAT.
2484*59bfda1fSAndroid Build Coastguard Worker * 3. sit_area_bitmap has bitmap information of used main block.
2485*59bfda1fSAndroid Build Coastguard Worker * At Last sequence, we compare main_area_bitmap with sit_area_bitmap.
2486*59bfda1fSAndroid Build Coastguard Worker */
2487*59bfda1fSAndroid Build Coastguard Worker fsck->nr_main_blks = sm_i->main_segments << sbi->log_blocks_per_seg;
2488*59bfda1fSAndroid Build Coastguard Worker fsck->main_area_bitmap_sz = (fsck->nr_main_blks + 7) / 8;
2489*59bfda1fSAndroid Build Coastguard Worker fsck->main_area_bitmap = calloc(fsck->main_area_bitmap_sz, 1);
2490*59bfda1fSAndroid Build Coastguard Worker ASSERT(fsck->main_area_bitmap != NULL);
2491*59bfda1fSAndroid Build Coastguard Worker
2492*59bfda1fSAndroid Build Coastguard Worker build_nat_area_bitmap(sbi);
2493*59bfda1fSAndroid Build Coastguard Worker
2494*59bfda1fSAndroid Build Coastguard Worker build_sit_area_bitmap(sbi);
2495*59bfda1fSAndroid Build Coastguard Worker
2496*59bfda1fSAndroid Build Coastguard Worker ASSERT(tree_mark_size != 0);
2497*59bfda1fSAndroid Build Coastguard Worker tree_mark = calloc(tree_mark_size, 1);
2498*59bfda1fSAndroid Build Coastguard Worker ASSERT(tree_mark != NULL);
2499*59bfda1fSAndroid Build Coastguard Worker fsck->dentry = calloc(sizeof(struct f2fs_dentry), 1);
2500*59bfda1fSAndroid Build Coastguard Worker ASSERT(fsck->dentry != NULL);
2501*59bfda1fSAndroid Build Coastguard Worker memcpy(fsck->dentry->name, "/", 1);
2502*59bfda1fSAndroid Build Coastguard Worker fsck->dentry_end = fsck->dentry;
2503*59bfda1fSAndroid Build Coastguard Worker
2504*59bfda1fSAndroid Build Coastguard Worker c.quota_fixed = false;
2505*59bfda1fSAndroid Build Coastguard Worker }
2506*59bfda1fSAndroid Build Coastguard Worker
fix_hard_links(struct f2fs_sb_info * sbi)2507*59bfda1fSAndroid Build Coastguard Worker static void fix_hard_links(struct f2fs_sb_info *sbi)
2508*59bfda1fSAndroid Build Coastguard Worker {
2509*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2510*59bfda1fSAndroid Build Coastguard Worker struct hard_link_node *tmp, *node;
2511*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node_blk = NULL;
2512*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
2513*59bfda1fSAndroid Build Coastguard Worker int ret;
2514*59bfda1fSAndroid Build Coastguard Worker
2515*59bfda1fSAndroid Build Coastguard Worker if (fsck->hard_link_list_head == NULL)
2516*59bfda1fSAndroid Build Coastguard Worker return;
2517*59bfda1fSAndroid Build Coastguard Worker
2518*59bfda1fSAndroid Build Coastguard Worker node_blk = (struct f2fs_node *)calloc(F2FS_BLKSIZE, 1);
2519*59bfda1fSAndroid Build Coastguard Worker ASSERT(node_blk != NULL);
2520*59bfda1fSAndroid Build Coastguard Worker
2521*59bfda1fSAndroid Build Coastguard Worker node = fsck->hard_link_list_head;
2522*59bfda1fSAndroid Build Coastguard Worker while (node) {
2523*59bfda1fSAndroid Build Coastguard Worker /* Sanity check */
2524*59bfda1fSAndroid Build Coastguard Worker if (sanity_check_nid(sbi, node->nid, node_blk,
2525*59bfda1fSAndroid Build Coastguard Worker F2FS_FT_MAX, TYPE_INODE, &ni))
2526*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Failed to fix, rerun fsck.f2fs");
2527*59bfda1fSAndroid Build Coastguard Worker
2528*59bfda1fSAndroid Build Coastguard Worker node_blk->i.i_links = cpu_to_le32(node->actual_links);
2529*59bfda1fSAndroid Build Coastguard Worker
2530*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("File: 0x%x i_links= 0x%x -> 0x%x",
2531*59bfda1fSAndroid Build Coastguard Worker node->nid, node->links, node->actual_links);
2532*59bfda1fSAndroid Build Coastguard Worker
2533*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, node_blk, &ni.blk_addr, NULL);
2534*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2535*59bfda1fSAndroid Build Coastguard Worker tmp = node;
2536*59bfda1fSAndroid Build Coastguard Worker node = node->next;
2537*59bfda1fSAndroid Build Coastguard Worker free(tmp);
2538*59bfda1fSAndroid Build Coastguard Worker }
2539*59bfda1fSAndroid Build Coastguard Worker free(node_blk);
2540*59bfda1fSAndroid Build Coastguard Worker }
2541*59bfda1fSAndroid Build Coastguard Worker
fix_nat_entries(struct f2fs_sb_info * sbi)2542*59bfda1fSAndroid Build Coastguard Worker static void fix_nat_entries(struct f2fs_sb_info *sbi)
2543*59bfda1fSAndroid Build Coastguard Worker {
2544*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2545*59bfda1fSAndroid Build Coastguard Worker u32 i;
2546*59bfda1fSAndroid Build Coastguard Worker
2547*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < fsck->nr_nat_entries; i++)
2548*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0)
2549*59bfda1fSAndroid Build Coastguard Worker nullify_nat_entry(sbi, i);
2550*59bfda1fSAndroid Build Coastguard Worker }
2551*59bfda1fSAndroid Build Coastguard Worker
flush_curseg_sit_entries(struct f2fs_sb_info * sbi)2552*59bfda1fSAndroid Build Coastguard Worker static void flush_curseg_sit_entries(struct f2fs_sb_info *sbi)
2553*59bfda1fSAndroid Build Coastguard Worker {
2554*59bfda1fSAndroid Build Coastguard Worker struct sit_info *sit_i = SIT_I(sbi);
2555*59bfda1fSAndroid Build Coastguard Worker struct f2fs_sit_block *sit_blk;
2556*59bfda1fSAndroid Build Coastguard Worker int i;
2557*59bfda1fSAndroid Build Coastguard Worker
2558*59bfda1fSAndroid Build Coastguard Worker sit_blk = calloc(F2FS_BLKSIZE, 1);
2559*59bfda1fSAndroid Build Coastguard Worker ASSERT(sit_blk);
2560*59bfda1fSAndroid Build Coastguard Worker /* update curseg sit entries, since we may change
2561*59bfda1fSAndroid Build Coastguard Worker * a segment type in move_curseg_info
2562*59bfda1fSAndroid Build Coastguard Worker */
2563*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
2564*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *curseg = CURSEG_I(sbi, i);
2565*59bfda1fSAndroid Build Coastguard Worker struct f2fs_sit_entry *sit;
2566*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
2567*59bfda1fSAndroid Build Coastguard Worker
2568*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, curseg->segno);
2569*59bfda1fSAndroid Build Coastguard Worker get_current_sit_page(sbi, curseg->segno, sit_blk);
2570*59bfda1fSAndroid Build Coastguard Worker sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, curseg->segno)];
2571*59bfda1fSAndroid Build Coastguard Worker sit->vblocks = cpu_to_le16((se->type << SIT_VBLOCKS_SHIFT) |
2572*59bfda1fSAndroid Build Coastguard Worker se->valid_blocks);
2573*59bfda1fSAndroid Build Coastguard Worker rewrite_current_sit_page(sbi, curseg->segno, sit_blk);
2574*59bfda1fSAndroid Build Coastguard Worker }
2575*59bfda1fSAndroid Build Coastguard Worker
2576*59bfda1fSAndroid Build Coastguard Worker free(sit_blk);
2577*59bfda1fSAndroid Build Coastguard Worker }
2578*59bfda1fSAndroid Build Coastguard Worker
fix_checksum(struct f2fs_sb_info * sbi)2579*59bfda1fSAndroid Build Coastguard Worker static void fix_checksum(struct f2fs_sb_info *sbi)
2580*59bfda1fSAndroid Build Coastguard Worker {
2581*59bfda1fSAndroid Build Coastguard Worker struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
2582*59bfda1fSAndroid Build Coastguard Worker struct f2fs_nm_info *nm_i = NM_I(sbi);
2583*59bfda1fSAndroid Build Coastguard Worker struct sit_info *sit_i = SIT_I(sbi);
2584*59bfda1fSAndroid Build Coastguard Worker void *bitmap_offset;
2585*59bfda1fSAndroid Build Coastguard Worker
2586*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_chksum)
2587*59bfda1fSAndroid Build Coastguard Worker return;
2588*59bfda1fSAndroid Build Coastguard Worker
2589*59bfda1fSAndroid Build Coastguard Worker bitmap_offset = cp->sit_nat_version_bitmap + sizeof(__le32);
2590*59bfda1fSAndroid Build Coastguard Worker
2591*59bfda1fSAndroid Build Coastguard Worker memcpy(bitmap_offset, nm_i->nat_bitmap, nm_i->bitmap_size);
2592*59bfda1fSAndroid Build Coastguard Worker memcpy(bitmap_offset + nm_i->bitmap_size,
2593*59bfda1fSAndroid Build Coastguard Worker sit_i->sit_bitmap, sit_i->bitmap_size);
2594*59bfda1fSAndroid Build Coastguard Worker }
2595*59bfda1fSAndroid Build Coastguard Worker
fix_checkpoint(struct f2fs_sb_info * sbi)2596*59bfda1fSAndroid Build Coastguard Worker static void fix_checkpoint(struct f2fs_sb_info *sbi)
2597*59bfda1fSAndroid Build Coastguard Worker {
2598*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2599*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
2600*59bfda1fSAndroid Build Coastguard Worker struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
2601*59bfda1fSAndroid Build Coastguard Worker unsigned long long cp_blk_no;
2602*59bfda1fSAndroid Build Coastguard Worker u32 flags = c.alloc_failed ? CP_FSCK_FLAG :
2603*59bfda1fSAndroid Build Coastguard Worker (c.roll_forward ? 0 : CP_UMOUNT_FLAG);
2604*59bfda1fSAndroid Build Coastguard Worker block_t orphan_blks = 0;
2605*59bfda1fSAndroid Build Coastguard Worker block_t cp_blocks;
2606*59bfda1fSAndroid Build Coastguard Worker u32 i;
2607*59bfda1fSAndroid Build Coastguard Worker int ret;
2608*59bfda1fSAndroid Build Coastguard Worker uint32_t crc = 0;
2609*59bfda1fSAndroid Build Coastguard Worker
2610*59bfda1fSAndroid Build Coastguard Worker /* should call from fsck */
2611*59bfda1fSAndroid Build Coastguard Worker ASSERT(c.func == FSCK);
2612*59bfda1fSAndroid Build Coastguard Worker
2613*59bfda1fSAndroid Build Coastguard Worker if (is_set_ckpt_flags(cp, CP_ORPHAN_PRESENT_FLAG)) {
2614*59bfda1fSAndroid Build Coastguard Worker orphan_blks = __start_sum_addr(sbi) - 1;
2615*59bfda1fSAndroid Build Coastguard Worker flags |= CP_ORPHAN_PRESENT_FLAG;
2616*59bfda1fSAndroid Build Coastguard Worker }
2617*59bfda1fSAndroid Build Coastguard Worker if (is_set_ckpt_flags(cp, CP_TRIMMED_FLAG))
2618*59bfda1fSAndroid Build Coastguard Worker flags |= CP_TRIMMED_FLAG;
2619*59bfda1fSAndroid Build Coastguard Worker if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG))
2620*59bfda1fSAndroid Build Coastguard Worker flags |= CP_DISABLED_FLAG;
2621*59bfda1fSAndroid Build Coastguard Worker if (is_set_ckpt_flags(cp, CP_LARGE_NAT_BITMAP_FLAG)) {
2622*59bfda1fSAndroid Build Coastguard Worker flags |= CP_LARGE_NAT_BITMAP_FLAG;
2623*59bfda1fSAndroid Build Coastguard Worker set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET);
2624*59bfda1fSAndroid Build Coastguard Worker } else {
2625*59bfda1fSAndroid Build Coastguard Worker set_cp(checksum_offset, CP_CHKSUM_OFFSET);
2626*59bfda1fSAndroid Build Coastguard Worker }
2627*59bfda1fSAndroid Build Coastguard Worker
2628*59bfda1fSAndroid Build Coastguard Worker if (flags & CP_UMOUNT_FLAG)
2629*59bfda1fSAndroid Build Coastguard Worker cp_blocks = 8;
2630*59bfda1fSAndroid Build Coastguard Worker else
2631*59bfda1fSAndroid Build Coastguard Worker cp_blocks = 5;
2632*59bfda1fSAndroid Build Coastguard Worker
2633*59bfda1fSAndroid Build Coastguard Worker set_cp(cp_pack_total_block_count, cp_blocks +
2634*59bfda1fSAndroid Build Coastguard Worker orphan_blks + get_sb(cp_payload));
2635*59bfda1fSAndroid Build Coastguard Worker
2636*59bfda1fSAndroid Build Coastguard Worker flags = update_nat_bits_flags(sb, cp, flags);
2637*59bfda1fSAndroid Build Coastguard Worker flags |= CP_NOCRC_RECOVERY_FLAG;
2638*59bfda1fSAndroid Build Coastguard Worker set_cp(ckpt_flags, flags);
2639*59bfda1fSAndroid Build Coastguard Worker
2640*59bfda1fSAndroid Build Coastguard Worker set_cp(free_segment_count, get_free_segments(sbi));
2641*59bfda1fSAndroid Build Coastguard Worker set_cp(valid_block_count, fsck->chk.valid_blk_cnt);
2642*59bfda1fSAndroid Build Coastguard Worker set_cp(valid_node_count, fsck->chk.valid_node_cnt);
2643*59bfda1fSAndroid Build Coastguard Worker set_cp(valid_inode_count, fsck->chk.valid_inode_cnt);
2644*59bfda1fSAndroid Build Coastguard Worker
2645*59bfda1fSAndroid Build Coastguard Worker crc = f2fs_checkpoint_chksum(cp);
2646*59bfda1fSAndroid Build Coastguard Worker *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) =
2647*59bfda1fSAndroid Build Coastguard Worker cpu_to_le32(crc);
2648*59bfda1fSAndroid Build Coastguard Worker
2649*59bfda1fSAndroid Build Coastguard Worker cp_blk_no = get_sb(cp_blkaddr);
2650*59bfda1fSAndroid Build Coastguard Worker if (sbi->cur_cp == 2)
2651*59bfda1fSAndroid Build Coastguard Worker cp_blk_no += 1 << get_sb(log_blocks_per_seg);
2652*59bfda1fSAndroid Build Coastguard Worker
2653*59bfda1fSAndroid Build Coastguard Worker ret = dev_write_block(cp, cp_blk_no++, WRITE_LIFE_NONE);
2654*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2655*59bfda1fSAndroid Build Coastguard Worker
2656*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < get_sb(cp_payload); i++) {
2657*59bfda1fSAndroid Build Coastguard Worker ret = dev_write_block(((unsigned char *)cp) +
2658*59bfda1fSAndroid Build Coastguard Worker (i + 1) * F2FS_BLKSIZE, cp_blk_no++,
2659*59bfda1fSAndroid Build Coastguard Worker WRITE_LIFE_NONE);
2660*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2661*59bfda1fSAndroid Build Coastguard Worker }
2662*59bfda1fSAndroid Build Coastguard Worker
2663*59bfda1fSAndroid Build Coastguard Worker cp_blk_no += orphan_blks;
2664*59bfda1fSAndroid Build Coastguard Worker
2665*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
2666*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *curseg = CURSEG_I(sbi, i);
2667*59bfda1fSAndroid Build Coastguard Worker
2668*59bfda1fSAndroid Build Coastguard Worker if (!(flags & CP_UMOUNT_FLAG) && IS_NODESEG(i))
2669*59bfda1fSAndroid Build Coastguard Worker continue;
2670*59bfda1fSAndroid Build Coastguard Worker
2671*59bfda1fSAndroid Build Coastguard Worker ret = dev_write_block(curseg->sum_blk, cp_blk_no++,
2672*59bfda1fSAndroid Build Coastguard Worker WRITE_LIFE_NONE);
2673*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2674*59bfda1fSAndroid Build Coastguard Worker }
2675*59bfda1fSAndroid Build Coastguard Worker
2676*59bfda1fSAndroid Build Coastguard Worker /* Write nat bits */
2677*59bfda1fSAndroid Build Coastguard Worker if (flags & CP_NAT_BITS_FLAG)
2678*59bfda1fSAndroid Build Coastguard Worker write_nat_bits(sbi, sb, cp, sbi->cur_cp);
2679*59bfda1fSAndroid Build Coastguard Worker
2680*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_fsync_device();
2681*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2682*59bfda1fSAndroid Build Coastguard Worker
2683*59bfda1fSAndroid Build Coastguard Worker ret = dev_write_block(cp, cp_blk_no++, WRITE_LIFE_NONE);
2684*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2685*59bfda1fSAndroid Build Coastguard Worker
2686*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_fsync_device();
2687*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2688*59bfda1fSAndroid Build Coastguard Worker
2689*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: fix_checkpoint() cur_cp:%d\n", sbi->cur_cp);
2690*59bfda1fSAndroid Build Coastguard Worker }
2691*59bfda1fSAndroid Build Coastguard Worker
fix_checkpoints(struct f2fs_sb_info * sbi)2692*59bfda1fSAndroid Build Coastguard Worker static void fix_checkpoints(struct f2fs_sb_info *sbi)
2693*59bfda1fSAndroid Build Coastguard Worker {
2694*59bfda1fSAndroid Build Coastguard Worker /* copy valid checkpoint to its mirror position */
2695*59bfda1fSAndroid Build Coastguard Worker duplicate_checkpoint(sbi);
2696*59bfda1fSAndroid Build Coastguard Worker
2697*59bfda1fSAndroid Build Coastguard Worker /* repair checkpoint at CP #0 position */
2698*59bfda1fSAndroid Build Coastguard Worker sbi->cur_cp = 1;
2699*59bfda1fSAndroid Build Coastguard Worker fix_checkpoint(sbi);
2700*59bfda1fSAndroid Build Coastguard Worker }
2701*59bfda1fSAndroid Build Coastguard Worker
2702*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_BLKZONED_H
2703*59bfda1fSAndroid Build Coastguard Worker
2704*59bfda1fSAndroid Build Coastguard Worker /*
2705*59bfda1fSAndroid Build Coastguard Worker * Refer valid block map and return offset of the last valid block in the zone.
2706*59bfda1fSAndroid Build Coastguard Worker * Obtain valid block map from SIT and fsync data.
2707*59bfda1fSAndroid Build Coastguard Worker * If there is no valid block in the zone, return -1.
2708*59bfda1fSAndroid Build Coastguard Worker */
last_vblk_off_in_zone(struct f2fs_sb_info * sbi,unsigned int zone_segno)2709*59bfda1fSAndroid Build Coastguard Worker static int last_vblk_off_in_zone(struct f2fs_sb_info *sbi,
2710*59bfda1fSAndroid Build Coastguard Worker unsigned int zone_segno)
2711*59bfda1fSAndroid Build Coastguard Worker {
2712*59bfda1fSAndroid Build Coastguard Worker int s, b;
2713*59bfda1fSAndroid Build Coastguard Worker unsigned int segs_per_zone = sbi->segs_per_sec * sbi->secs_per_zone;
2714*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
2715*59bfda1fSAndroid Build Coastguard Worker
2716*59bfda1fSAndroid Build Coastguard Worker for (s = segs_per_zone - 1; s >= 0; s--) {
2717*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, zone_segno + s);
2718*59bfda1fSAndroid Build Coastguard Worker
2719*59bfda1fSAndroid Build Coastguard Worker for (b = sbi->blocks_per_seg - 1; b >= 0; b--)
2720*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(b, (const char *)se->cur_valid_map))
2721*59bfda1fSAndroid Build Coastguard Worker return b + (s << sbi->log_blocks_per_seg);
2722*59bfda1fSAndroid Build Coastguard Worker }
2723*59bfda1fSAndroid Build Coastguard Worker
2724*59bfda1fSAndroid Build Coastguard Worker return -1;
2725*59bfda1fSAndroid Build Coastguard Worker }
2726*59bfda1fSAndroid Build Coastguard Worker
check_curseg_write_pointer(struct f2fs_sb_info * sbi,int type)2727*59bfda1fSAndroid Build Coastguard Worker static int check_curseg_write_pointer(struct f2fs_sb_info *sbi, int type)
2728*59bfda1fSAndroid Build Coastguard Worker {
2729*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *curseg = CURSEG_I(sbi, type);
2730*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
2731*59bfda1fSAndroid Build Coastguard Worker struct blk_zone blkz;
2732*59bfda1fSAndroid Build Coastguard Worker block_t cs_block, wp_block;
2733*59bfda1fSAndroid Build Coastguard Worker uint64_t cs_sector, wp_sector;
2734*59bfda1fSAndroid Build Coastguard Worker int i, ret;
2735*59bfda1fSAndroid Build Coastguard Worker int log_sectors_per_block = sbi->log_blocksize - SECTOR_SHIFT;
2736*59bfda1fSAndroid Build Coastguard Worker
2737*59bfda1fSAndroid Build Coastguard Worker if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG))
2738*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2739*59bfda1fSAndroid Build Coastguard Worker
2740*59bfda1fSAndroid Build Coastguard Worker /* get the device the curseg points to */
2741*59bfda1fSAndroid Build Coastguard Worker cs_block = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;
2742*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < MAX_DEVICES; i++) {
2743*59bfda1fSAndroid Build Coastguard Worker if (!c.devices[i].path)
2744*59bfda1fSAndroid Build Coastguard Worker break;
2745*59bfda1fSAndroid Build Coastguard Worker if (c.devices[i].start_blkaddr <= cs_block &&
2746*59bfda1fSAndroid Build Coastguard Worker cs_block <= c.devices[i].end_blkaddr)
2747*59bfda1fSAndroid Build Coastguard Worker break;
2748*59bfda1fSAndroid Build Coastguard Worker }
2749*59bfda1fSAndroid Build Coastguard Worker
2750*59bfda1fSAndroid Build Coastguard Worker if (i >= MAX_DEVICES)
2751*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2752*59bfda1fSAndroid Build Coastguard Worker
2753*59bfda1fSAndroid Build Coastguard Worker if (c.devices[i].zoned_model != F2FS_ZONED_HM)
2754*59bfda1fSAndroid Build Coastguard Worker return 0;
2755*59bfda1fSAndroid Build Coastguard Worker
2756*59bfda1fSAndroid Build Coastguard Worker /* get write pointer position of the zone the curseg points to */
2757*59bfda1fSAndroid Build Coastguard Worker cs_sector = (cs_block - c.devices[i].start_blkaddr)
2758*59bfda1fSAndroid Build Coastguard Worker << log_sectors_per_block;
2759*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_report_zone(i, cs_sector, &blkz);
2760*59bfda1fSAndroid Build Coastguard Worker if (ret)
2761*59bfda1fSAndroid Build Coastguard Worker return ret;
2762*59bfda1fSAndroid Build Coastguard Worker
2763*59bfda1fSAndroid Build Coastguard Worker if (blk_zone_type(&blkz) != BLK_ZONE_TYPE_SEQWRITE_REQ)
2764*59bfda1fSAndroid Build Coastguard Worker return 0;
2765*59bfda1fSAndroid Build Coastguard Worker
2766*59bfda1fSAndroid Build Coastguard Worker /* check consistency between the curseg and the write pointer */
2767*59bfda1fSAndroid Build Coastguard Worker wp_block = c.devices[i].start_blkaddr +
2768*59bfda1fSAndroid Build Coastguard Worker (blk_zone_wp_sector(&blkz) >> log_sectors_per_block);
2769*59bfda1fSAndroid Build Coastguard Worker wp_sector = blk_zone_wp_sector(&blkz);
2770*59bfda1fSAndroid Build Coastguard Worker
2771*59bfda1fSAndroid Build Coastguard Worker if (cs_sector == wp_sector) {
2772*59bfda1fSAndroid Build Coastguard Worker return 0;
2773*59bfda1fSAndroid Build Coastguard Worker } else if (cs_sector > wp_sector) {
2774*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Inconsistent write pointer with curseg %d: "
2775*59bfda1fSAndroid Build Coastguard Worker "curseg %d[0x%x,0x%x] > wp[0x%x,0x%x]\n",
2776*59bfda1fSAndroid Build Coastguard Worker type, type, curseg->segno, curseg->next_blkoff,
2777*59bfda1fSAndroid Build Coastguard Worker GET_SEGNO(sbi, wp_block),
2778*59bfda1fSAndroid Build Coastguard Worker OFFSET_IN_SEG(sbi, wp_block));
2779*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on)
2780*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_inconsistent_zones++;
2781*59bfda1fSAndroid Build Coastguard Worker } else {
2782*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Write pointer goes advance from curseg %d: "
2783*59bfda1fSAndroid Build Coastguard Worker "curseg %d[0x%x,0x%x] wp[0x%x,0x%x]\n",
2784*59bfda1fSAndroid Build Coastguard Worker type, type, curseg->segno, curseg->next_blkoff,
2785*59bfda1fSAndroid Build Coastguard Worker GET_SEGNO(sbi, wp_block), OFFSET_IN_SEG(sbi, wp_block));
2786*59bfda1fSAndroid Build Coastguard Worker }
2787*59bfda1fSAndroid Build Coastguard Worker
2788*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2789*59bfda1fSAndroid Build Coastguard Worker }
2790*59bfda1fSAndroid Build Coastguard Worker
2791*59bfda1fSAndroid Build Coastguard Worker #else
2792*59bfda1fSAndroid Build Coastguard Worker
check_curseg_write_pointer(struct f2fs_sb_info * UNUSED (sbi),int UNUSED (type))2793*59bfda1fSAndroid Build Coastguard Worker static int check_curseg_write_pointer(struct f2fs_sb_info *UNUSED(sbi),
2794*59bfda1fSAndroid Build Coastguard Worker int UNUSED(type))
2795*59bfda1fSAndroid Build Coastguard Worker {
2796*59bfda1fSAndroid Build Coastguard Worker return 0;
2797*59bfda1fSAndroid Build Coastguard Worker }
2798*59bfda1fSAndroid Build Coastguard Worker
2799*59bfda1fSAndroid Build Coastguard Worker #endif
2800*59bfda1fSAndroid Build Coastguard Worker
check_curseg_offset(struct f2fs_sb_info * sbi,int type,bool check_wp)2801*59bfda1fSAndroid Build Coastguard Worker int check_curseg_offset(struct f2fs_sb_info *sbi, int type, bool check_wp)
2802*59bfda1fSAndroid Build Coastguard Worker {
2803*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
2804*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *curseg = CURSEG_I(sbi, type);
2805*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
2806*59bfda1fSAndroid Build Coastguard Worker int j, nblocks;
2807*59bfda1fSAndroid Build Coastguard Worker
2808*59bfda1fSAndroid Build Coastguard Worker if ((get_sb(feature) & F2FS_FEATURE_RO) &&
2809*59bfda1fSAndroid Build Coastguard Worker type != CURSEG_HOT_DATA && type != CURSEG_HOT_NODE)
2810*59bfda1fSAndroid Build Coastguard Worker return 0;
2811*59bfda1fSAndroid Build Coastguard Worker
2812*59bfda1fSAndroid Build Coastguard Worker if ((curseg->next_blkoff >> 3) >= SIT_VBLOCK_MAP_SIZE) {
2813*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Next block offset:%u is invalid, type:%d",
2814*59bfda1fSAndroid Build Coastguard Worker curseg->next_blkoff, type);
2815*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2816*59bfda1fSAndroid Build Coastguard Worker }
2817*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, curseg->segno);
2818*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(curseg->next_blkoff,
2819*59bfda1fSAndroid Build Coastguard Worker (const char *)se->cur_valid_map)) {
2820*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Next block offset is not free, type:%d", type);
2821*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2822*59bfda1fSAndroid Build Coastguard Worker }
2823*59bfda1fSAndroid Build Coastguard Worker if (curseg->alloc_type == SSR)
2824*59bfda1fSAndroid Build Coastguard Worker return 0;
2825*59bfda1fSAndroid Build Coastguard Worker
2826*59bfda1fSAndroid Build Coastguard Worker nblocks = sbi->blocks_per_seg;
2827*59bfda1fSAndroid Build Coastguard Worker for (j = curseg->next_blkoff + 1; j < nblocks; j++) {
2828*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(j, (const char *)se->cur_valid_map)) {
2829*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("For LFS curseg, space after .next_blkoff "
2830*59bfda1fSAndroid Build Coastguard Worker "should be unused, type:%d", type);
2831*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2832*59bfda1fSAndroid Build Coastguard Worker }
2833*59bfda1fSAndroid Build Coastguard Worker }
2834*59bfda1fSAndroid Build Coastguard Worker
2835*59bfda1fSAndroid Build Coastguard Worker if (check_wp && c.zoned_model == F2FS_ZONED_HM)
2836*59bfda1fSAndroid Build Coastguard Worker return check_curseg_write_pointer(sbi, type);
2837*59bfda1fSAndroid Build Coastguard Worker
2838*59bfda1fSAndroid Build Coastguard Worker return 0;
2839*59bfda1fSAndroid Build Coastguard Worker }
2840*59bfda1fSAndroid Build Coastguard Worker
check_curseg_offsets(struct f2fs_sb_info * sbi,bool check_wp)2841*59bfda1fSAndroid Build Coastguard Worker int check_curseg_offsets(struct f2fs_sb_info *sbi, bool check_wp)
2842*59bfda1fSAndroid Build Coastguard Worker {
2843*59bfda1fSAndroid Build Coastguard Worker int i, ret;
2844*59bfda1fSAndroid Build Coastguard Worker
2845*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
2846*59bfda1fSAndroid Build Coastguard Worker ret = check_curseg_offset(sbi, i, check_wp);
2847*59bfda1fSAndroid Build Coastguard Worker if (ret)
2848*59bfda1fSAndroid Build Coastguard Worker return ret;
2849*59bfda1fSAndroid Build Coastguard Worker }
2850*59bfda1fSAndroid Build Coastguard Worker return 0;
2851*59bfda1fSAndroid Build Coastguard Worker }
2852*59bfda1fSAndroid Build Coastguard Worker
fix_curseg_info(struct f2fs_sb_info * sbi,bool check_wp)2853*59bfda1fSAndroid Build Coastguard Worker static void fix_curseg_info(struct f2fs_sb_info *sbi, bool check_wp)
2854*59bfda1fSAndroid Build Coastguard Worker {
2855*59bfda1fSAndroid Build Coastguard Worker int i, need_update = 0;
2856*59bfda1fSAndroid Build Coastguard Worker
2857*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
2858*59bfda1fSAndroid Build Coastguard Worker if (check_curseg_offset(sbi, i, check_wp)) {
2859*59bfda1fSAndroid Build Coastguard Worker update_curseg_info(sbi, i);
2860*59bfda1fSAndroid Build Coastguard Worker need_update = 1;
2861*59bfda1fSAndroid Build Coastguard Worker }
2862*59bfda1fSAndroid Build Coastguard Worker }
2863*59bfda1fSAndroid Build Coastguard Worker
2864*59bfda1fSAndroid Build Coastguard Worker if (need_update) {
2865*59bfda1fSAndroid Build Coastguard Worker write_curseg_info(sbi);
2866*59bfda1fSAndroid Build Coastguard Worker flush_curseg_sit_entries(sbi);
2867*59bfda1fSAndroid Build Coastguard Worker }
2868*59bfda1fSAndroid Build Coastguard Worker }
2869*59bfda1fSAndroid Build Coastguard Worker
check_sit_types(struct f2fs_sb_info * sbi)2870*59bfda1fSAndroid Build Coastguard Worker int check_sit_types(struct f2fs_sb_info *sbi)
2871*59bfda1fSAndroid Build Coastguard Worker {
2872*59bfda1fSAndroid Build Coastguard Worker unsigned int i;
2873*59bfda1fSAndroid Build Coastguard Worker int err = 0;
2874*59bfda1fSAndroid Build Coastguard Worker
2875*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < MAIN_SEGS(sbi); i++) {
2876*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
2877*59bfda1fSAndroid Build Coastguard Worker
2878*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, i);
2879*59bfda1fSAndroid Build Coastguard Worker if (se->orig_type != se->type) {
2880*59bfda1fSAndroid Build Coastguard Worker if (se->orig_type == CURSEG_COLD_DATA &&
2881*59bfda1fSAndroid Build Coastguard Worker se->type <= CURSEG_COLD_DATA) {
2882*59bfda1fSAndroid Build Coastguard Worker se->type = se->orig_type;
2883*59bfda1fSAndroid Build Coastguard Worker } else {
2884*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Wrong segment type [0x%x] %x -> %x",
2885*59bfda1fSAndroid Build Coastguard Worker i, se->orig_type, se->type);
2886*59bfda1fSAndroid Build Coastguard Worker err = -EINVAL;
2887*59bfda1fSAndroid Build Coastguard Worker }
2888*59bfda1fSAndroid Build Coastguard Worker }
2889*59bfda1fSAndroid Build Coastguard Worker }
2890*59bfda1fSAndroid Build Coastguard Worker return err;
2891*59bfda1fSAndroid Build Coastguard Worker }
2892*59bfda1fSAndroid Build Coastguard Worker
fsck_get_lpf(struct f2fs_sb_info * sbi)2893*59bfda1fSAndroid Build Coastguard Worker static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi)
2894*59bfda1fSAndroid Build Coastguard Worker {
2895*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node;
2896*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
2897*59bfda1fSAndroid Build Coastguard Worker nid_t lpf_ino;
2898*59bfda1fSAndroid Build Coastguard Worker int err;
2899*59bfda1fSAndroid Build Coastguard Worker
2900*59bfda1fSAndroid Build Coastguard Worker /* read root inode first */
2901*59bfda1fSAndroid Build Coastguard Worker node = calloc(F2FS_BLKSIZE, 1);
2902*59bfda1fSAndroid Build Coastguard Worker ASSERT(node);
2903*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, F2FS_ROOT_INO(sbi), &ni);
2904*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
2905*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
2906*59bfda1fSAndroid Build Coastguard Worker
2907*59bfda1fSAndroid Build Coastguard Worker /* lookup lost+found in root directory */
2908*59bfda1fSAndroid Build Coastguard Worker lpf_ino = f2fs_lookup(sbi, node, (u8 *)LPF, strlen(LPF));
2909*59bfda1fSAndroid Build Coastguard Worker if (lpf_ino) { /* found */
2910*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, lpf_ino, &ni);
2911*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
2912*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
2913*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Found lost+found 0x%x at blkaddr [0x%x]\n",
2914*59bfda1fSAndroid Build Coastguard Worker lpf_ino, ni.blk_addr);
2915*59bfda1fSAndroid Build Coastguard Worker if (!S_ISDIR(le16_to_cpu(node->i.i_mode))) {
2916*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("lost+found is not directory [0%o]\n",
2917*59bfda1fSAndroid Build Coastguard Worker le16_to_cpu(node->i.i_mode));
2918*59bfda1fSAndroid Build Coastguard Worker /* FIXME: give up? */
2919*59bfda1fSAndroid Build Coastguard Worker goto out;
2920*59bfda1fSAndroid Build Coastguard Worker }
2921*59bfda1fSAndroid Build Coastguard Worker
2922*59bfda1fSAndroid Build Coastguard Worker /* Must convert inline dentry before adding inodes */
2923*59bfda1fSAndroid Build Coastguard Worker err = convert_inline_dentry(sbi, node, &ni.blk_addr);
2924*59bfda1fSAndroid Build Coastguard Worker if (err) {
2925*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Convert inline dentry for ino=%x failed.\n",
2926*59bfda1fSAndroid Build Coastguard Worker lpf_ino);
2927*59bfda1fSAndroid Build Coastguard Worker goto out;
2928*59bfda1fSAndroid Build Coastguard Worker }
2929*59bfda1fSAndroid Build Coastguard Worker } else { /* not found, create it */
2930*59bfda1fSAndroid Build Coastguard Worker struct dentry de;
2931*59bfda1fSAndroid Build Coastguard Worker
2932*59bfda1fSAndroid Build Coastguard Worker memset(&de, 0, sizeof(de));
2933*59bfda1fSAndroid Build Coastguard Worker de.name = (u8 *) LPF;
2934*59bfda1fSAndroid Build Coastguard Worker de.len = strlen(LPF);
2935*59bfda1fSAndroid Build Coastguard Worker de.mode = 0x41c0;
2936*59bfda1fSAndroid Build Coastguard Worker de.pino = F2FS_ROOT_INO(sbi),
2937*59bfda1fSAndroid Build Coastguard Worker de.file_type = F2FS_FT_DIR,
2938*59bfda1fSAndroid Build Coastguard Worker de.uid = getuid();
2939*59bfda1fSAndroid Build Coastguard Worker de.gid = getgid();
2940*59bfda1fSAndroid Build Coastguard Worker de.mtime = time(NULL);
2941*59bfda1fSAndroid Build Coastguard Worker
2942*59bfda1fSAndroid Build Coastguard Worker err = f2fs_mkdir(sbi, &de);
2943*59bfda1fSAndroid Build Coastguard Worker if (err) {
2944*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Failed create lost+found");
2945*59bfda1fSAndroid Build Coastguard Worker goto out;
2946*59bfda1fSAndroid Build Coastguard Worker }
2947*59bfda1fSAndroid Build Coastguard Worker
2948*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, de.ino, &ni);
2949*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
2950*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
2951*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Create lost+found 0x%x at blkaddr [0x%x]\n",
2952*59bfda1fSAndroid Build Coastguard Worker de.ino, ni.blk_addr);
2953*59bfda1fSAndroid Build Coastguard Worker }
2954*59bfda1fSAndroid Build Coastguard Worker
2955*59bfda1fSAndroid Build Coastguard Worker c.lpf_ino = le32_to_cpu(F2FS_NODE_FOOTER(node)->ino);
2956*59bfda1fSAndroid Build Coastguard Worker return node;
2957*59bfda1fSAndroid Build Coastguard Worker out:
2958*59bfda1fSAndroid Build Coastguard Worker free(node);
2959*59bfda1fSAndroid Build Coastguard Worker return NULL;
2960*59bfda1fSAndroid Build Coastguard Worker }
2961*59bfda1fSAndroid Build Coastguard Worker
fsck_do_reconnect_file(struct f2fs_sb_info * sbi,struct f2fs_node * lpf,struct f2fs_node * fnode)2962*59bfda1fSAndroid Build Coastguard Worker static int fsck_do_reconnect_file(struct f2fs_sb_info *sbi,
2963*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *lpf,
2964*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *fnode)
2965*59bfda1fSAndroid Build Coastguard Worker {
2966*59bfda1fSAndroid Build Coastguard Worker char name[80];
2967*59bfda1fSAndroid Build Coastguard Worker size_t namelen;
2968*59bfda1fSAndroid Build Coastguard Worker nid_t ino = le32_to_cpu(F2FS_NODE_FOOTER(fnode)->ino);
2969*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
2970*59bfda1fSAndroid Build Coastguard Worker int ftype, ret;
2971*59bfda1fSAndroid Build Coastguard Worker
2972*59bfda1fSAndroid Build Coastguard Worker namelen = snprintf(name, 80, "%u", ino);
2973*59bfda1fSAndroid Build Coastguard Worker if (namelen >= 80)
2974*59bfda1fSAndroid Build Coastguard Worker /* ignore terminating '\0', should never happen */
2975*59bfda1fSAndroid Build Coastguard Worker namelen = 79;
2976*59bfda1fSAndroid Build Coastguard Worker
2977*59bfda1fSAndroid Build Coastguard Worker if (f2fs_lookup(sbi, lpf, (u8 *)name, namelen)) {
2978*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Name %s already exist in lost+found", name);
2979*59bfda1fSAndroid Build Coastguard Worker return -EEXIST;
2980*59bfda1fSAndroid Build Coastguard Worker }
2981*59bfda1fSAndroid Build Coastguard Worker
2982*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, le32_to_cpu(F2FS_NODE_FOOTER(lpf)->ino), &ni);
2983*59bfda1fSAndroid Build Coastguard Worker ftype = map_de_type(le16_to_cpu(fnode->i.i_mode));
2984*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_add_link(sbi, lpf, (unsigned char *)name, namelen,
2985*59bfda1fSAndroid Build Coastguard Worker ino, ftype, &ni.blk_addr, 0);
2986*59bfda1fSAndroid Build Coastguard Worker if (ret) {
2987*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Failed to add inode [0x%x] to lost+found", ino);
2988*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
2989*59bfda1fSAndroid Build Coastguard Worker }
2990*59bfda1fSAndroid Build Coastguard Worker
2991*59bfda1fSAndroid Build Coastguard Worker /* update fnode */
2992*59bfda1fSAndroid Build Coastguard Worker memcpy(fnode->i.i_name, name, namelen);
2993*59bfda1fSAndroid Build Coastguard Worker fnode->i.i_namelen = cpu_to_le32(namelen);
2994*59bfda1fSAndroid Build Coastguard Worker fnode->i.i_pino = c.lpf_ino;
2995*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, le32_to_cpu(F2FS_NODE_FOOTER(fnode)->ino), &ni);
2996*59bfda1fSAndroid Build Coastguard Worker ret = update_block(sbi, fnode, &ni.blk_addr, NULL);
2997*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
2998*59bfda1fSAndroid Build Coastguard Worker
2999*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Reconnect inode [0x%x] to lost+found\n", ino);
3000*59bfda1fSAndroid Build Coastguard Worker return 0;
3001*59bfda1fSAndroid Build Coastguard Worker }
3002*59bfda1fSAndroid Build Coastguard Worker
release_inode_cnt(struct f2fs_sb_info * sbi,bool dealloc)3003*59bfda1fSAndroid Build Coastguard Worker static inline void release_inode_cnt(struct f2fs_sb_info *sbi, bool dealloc)
3004*59bfda1fSAndroid Build Coastguard Worker {
3005*59bfda1fSAndroid Build Coastguard Worker F2FS_FSCK(sbi)->chk.valid_inode_cnt--;
3006*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3007*59bfda1fSAndroid Build Coastguard Worker sbi->total_valid_inode_count--;
3008*59bfda1fSAndroid Build Coastguard Worker }
3009*59bfda1fSAndroid Build Coastguard Worker
release_node_cnt(struct f2fs_sb_info * sbi,bool dealloc)3010*59bfda1fSAndroid Build Coastguard Worker static inline void release_node_cnt(struct f2fs_sb_info *sbi, bool dealloc)
3011*59bfda1fSAndroid Build Coastguard Worker {
3012*59bfda1fSAndroid Build Coastguard Worker F2FS_FSCK(sbi)->chk.valid_node_cnt--;
3013*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3014*59bfda1fSAndroid Build Coastguard Worker sbi->total_valid_node_count--;
3015*59bfda1fSAndroid Build Coastguard Worker }
3016*59bfda1fSAndroid Build Coastguard Worker
release_block_cnt(struct f2fs_sb_info * sbi,bool dealloc)3017*59bfda1fSAndroid Build Coastguard Worker static inline void release_block_cnt(struct f2fs_sb_info *sbi, bool dealloc)
3018*59bfda1fSAndroid Build Coastguard Worker {
3019*59bfda1fSAndroid Build Coastguard Worker F2FS_FSCK(sbi)->chk.valid_blk_cnt--;
3020*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3021*59bfda1fSAndroid Build Coastguard Worker sbi->total_valid_block_count--;
3022*59bfda1fSAndroid Build Coastguard Worker }
3023*59bfda1fSAndroid Build Coastguard Worker
release_block(struct f2fs_sb_info * sbi,u64 blkaddr,bool dealloc)3024*59bfda1fSAndroid Build Coastguard Worker static inline void release_block(struct f2fs_sb_info *sbi, u64 blkaddr,
3025*59bfda1fSAndroid Build Coastguard Worker bool dealloc)
3026*59bfda1fSAndroid Build Coastguard Worker {
3027*59bfda1fSAndroid Build Coastguard Worker f2fs_clear_main_bitmap(sbi, blkaddr);
3028*59bfda1fSAndroid Build Coastguard Worker if (dealloc) {
3029*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
3030*59bfda1fSAndroid Build Coastguard Worker u64 offset;
3031*59bfda1fSAndroid Build Coastguard Worker
3032*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, GET_SEGNO(sbi, blkaddr));
3033*59bfda1fSAndroid Build Coastguard Worker offset = OFFSET_IN_SEG(sbi, blkaddr);
3034*59bfda1fSAndroid Build Coastguard Worker se->valid_blocks--;
3035*59bfda1fSAndroid Build Coastguard Worker f2fs_clear_bit(offset, (char *)se->cur_valid_map);
3036*59bfda1fSAndroid Build Coastguard Worker if (need_fsync_data_record(sbi))
3037*59bfda1fSAndroid Build Coastguard Worker f2fs_clear_bit(offset, (char *)se->ckpt_valid_map);
3038*59bfda1fSAndroid Build Coastguard Worker se->dirty = 1;
3039*59bfda1fSAndroid Build Coastguard Worker f2fs_clear_sit_bitmap(sbi, blkaddr);
3040*59bfda1fSAndroid Build Coastguard Worker }
3041*59bfda1fSAndroid Build Coastguard Worker }
3042*59bfda1fSAndroid Build Coastguard Worker
release_nat_entry(struct f2fs_sb_info * sbi,u32 nid)3043*59bfda1fSAndroid Build Coastguard Worker static inline void release_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
3044*59bfda1fSAndroid Build Coastguard Worker {
3045*59bfda1fSAndroid Build Coastguard Worker nullify_nat_entry(sbi, nid);
3046*59bfda1fSAndroid Build Coastguard Worker F2FS_FSCK(sbi)->chk.valid_nat_entry_cnt--;
3047*59bfda1fSAndroid Build Coastguard Worker }
3048*59bfda1fSAndroid Build Coastguard Worker
fsck_disconnect_file_dnode(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,nid_t nid,bool dealloc)3049*59bfda1fSAndroid Build Coastguard Worker static void fsck_disconnect_file_dnode(struct f2fs_sb_info *sbi,
3050*59bfda1fSAndroid Build Coastguard Worker struct f2fs_inode *inode, nid_t nid, bool dealloc)
3051*59bfda1fSAndroid Build Coastguard Worker {
3052*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node;
3053*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
3054*59bfda1fSAndroid Build Coastguard Worker u32 addr;
3055*59bfda1fSAndroid Build Coastguard Worker int i, err;
3056*59bfda1fSAndroid Build Coastguard Worker
3057*59bfda1fSAndroid Build Coastguard Worker node = calloc(F2FS_BLKSIZE, 1);
3058*59bfda1fSAndroid Build Coastguard Worker ASSERT(node);
3059*59bfda1fSAndroid Build Coastguard Worker
3060*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
3061*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
3062*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
3063*59bfda1fSAndroid Build Coastguard Worker
3064*59bfda1fSAndroid Build Coastguard Worker release_node_cnt(sbi, dealloc);
3065*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3066*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, ni.blk_addr, dealloc);
3067*59bfda1fSAndroid Build Coastguard Worker
3068*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < ADDRS_PER_BLOCK(inode); i++) {
3069*59bfda1fSAndroid Build Coastguard Worker addr = le32_to_cpu(node->dn.addr[i]);
3070*59bfda1fSAndroid Build Coastguard Worker if (!addr)
3071*59bfda1fSAndroid Build Coastguard Worker continue;
3072*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3073*59bfda1fSAndroid Build Coastguard Worker if (addr == NEW_ADDR || addr == COMPRESS_ADDR)
3074*59bfda1fSAndroid Build Coastguard Worker continue;
3075*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, addr, dealloc);
3076*59bfda1fSAndroid Build Coastguard Worker }
3077*59bfda1fSAndroid Build Coastguard Worker
3078*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3079*59bfda1fSAndroid Build Coastguard Worker release_nat_entry(sbi, nid);
3080*59bfda1fSAndroid Build Coastguard Worker
3081*59bfda1fSAndroid Build Coastguard Worker free(node);
3082*59bfda1fSAndroid Build Coastguard Worker }
3083*59bfda1fSAndroid Build Coastguard Worker
fsck_disconnect_file_idnode(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,nid_t nid,bool dealloc)3084*59bfda1fSAndroid Build Coastguard Worker static void fsck_disconnect_file_idnode(struct f2fs_sb_info *sbi,
3085*59bfda1fSAndroid Build Coastguard Worker struct f2fs_inode *inode, nid_t nid, bool dealloc)
3086*59bfda1fSAndroid Build Coastguard Worker {
3087*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node;
3088*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
3089*59bfda1fSAndroid Build Coastguard Worker nid_t tmp;
3090*59bfda1fSAndroid Build Coastguard Worker int i, err;
3091*59bfda1fSAndroid Build Coastguard Worker
3092*59bfda1fSAndroid Build Coastguard Worker node = calloc(F2FS_BLKSIZE, 1);
3093*59bfda1fSAndroid Build Coastguard Worker ASSERT(node);
3094*59bfda1fSAndroid Build Coastguard Worker
3095*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
3096*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
3097*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
3098*59bfda1fSAndroid Build Coastguard Worker
3099*59bfda1fSAndroid Build Coastguard Worker release_node_cnt(sbi, dealloc);
3100*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3101*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, ni.blk_addr, dealloc);
3102*59bfda1fSAndroid Build Coastguard Worker
3103*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NIDS_PER_BLOCK; i++) {
3104*59bfda1fSAndroid Build Coastguard Worker tmp = le32_to_cpu(node->in.nid[i]);
3105*59bfda1fSAndroid Build Coastguard Worker if (!tmp)
3106*59bfda1fSAndroid Build Coastguard Worker continue;
3107*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file_dnode(sbi, inode, tmp, dealloc);
3108*59bfda1fSAndroid Build Coastguard Worker }
3109*59bfda1fSAndroid Build Coastguard Worker
3110*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3111*59bfda1fSAndroid Build Coastguard Worker release_nat_entry(sbi, nid);
3112*59bfda1fSAndroid Build Coastguard Worker
3113*59bfda1fSAndroid Build Coastguard Worker free(node);
3114*59bfda1fSAndroid Build Coastguard Worker }
3115*59bfda1fSAndroid Build Coastguard Worker
fsck_disconnect_file_didnode(struct f2fs_sb_info * sbi,struct f2fs_inode * inode,nid_t nid,bool dealloc)3116*59bfda1fSAndroid Build Coastguard Worker static void fsck_disconnect_file_didnode(struct f2fs_sb_info *sbi,
3117*59bfda1fSAndroid Build Coastguard Worker struct f2fs_inode *inode, nid_t nid, bool dealloc)
3118*59bfda1fSAndroid Build Coastguard Worker {
3119*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node;
3120*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
3121*59bfda1fSAndroid Build Coastguard Worker nid_t tmp;
3122*59bfda1fSAndroid Build Coastguard Worker int i, err;
3123*59bfda1fSAndroid Build Coastguard Worker
3124*59bfda1fSAndroid Build Coastguard Worker node = calloc(F2FS_BLKSIZE, 1);
3125*59bfda1fSAndroid Build Coastguard Worker ASSERT(node);
3126*59bfda1fSAndroid Build Coastguard Worker
3127*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
3128*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
3129*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
3130*59bfda1fSAndroid Build Coastguard Worker
3131*59bfda1fSAndroid Build Coastguard Worker release_node_cnt(sbi, dealloc);
3132*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3133*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, ni.blk_addr, dealloc);
3134*59bfda1fSAndroid Build Coastguard Worker
3135*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NIDS_PER_BLOCK; i++) {
3136*59bfda1fSAndroid Build Coastguard Worker tmp = le32_to_cpu(node->in.nid[i]);
3137*59bfda1fSAndroid Build Coastguard Worker if (!tmp)
3138*59bfda1fSAndroid Build Coastguard Worker continue;
3139*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file_idnode(sbi, inode, tmp, dealloc);
3140*59bfda1fSAndroid Build Coastguard Worker }
3141*59bfda1fSAndroid Build Coastguard Worker
3142*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3143*59bfda1fSAndroid Build Coastguard Worker release_nat_entry(sbi, nid);
3144*59bfda1fSAndroid Build Coastguard Worker
3145*59bfda1fSAndroid Build Coastguard Worker free(node);
3146*59bfda1fSAndroid Build Coastguard Worker }
3147*59bfda1fSAndroid Build Coastguard Worker
fsck_disconnect_file(struct f2fs_sb_info * sbi,nid_t ino,bool dealloc)3148*59bfda1fSAndroid Build Coastguard Worker static void fsck_disconnect_file(struct f2fs_sb_info *sbi, nid_t ino,
3149*59bfda1fSAndroid Build Coastguard Worker bool dealloc)
3150*59bfda1fSAndroid Build Coastguard Worker {
3151*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *node;
3152*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
3153*59bfda1fSAndroid Build Coastguard Worker nid_t nid;
3154*59bfda1fSAndroid Build Coastguard Worker int ofs, i, err;
3155*59bfda1fSAndroid Build Coastguard Worker
3156*59bfda1fSAndroid Build Coastguard Worker node = calloc(F2FS_BLKSIZE, 1);
3157*59bfda1fSAndroid Build Coastguard Worker ASSERT(node);
3158*59bfda1fSAndroid Build Coastguard Worker
3159*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, ino, &ni);
3160*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
3161*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
3162*59bfda1fSAndroid Build Coastguard Worker
3163*59bfda1fSAndroid Build Coastguard Worker /* clear inode counters */
3164*59bfda1fSAndroid Build Coastguard Worker release_inode_cnt(sbi, dealloc);
3165*59bfda1fSAndroid Build Coastguard Worker release_node_cnt(sbi, dealloc);
3166*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3167*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, ni.blk_addr, dealloc);
3168*59bfda1fSAndroid Build Coastguard Worker
3169*59bfda1fSAndroid Build Coastguard Worker /* clear xnid counters */
3170*59bfda1fSAndroid Build Coastguard Worker if (node->i.i_xattr_nid) {
3171*59bfda1fSAndroid Build Coastguard Worker nid = le32_to_cpu(node->i.i_xattr_nid);
3172*59bfda1fSAndroid Build Coastguard Worker release_node_cnt(sbi, dealloc);
3173*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3174*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
3175*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, ni.blk_addr, dealloc);
3176*59bfda1fSAndroid Build Coastguard Worker
3177*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3178*59bfda1fSAndroid Build Coastguard Worker release_nat_entry(sbi, nid);
3179*59bfda1fSAndroid Build Coastguard Worker }
3180*59bfda1fSAndroid Build Coastguard Worker
3181*59bfda1fSAndroid Build Coastguard Worker /* clear data counters */
3182*59bfda1fSAndroid Build Coastguard Worker if (!(node->i.i_inline & (F2FS_INLINE_DATA | F2FS_INLINE_DENTRY))) {
3183*59bfda1fSAndroid Build Coastguard Worker ofs = get_extra_isize(node);
3184*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < ADDRS_PER_INODE(&node->i); i++) {
3185*59bfda1fSAndroid Build Coastguard Worker block_t addr = le32_to_cpu(node->i.i_addr[ofs + i]);
3186*59bfda1fSAndroid Build Coastguard Worker if (!addr)
3187*59bfda1fSAndroid Build Coastguard Worker continue;
3188*59bfda1fSAndroid Build Coastguard Worker release_block_cnt(sbi, dealloc);
3189*59bfda1fSAndroid Build Coastguard Worker if (addr == NEW_ADDR || addr == COMPRESS_ADDR)
3190*59bfda1fSAndroid Build Coastguard Worker continue;
3191*59bfda1fSAndroid Build Coastguard Worker release_block(sbi, addr, dealloc);
3192*59bfda1fSAndroid Build Coastguard Worker }
3193*59bfda1fSAndroid Build Coastguard Worker }
3194*59bfda1fSAndroid Build Coastguard Worker
3195*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < 5; i++) {
3196*59bfda1fSAndroid Build Coastguard Worker nid = le32_to_cpu(F2FS_INODE_I_NID(&node->i, i));
3197*59bfda1fSAndroid Build Coastguard Worker if (!nid)
3198*59bfda1fSAndroid Build Coastguard Worker continue;
3199*59bfda1fSAndroid Build Coastguard Worker
3200*59bfda1fSAndroid Build Coastguard Worker switch (i) {
3201*59bfda1fSAndroid Build Coastguard Worker case 0: /* direct node */
3202*59bfda1fSAndroid Build Coastguard Worker case 1:
3203*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file_dnode(sbi, &node->i, nid,
3204*59bfda1fSAndroid Build Coastguard Worker dealloc);
3205*59bfda1fSAndroid Build Coastguard Worker break;
3206*59bfda1fSAndroid Build Coastguard Worker case 2: /* indirect node */
3207*59bfda1fSAndroid Build Coastguard Worker case 3:
3208*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file_idnode(sbi, &node->i, nid,
3209*59bfda1fSAndroid Build Coastguard Worker dealloc);
3210*59bfda1fSAndroid Build Coastguard Worker break;
3211*59bfda1fSAndroid Build Coastguard Worker case 4: /* double indirect node */
3212*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file_didnode(sbi, &node->i, nid,
3213*59bfda1fSAndroid Build Coastguard Worker dealloc);
3214*59bfda1fSAndroid Build Coastguard Worker break;
3215*59bfda1fSAndroid Build Coastguard Worker }
3216*59bfda1fSAndroid Build Coastguard Worker }
3217*59bfda1fSAndroid Build Coastguard Worker
3218*59bfda1fSAndroid Build Coastguard Worker if (dealloc)
3219*59bfda1fSAndroid Build Coastguard Worker release_nat_entry(sbi, ino);
3220*59bfda1fSAndroid Build Coastguard Worker
3221*59bfda1fSAndroid Build Coastguard Worker free(node);
3222*59bfda1fSAndroid Build Coastguard Worker }
3223*59bfda1fSAndroid Build Coastguard Worker
3224*59bfda1fSAndroid Build Coastguard Worker /*
3225*59bfda1fSAndroid Build Coastguard Worker * Scan unreachable nids and find only regular file inodes. If these files
3226*59bfda1fSAndroid Build Coastguard Worker * are not corrupted, reconnect them to lost+found.
3227*59bfda1fSAndroid Build Coastguard Worker *
3228*59bfda1fSAndroid Build Coastguard Worker * Since all unreachable nodes are already checked, we can allocate new
3229*59bfda1fSAndroid Build Coastguard Worker * blocks safely.
3230*59bfda1fSAndroid Build Coastguard Worker *
3231*59bfda1fSAndroid Build Coastguard Worker * This function returns the number of files been reconnected.
3232*59bfda1fSAndroid Build Coastguard Worker */
fsck_reconnect_file(struct f2fs_sb_info * sbi)3233*59bfda1fSAndroid Build Coastguard Worker static int fsck_reconnect_file(struct f2fs_sb_info *sbi)
3234*59bfda1fSAndroid Build Coastguard Worker {
3235*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
3236*59bfda1fSAndroid Build Coastguard Worker struct f2fs_node *lpf_node, *node;
3237*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
3238*59bfda1fSAndroid Build Coastguard Worker char *reconnect_bitmap;
3239*59bfda1fSAndroid Build Coastguard Worker u32 blk_cnt;
3240*59bfda1fSAndroid Build Coastguard Worker struct f2fs_compr_blk_cnt cbc;
3241*59bfda1fSAndroid Build Coastguard Worker nid_t nid;
3242*59bfda1fSAndroid Build Coastguard Worker int err, cnt = 0, ftype;
3243*59bfda1fSAndroid Build Coastguard Worker
3244*59bfda1fSAndroid Build Coastguard Worker node = calloc(F2FS_BLKSIZE, 1);
3245*59bfda1fSAndroid Build Coastguard Worker ASSERT(node);
3246*59bfda1fSAndroid Build Coastguard Worker
3247*59bfda1fSAndroid Build Coastguard Worker reconnect_bitmap = calloc(fsck->nat_area_bitmap_sz, 1);
3248*59bfda1fSAndroid Build Coastguard Worker ASSERT(reconnect_bitmap);
3249*59bfda1fSAndroid Build Coastguard Worker
3250*59bfda1fSAndroid Build Coastguard Worker for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
3251*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(nid, fsck->nat_area_bitmap)) {
3252*59bfda1fSAndroid Build Coastguard Worker if (is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
3253*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Not support quota inode [0x%x]\n",
3254*59bfda1fSAndroid Build Coastguard Worker nid);
3255*59bfda1fSAndroid Build Coastguard Worker continue;
3256*59bfda1fSAndroid Build Coastguard Worker }
3257*59bfda1fSAndroid Build Coastguard Worker
3258*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
3259*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
3260*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
3261*59bfda1fSAndroid Build Coastguard Worker
3262*59bfda1fSAndroid Build Coastguard Worker /* reconnection will restore these nodes if needed */
3263*59bfda1fSAndroid Build Coastguard Worker if (!IS_INODE(node)) {
3264*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Not support non-inode node [0x%x]\n",
3265*59bfda1fSAndroid Build Coastguard Worker nid);
3266*59bfda1fSAndroid Build Coastguard Worker continue;
3267*59bfda1fSAndroid Build Coastguard Worker }
3268*59bfda1fSAndroid Build Coastguard Worker
3269*59bfda1fSAndroid Build Coastguard Worker if (S_ISDIR(le16_to_cpu(node->i.i_mode))) {
3270*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Not support directory inode [0x%x]\n",
3271*59bfda1fSAndroid Build Coastguard Worker nid);
3272*59bfda1fSAndroid Build Coastguard Worker continue;
3273*59bfda1fSAndroid Build Coastguard Worker }
3274*59bfda1fSAndroid Build Coastguard Worker
3275*59bfda1fSAndroid Build Coastguard Worker ftype = map_de_type(le16_to_cpu(node->i.i_mode));
3276*59bfda1fSAndroid Build Coastguard Worker if (sanity_check_nid(sbi, nid, node, ftype,
3277*59bfda1fSAndroid Build Coastguard Worker TYPE_INODE, &ni)) {
3278*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Invalid nid [0x%x]\n", nid);
3279*59bfda1fSAndroid Build Coastguard Worker continue;
3280*59bfda1fSAndroid Build Coastguard Worker }
3281*59bfda1fSAndroid Build Coastguard Worker
3282*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Check inode 0x%x\n", nid);
3283*59bfda1fSAndroid Build Coastguard Worker blk_cnt = 1;
3284*59bfda1fSAndroid Build Coastguard Worker cbc.cnt = 0;
3285*59bfda1fSAndroid Build Coastguard Worker cbc.cheader_pgofs = CHEADER_PGOFS_NONE;
3286*59bfda1fSAndroid Build Coastguard Worker fsck_chk_inode_blk(sbi, nid, ftype, node,
3287*59bfda1fSAndroid Build Coastguard Worker &blk_cnt, &cbc, &ni, NULL);
3288*59bfda1fSAndroid Build Coastguard Worker
3289*59bfda1fSAndroid Build Coastguard Worker f2fs_set_bit(nid, reconnect_bitmap);
3290*59bfda1fSAndroid Build Coastguard Worker }
3291*59bfda1fSAndroid Build Coastguard Worker }
3292*59bfda1fSAndroid Build Coastguard Worker
3293*59bfda1fSAndroid Build Coastguard Worker lpf_node = fsck_get_lpf(sbi);
3294*59bfda1fSAndroid Build Coastguard Worker if (!lpf_node)
3295*59bfda1fSAndroid Build Coastguard Worker goto out;
3296*59bfda1fSAndroid Build Coastguard Worker
3297*59bfda1fSAndroid Build Coastguard Worker for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
3298*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(nid, reconnect_bitmap)) {
3299*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, nid, &ni);
3300*59bfda1fSAndroid Build Coastguard Worker err = dev_read_block(node, ni.blk_addr);
3301*59bfda1fSAndroid Build Coastguard Worker ASSERT(err >= 0);
3302*59bfda1fSAndroid Build Coastguard Worker
3303*59bfda1fSAndroid Build Coastguard Worker if (fsck_do_reconnect_file(sbi, lpf_node, node)) {
3304*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Failed to reconnect inode [0x%x]\n",
3305*59bfda1fSAndroid Build Coastguard Worker nid);
3306*59bfda1fSAndroid Build Coastguard Worker fsck_disconnect_file(sbi, nid, false);
3307*59bfda1fSAndroid Build Coastguard Worker continue;
3308*59bfda1fSAndroid Build Coastguard Worker }
3309*59bfda1fSAndroid Build Coastguard Worker
3310*59bfda1fSAndroid Build Coastguard Worker quota_add_inode_usage(fsck->qctx, nid, &node->i);
3311*59bfda1fSAndroid Build Coastguard Worker
3312*59bfda1fSAndroid Build Coastguard Worker DBG(1, "Reconnected inode [0x%x] to lost+found\n", nid);
3313*59bfda1fSAndroid Build Coastguard Worker cnt++;
3314*59bfda1fSAndroid Build Coastguard Worker }
3315*59bfda1fSAndroid Build Coastguard Worker }
3316*59bfda1fSAndroid Build Coastguard Worker
3317*59bfda1fSAndroid Build Coastguard Worker out:
3318*59bfda1fSAndroid Build Coastguard Worker free(node);
3319*59bfda1fSAndroid Build Coastguard Worker free(lpf_node);
3320*59bfda1fSAndroid Build Coastguard Worker free(reconnect_bitmap);
3321*59bfda1fSAndroid Build Coastguard Worker return cnt;
3322*59bfda1fSAndroid Build Coastguard Worker }
3323*59bfda1fSAndroid Build Coastguard Worker
3324*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_BLKZONED_H
3325*59bfda1fSAndroid Build Coastguard Worker
3326*59bfda1fSAndroid Build Coastguard Worker struct write_pointer_check_data {
3327*59bfda1fSAndroid Build Coastguard Worker struct f2fs_sb_info *sbi;
3328*59bfda1fSAndroid Build Coastguard Worker int dev_index;
3329*59bfda1fSAndroid Build Coastguard Worker };
3330*59bfda1fSAndroid Build Coastguard Worker
chk_and_fix_wp_with_sit(int UNUSED (i),void * blkzone,void * opaque)3331*59bfda1fSAndroid Build Coastguard Worker static int chk_and_fix_wp_with_sit(int UNUSED(i), void *blkzone, void *opaque)
3332*59bfda1fSAndroid Build Coastguard Worker {
3333*59bfda1fSAndroid Build Coastguard Worker struct blk_zone *blkz = (struct blk_zone *)blkzone;
3334*59bfda1fSAndroid Build Coastguard Worker struct write_pointer_check_data *wpd = opaque;
3335*59bfda1fSAndroid Build Coastguard Worker struct f2fs_sb_info *sbi = wpd->sbi;
3336*59bfda1fSAndroid Build Coastguard Worker struct device_info *dev = c.devices + wpd->dev_index;
3337*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
3338*59bfda1fSAndroid Build Coastguard Worker block_t zone_block, wp_block, wp_blkoff;
3339*59bfda1fSAndroid Build Coastguard Worker unsigned int zone_segno, wp_segno;
3340*59bfda1fSAndroid Build Coastguard Worker int i, ret, last_valid_blkoff;
3341*59bfda1fSAndroid Build Coastguard Worker int log_sectors_per_block = sbi->log_blocksize - SECTOR_SHIFT;
3342*59bfda1fSAndroid Build Coastguard Worker unsigned int segs_per_zone = sbi->segs_per_sec * sbi->secs_per_zone;
3343*59bfda1fSAndroid Build Coastguard Worker
3344*59bfda1fSAndroid Build Coastguard Worker if (blk_zone_conv(blkz))
3345*59bfda1fSAndroid Build Coastguard Worker return 0;
3346*59bfda1fSAndroid Build Coastguard Worker
3347*59bfda1fSAndroid Build Coastguard Worker zone_block = dev->start_blkaddr
3348*59bfda1fSAndroid Build Coastguard Worker + (blk_zone_sector(blkz) >> log_sectors_per_block);
3349*59bfda1fSAndroid Build Coastguard Worker zone_segno = GET_SEGNO(sbi, zone_block);
3350*59bfda1fSAndroid Build Coastguard Worker if (zone_segno >= MAIN_SEGS(sbi))
3351*59bfda1fSAndroid Build Coastguard Worker return 0;
3352*59bfda1fSAndroid Build Coastguard Worker
3353*59bfda1fSAndroid Build Coastguard Worker wp_block = dev->start_blkaddr
3354*59bfda1fSAndroid Build Coastguard Worker + (blk_zone_wp_sector(blkz) >> log_sectors_per_block);
3355*59bfda1fSAndroid Build Coastguard Worker wp_segno = GET_SEGNO(sbi, wp_block);
3356*59bfda1fSAndroid Build Coastguard Worker wp_blkoff = wp_block - START_BLOCK(sbi, wp_segno);
3357*59bfda1fSAndroid Build Coastguard Worker
3358*59bfda1fSAndroid Build Coastguard Worker last_valid_blkoff = last_vblk_off_in_zone(sbi, zone_segno);
3359*59bfda1fSAndroid Build Coastguard Worker
3360*59bfda1fSAndroid Build Coastguard Worker /* if a curseg points to the zone, do not finishing zone */
3361*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
3362*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *cs = CURSEG_I(sbi, i);
3363*59bfda1fSAndroid Build Coastguard Worker
3364*59bfda1fSAndroid Build Coastguard Worker if (zone_segno <= cs->segno &&
3365*59bfda1fSAndroid Build Coastguard Worker cs->segno < zone_segno + segs_per_zone) {
3366*59bfda1fSAndroid Build Coastguard Worker /*
3367*59bfda1fSAndroid Build Coastguard Worker * When there is no valid block in the zone, check
3368*59bfda1fSAndroid Build Coastguard Worker * write pointer is at zone start. If not, reset
3369*59bfda1fSAndroid Build Coastguard Worker * the write pointer.
3370*59bfda1fSAndroid Build Coastguard Worker */
3371*59bfda1fSAndroid Build Coastguard Worker if (last_valid_blkoff < 0 &&
3372*59bfda1fSAndroid Build Coastguard Worker blk_zone_wp_sector(blkz) != blk_zone_sector(blkz)) {
3373*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on) {
3374*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Inconsistent write pointer: "
3375*59bfda1fSAndroid Build Coastguard Worker "wp[0x%x,0x%x]\n",
3376*59bfda1fSAndroid Build Coastguard Worker wp_segno, wp_blkoff);
3377*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_inconsistent_zones++;
3378*59bfda1fSAndroid Build Coastguard Worker return 0;
3379*59bfda1fSAndroid Build Coastguard Worker }
3380*59bfda1fSAndroid Build Coastguard Worker
3381*59bfda1fSAndroid Build Coastguard Worker FIX_MSG("Reset write pointer of zone at "
3382*59bfda1fSAndroid Build Coastguard Worker "segment 0x%x", zone_segno);
3383*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_reset_zone(wpd->dev_index, blkz);
3384*59bfda1fSAndroid Build Coastguard Worker if (ret) {
3385*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Write pointer reset "
3386*59bfda1fSAndroid Build Coastguard Worker "failed: %s\n", dev->path);
3387*59bfda1fSAndroid Build Coastguard Worker return ret;
3388*59bfda1fSAndroid Build Coastguard Worker }
3389*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_fixed = 1;
3390*59bfda1fSAndroid Build Coastguard Worker }
3391*59bfda1fSAndroid Build Coastguard Worker return 0;
3392*59bfda1fSAndroid Build Coastguard Worker }
3393*59bfda1fSAndroid Build Coastguard Worker }
3394*59bfda1fSAndroid Build Coastguard Worker
3395*59bfda1fSAndroid Build Coastguard Worker /*
3396*59bfda1fSAndroid Build Coastguard Worker * If valid blocks exist in the zone beyond the write pointer, it
3397*59bfda1fSAndroid Build Coastguard Worker * is a bug. No need to fix because the zone is not selected for the
3398*59bfda1fSAndroid Build Coastguard Worker * write. Just report it.
3399*59bfda1fSAndroid Build Coastguard Worker */
3400*59bfda1fSAndroid Build Coastguard Worker if (last_valid_blkoff + zone_block > wp_block) {
3401*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Unexpected invalid write pointer: wp[0x%x,0x%x]\n",
3402*59bfda1fSAndroid Build Coastguard Worker wp_segno, wp_blkoff);
3403*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on)
3404*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_inconsistent_zones++;
3405*59bfda1fSAndroid Build Coastguard Worker }
3406*59bfda1fSAndroid Build Coastguard Worker
3407*59bfda1fSAndroid Build Coastguard Worker if (!c.fix_on)
3408*59bfda1fSAndroid Build Coastguard Worker return 0;
3409*59bfda1fSAndroid Build Coastguard Worker
3410*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_finish_zone(wpd->dev_index, blkz);
3411*59bfda1fSAndroid Build Coastguard Worker if (ret) {
3412*59bfda1fSAndroid Build Coastguard Worker u64 fill_sects = blk_zone_length(blkz) -
3413*59bfda1fSAndroid Build Coastguard Worker (blk_zone_wp_sector(blkz) - blk_zone_sector(blkz));
3414*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se = get_seg_entry(sbi, wp_segno);
3415*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Finishing zone failed: %s\n", dev->path);
3416*59bfda1fSAndroid Build Coastguard Worker ret = dev_fill(NULL, wp_block * F2FS_BLKSIZE,
3417*59bfda1fSAndroid Build Coastguard Worker (fill_sects >> log_sectors_per_block) * F2FS_BLKSIZE,
3418*59bfda1fSAndroid Build Coastguard Worker f2fs_io_type_to_rw_hint(se->type));
3419*59bfda1fSAndroid Build Coastguard Worker if (ret)
3420*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Fill up zone failed: %s\n", dev->path);
3421*59bfda1fSAndroid Build Coastguard Worker }
3422*59bfda1fSAndroid Build Coastguard Worker
3423*59bfda1fSAndroid Build Coastguard Worker if (!ret)
3424*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_fixed = 1;
3425*59bfda1fSAndroid Build Coastguard Worker return ret;
3426*59bfda1fSAndroid Build Coastguard Worker }
3427*59bfda1fSAndroid Build Coastguard Worker
fix_wp_sit_alignment(struct f2fs_sb_info * sbi)3428*59bfda1fSAndroid Build Coastguard Worker static void fix_wp_sit_alignment(struct f2fs_sb_info *sbi)
3429*59bfda1fSAndroid Build Coastguard Worker {
3430*59bfda1fSAndroid Build Coastguard Worker unsigned int i;
3431*59bfda1fSAndroid Build Coastguard Worker struct write_pointer_check_data wpd = { sbi, 0 };
3432*59bfda1fSAndroid Build Coastguard Worker
3433*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model != F2FS_ZONED_HM)
3434*59bfda1fSAndroid Build Coastguard Worker return;
3435*59bfda1fSAndroid Build Coastguard Worker
3436*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < MAX_DEVICES; i++) {
3437*59bfda1fSAndroid Build Coastguard Worker if (!c.devices[i].path)
3438*59bfda1fSAndroid Build Coastguard Worker break;
3439*59bfda1fSAndroid Build Coastguard Worker if (c.devices[i].zoned_model != F2FS_ZONED_HM)
3440*59bfda1fSAndroid Build Coastguard Worker continue;
3441*59bfda1fSAndroid Build Coastguard Worker
3442*59bfda1fSAndroid Build Coastguard Worker wpd.dev_index = i;
3443*59bfda1fSAndroid Build Coastguard Worker if (f2fs_report_zones(i, chk_and_fix_wp_with_sit, &wpd)) {
3444*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Write pointer check failed: %s\n",
3445*59bfda1fSAndroid Build Coastguard Worker c.devices[i].path);
3446*59bfda1fSAndroid Build Coastguard Worker return;
3447*59bfda1fSAndroid Build Coastguard Worker }
3448*59bfda1fSAndroid Build Coastguard Worker }
3449*59bfda1fSAndroid Build Coastguard Worker }
3450*59bfda1fSAndroid Build Coastguard Worker
3451*59bfda1fSAndroid Build Coastguard Worker #else
3452*59bfda1fSAndroid Build Coastguard Worker
fix_wp_sit_alignment(struct f2fs_sb_info * UNUSED (sbi))3453*59bfda1fSAndroid Build Coastguard Worker static void fix_wp_sit_alignment(struct f2fs_sb_info *UNUSED(sbi))
3454*59bfda1fSAndroid Build Coastguard Worker {
3455*59bfda1fSAndroid Build Coastguard Worker return;
3456*59bfda1fSAndroid Build Coastguard Worker }
3457*59bfda1fSAndroid Build Coastguard Worker
3458*59bfda1fSAndroid Build Coastguard Worker #endif
3459*59bfda1fSAndroid Build Coastguard Worker
3460*59bfda1fSAndroid Build Coastguard Worker /*
3461*59bfda1fSAndroid Build Coastguard Worker * Check and fix consistency with write pointers at the beginning of
3462*59bfda1fSAndroid Build Coastguard Worker * fsck so that following writes by fsck do not fail.
3463*59bfda1fSAndroid Build Coastguard Worker */
fsck_chk_and_fix_write_pointers(struct f2fs_sb_info * sbi)3464*59bfda1fSAndroid Build Coastguard Worker void fsck_chk_and_fix_write_pointers(struct f2fs_sb_info *sbi)
3465*59bfda1fSAndroid Build Coastguard Worker {
3466*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
3467*59bfda1fSAndroid Build Coastguard Worker
3468*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model != F2FS_ZONED_HM)
3469*59bfda1fSAndroid Build Coastguard Worker return;
3470*59bfda1fSAndroid Build Coastguard Worker
3471*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on) {
3472*59bfda1fSAndroid Build Coastguard Worker flush_nat_journal_entries(sbi);
3473*59bfda1fSAndroid Build Coastguard Worker flush_sit_journal_entries(sbi);
3474*59bfda1fSAndroid Build Coastguard Worker
3475*59bfda1fSAndroid Build Coastguard Worker if (check_curseg_offsets(sbi, true))
3476*59bfda1fSAndroid Build Coastguard Worker fix_curseg_info(sbi, true);
3477*59bfda1fSAndroid Build Coastguard Worker
3478*59bfda1fSAndroid Build Coastguard Worker fix_wp_sit_alignment(sbi);
3479*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_fixed = 1;
3480*59bfda1fSAndroid Build Coastguard Worker }
3481*59bfda1fSAndroid Build Coastguard Worker }
3482*59bfda1fSAndroid Build Coastguard Worker
fsck_chk_curseg_info(struct f2fs_sb_info * sbi)3483*59bfda1fSAndroid Build Coastguard Worker int fsck_chk_curseg_info(struct f2fs_sb_info *sbi)
3484*59bfda1fSAndroid Build Coastguard Worker {
3485*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
3486*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *curseg;
3487*59bfda1fSAndroid Build Coastguard Worker struct seg_entry *se;
3488*59bfda1fSAndroid Build Coastguard Worker struct f2fs_summary_block *sum_blk;
3489*59bfda1fSAndroid Build Coastguard Worker int i, ret = 0;
3490*59bfda1fSAndroid Build Coastguard Worker
3491*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
3492*59bfda1fSAndroid Build Coastguard Worker curseg = CURSEG_I(sbi, i);
3493*59bfda1fSAndroid Build Coastguard Worker se = get_seg_entry(sbi, curseg->segno);
3494*59bfda1fSAndroid Build Coastguard Worker sum_blk = curseg->sum_blk;
3495*59bfda1fSAndroid Build Coastguard Worker
3496*59bfda1fSAndroid Build Coastguard Worker if ((get_sb(feature) & F2FS_FEATURE_RO) &&
3497*59bfda1fSAndroid Build Coastguard Worker (i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE))
3498*59bfda1fSAndroid Build Coastguard Worker continue;
3499*59bfda1fSAndroid Build Coastguard Worker
3500*59bfda1fSAndroid Build Coastguard Worker if (se->type != i) {
3501*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Incorrect curseg [%d]: segno [0x%x] "
3502*59bfda1fSAndroid Build Coastguard Worker "type(SIT) [%d]", i, curseg->segno,
3503*59bfda1fSAndroid Build Coastguard Worker se->type);
3504*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on || c.preen_mode)
3505*59bfda1fSAndroid Build Coastguard Worker se->type = i;
3506*59bfda1fSAndroid Build Coastguard Worker ret = -1;
3507*59bfda1fSAndroid Build Coastguard Worker }
3508*59bfda1fSAndroid Build Coastguard Worker if (i <= CURSEG_COLD_DATA && IS_SUM_DATA_SEG(sum_blk)) {
3509*59bfda1fSAndroid Build Coastguard Worker continue;
3510*59bfda1fSAndroid Build Coastguard Worker } else if (i > CURSEG_COLD_DATA && IS_SUM_NODE_SEG(sum_blk)) {
3511*59bfda1fSAndroid Build Coastguard Worker continue;
3512*59bfda1fSAndroid Build Coastguard Worker } else {
3513*59bfda1fSAndroid Build Coastguard Worker ASSERT_MSG("Incorrect curseg [%d]: segno [0x%x] "
3514*59bfda1fSAndroid Build Coastguard Worker "type(SSA) [%d]", i, curseg->segno,
3515*59bfda1fSAndroid Build Coastguard Worker F2FS_SUMMARY_BLOCK_FOOTER(sum_blk)->entry_type);
3516*59bfda1fSAndroid Build Coastguard Worker if (c.fix_on || c.preen_mode)
3517*59bfda1fSAndroid Build Coastguard Worker F2FS_SUMMARY_BLOCK_FOOTER(sum_blk)->entry_type =
3518*59bfda1fSAndroid Build Coastguard Worker i <= CURSEG_COLD_DATA ?
3519*59bfda1fSAndroid Build Coastguard Worker SUM_TYPE_DATA : SUM_TYPE_NODE;
3520*59bfda1fSAndroid Build Coastguard Worker ret = -1;
3521*59bfda1fSAndroid Build Coastguard Worker }
3522*59bfda1fSAndroid Build Coastguard Worker }
3523*59bfda1fSAndroid Build Coastguard Worker
3524*59bfda1fSAndroid Build Coastguard Worker return ret;
3525*59bfda1fSAndroid Build Coastguard Worker }
3526*59bfda1fSAndroid Build Coastguard Worker
fsck_verify(struct f2fs_sb_info * sbi)3527*59bfda1fSAndroid Build Coastguard Worker int fsck_verify(struct f2fs_sb_info *sbi)
3528*59bfda1fSAndroid Build Coastguard Worker {
3529*59bfda1fSAndroid Build Coastguard Worker unsigned int i = 0;
3530*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
3531*59bfda1fSAndroid Build Coastguard Worker int force = 0;
3532*59bfda1fSAndroid Build Coastguard Worker u32 nr_unref_nid = 0;
3533*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
3534*59bfda1fSAndroid Build Coastguard Worker struct hard_link_node *node = NULL;
3535*59bfda1fSAndroid Build Coastguard Worker bool verify_failed = false;
3536*59bfda1fSAndroid Build Coastguard Worker uint64_t max_blks, data_secs, node_secs, free_blks;
3537*59bfda1fSAndroid Build Coastguard Worker
3538*59bfda1fSAndroid Build Coastguard Worker if (c.show_file_map)
3539*59bfda1fSAndroid Build Coastguard Worker return 0;
3540*59bfda1fSAndroid Build Coastguard Worker
3541*59bfda1fSAndroid Build Coastguard Worker printf("\n");
3542*59bfda1fSAndroid Build Coastguard Worker
3543*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model == F2FS_ZONED_HM) {
3544*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Write pointers consistency ");
3545*59bfda1fSAndroid Build Coastguard Worker if (fsck->chk.wp_inconsistent_zones == 0x0) {
3546*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..]\n");
3547*59bfda1fSAndroid Build Coastguard Worker } else {
3548*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x]\n",
3549*59bfda1fSAndroid Build Coastguard Worker fsck->chk.wp_inconsistent_zones);
3550*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3551*59bfda1fSAndroid Build Coastguard Worker }
3552*59bfda1fSAndroid Build Coastguard Worker
3553*59bfda1fSAndroid Build Coastguard Worker if (fsck->chk.wp_fixed && c.fix_on)
3554*59bfda1fSAndroid Build Coastguard Worker force = 1;
3555*59bfda1fSAndroid Build Coastguard Worker }
3556*59bfda1fSAndroid Build Coastguard Worker
3557*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_LOST_FOUND) {
3558*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < fsck->nr_nat_entries; i++)
3559*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0)
3560*59bfda1fSAndroid Build Coastguard Worker break;
3561*59bfda1fSAndroid Build Coastguard Worker if (i < fsck->nr_nat_entries) {
3562*59bfda1fSAndroid Build Coastguard Worker i = fsck_reconnect_file(sbi);
3563*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Reconnect %u files to lost+found\n", i);
3564*59bfda1fSAndroid Build Coastguard Worker }
3565*59bfda1fSAndroid Build Coastguard Worker }
3566*59bfda1fSAndroid Build Coastguard Worker
3567*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < fsck->nr_nat_entries; i++) {
3568*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) {
3569*59bfda1fSAndroid Build Coastguard Worker struct node_info ni;
3570*59bfda1fSAndroid Build Coastguard Worker
3571*59bfda1fSAndroid Build Coastguard Worker get_node_info(sbi, i, &ni);
3572*59bfda1fSAndroid Build Coastguard Worker printf("NID[0x%x] is unreachable, blkaddr:0x%x\n",
3573*59bfda1fSAndroid Build Coastguard Worker i, ni.blk_addr);
3574*59bfda1fSAndroid Build Coastguard Worker nr_unref_nid++;
3575*59bfda1fSAndroid Build Coastguard Worker }
3576*59bfda1fSAndroid Build Coastguard Worker }
3577*59bfda1fSAndroid Build Coastguard Worker
3578*59bfda1fSAndroid Build Coastguard Worker if (fsck->hard_link_list_head != NULL) {
3579*59bfda1fSAndroid Build Coastguard Worker node = fsck->hard_link_list_head;
3580*59bfda1fSAndroid Build Coastguard Worker while (node) {
3581*59bfda1fSAndroid Build Coastguard Worker printf("NID[0x%x] has [0x%x] more unreachable links\n",
3582*59bfda1fSAndroid Build Coastguard Worker node->nid, node->links);
3583*59bfda1fSAndroid Build Coastguard Worker node = node->next;
3584*59bfda1fSAndroid Build Coastguard Worker }
3585*59bfda1fSAndroid Build Coastguard Worker c.bug_on = 1;
3586*59bfda1fSAndroid Build Coastguard Worker }
3587*59bfda1fSAndroid Build Coastguard Worker
3588*59bfda1fSAndroid Build Coastguard Worker data_secs = round_up(sbi->total_valid_node_count, BLKS_PER_SEC(sbi));
3589*59bfda1fSAndroid Build Coastguard Worker node_secs = round_up(sbi->total_valid_block_count -
3590*59bfda1fSAndroid Build Coastguard Worker sbi->total_valid_node_count, BLKS_PER_SEC(sbi));
3591*59bfda1fSAndroid Build Coastguard Worker free_blks = (sbi->total_sections - data_secs - node_secs) *
3592*59bfda1fSAndroid Build Coastguard Worker BLKS_PER_SEC(sbi);
3593*59bfda1fSAndroid Build Coastguard Worker max_blks = SM_I(sbi)->main_blkaddr + (data_secs + node_secs) *
3594*59bfda1fSAndroid Build Coastguard Worker BLKS_PER_SEC(sbi);
3595*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Max image size: %"PRIu64" MB, Free space: %"PRIu64" MB\n",
3596*59bfda1fSAndroid Build Coastguard Worker max_blks >> (20 - F2FS_BLKSIZE_BITS),
3597*59bfda1fSAndroid Build Coastguard Worker free_blks >> (20 - F2FS_BLKSIZE_BITS));
3598*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Unreachable nat entries ");
3599*59bfda1fSAndroid Build Coastguard Worker if (nr_unref_nid == 0x0) {
3600*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", nr_unref_nid);
3601*59bfda1fSAndroid Build Coastguard Worker } else {
3602*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x]\n", nr_unref_nid);
3603*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3604*59bfda1fSAndroid Build Coastguard Worker }
3605*59bfda1fSAndroid Build Coastguard Worker
3606*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] SIT valid block bitmap checking ");
3607*59bfda1fSAndroid Build Coastguard Worker if (memcmp(fsck->sit_area_bitmap, fsck->main_area_bitmap,
3608*59bfda1fSAndroid Build Coastguard Worker fsck->sit_area_bitmap_sz) == 0x0) {
3609*59bfda1fSAndroid Build Coastguard Worker printf("[Ok..]\n");
3610*59bfda1fSAndroid Build Coastguard Worker } else {
3611*59bfda1fSAndroid Build Coastguard Worker printf("[Fail]\n");
3612*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3613*59bfda1fSAndroid Build Coastguard Worker }
3614*59bfda1fSAndroid Build Coastguard Worker
3615*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] Hard link checking for regular file ");
3616*59bfda1fSAndroid Build Coastguard Worker if (fsck->hard_link_list_head == NULL) {
3617*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", fsck->chk.multi_hard_link_files);
3618*59bfda1fSAndroid Build Coastguard Worker } else {
3619*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x]\n", fsck->chk.multi_hard_link_files);
3620*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3621*59bfda1fSAndroid Build Coastguard Worker }
3622*59bfda1fSAndroid Build Coastguard Worker
3623*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] valid_block_count matching with CP ");
3624*59bfda1fSAndroid Build Coastguard Worker if (sbi->total_valid_block_count == fsck->chk.valid_blk_cnt) {
3625*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", (u32)fsck->chk.valid_blk_cnt);
3626*59bfda1fSAndroid Build Coastguard Worker } else {
3627*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_block_count,
3628*59bfda1fSAndroid Build Coastguard Worker (u32)fsck->chk.valid_blk_cnt);
3629*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3630*59bfda1fSAndroid Build Coastguard Worker }
3631*59bfda1fSAndroid Build Coastguard Worker
3632*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] valid_node_count matching with CP (de lookup) ");
3633*59bfda1fSAndroid Build Coastguard Worker if (sbi->total_valid_node_count == fsck->chk.valid_node_cnt) {
3634*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", fsck->chk.valid_node_cnt);
3635*59bfda1fSAndroid Build Coastguard Worker } else {
3636*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_node_count,
3637*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_node_cnt);
3638*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3639*59bfda1fSAndroid Build Coastguard Worker }
3640*59bfda1fSAndroid Build Coastguard Worker
3641*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] valid_node_count matching with CP (nat lookup)");
3642*59bfda1fSAndroid Build Coastguard Worker if (sbi->total_valid_node_count == fsck->chk.valid_nat_entry_cnt) {
3643*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", fsck->chk.valid_nat_entry_cnt);
3644*59bfda1fSAndroid Build Coastguard Worker } else {
3645*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_node_count,
3646*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_nat_entry_cnt);
3647*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3648*59bfda1fSAndroid Build Coastguard Worker }
3649*59bfda1fSAndroid Build Coastguard Worker
3650*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] valid_inode_count matched with CP ");
3651*59bfda1fSAndroid Build Coastguard Worker if (sbi->total_valid_inode_count == fsck->chk.valid_inode_cnt) {
3652*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", fsck->chk.valid_inode_cnt);
3653*59bfda1fSAndroid Build Coastguard Worker } else {
3654*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x, 0x%x]\n", sbi->total_valid_inode_count,
3655*59bfda1fSAndroid Build Coastguard Worker fsck->chk.valid_inode_cnt);
3656*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3657*59bfda1fSAndroid Build Coastguard Worker }
3658*59bfda1fSAndroid Build Coastguard Worker
3659*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] free segment_count matched with CP ");
3660*59bfda1fSAndroid Build Coastguard Worker if (le32_to_cpu(F2FS_CKPT(sbi)->free_segment_count) ==
3661*59bfda1fSAndroid Build Coastguard Worker fsck->chk.sit_free_segs) {
3662*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..] [0x%x]\n", fsck->chk.sit_free_segs);
3663*59bfda1fSAndroid Build Coastguard Worker } else {
3664*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail] [0x%x, 0x%x]\n",
3665*59bfda1fSAndroid Build Coastguard Worker le32_to_cpu(F2FS_CKPT(sbi)->free_segment_count),
3666*59bfda1fSAndroid Build Coastguard Worker fsck->chk.sit_free_segs);
3667*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3668*59bfda1fSAndroid Build Coastguard Worker }
3669*59bfda1fSAndroid Build Coastguard Worker
3670*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] next block offset is free ");
3671*59bfda1fSAndroid Build Coastguard Worker if (check_curseg_offsets(sbi, false) == 0) {
3672*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..]\n");
3673*59bfda1fSAndroid Build Coastguard Worker } else {
3674*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail]\n");
3675*59bfda1fSAndroid Build Coastguard Worker verify_failed = true;
3676*59bfda1fSAndroid Build Coastguard Worker }
3677*59bfda1fSAndroid Build Coastguard Worker
3678*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] fixing SIT types\n");
3679*59bfda1fSAndroid Build Coastguard Worker if (check_sit_types(sbi) != 0)
3680*59bfda1fSAndroid Build Coastguard Worker force = 1;
3681*59bfda1fSAndroid Build Coastguard Worker
3682*59bfda1fSAndroid Build Coastguard Worker printf("[FSCK] other corrupted bugs ");
3683*59bfda1fSAndroid Build Coastguard Worker if (c.bug_on == 0) {
3684*59bfda1fSAndroid Build Coastguard Worker printf(" [Ok..]\n");
3685*59bfda1fSAndroid Build Coastguard Worker } else {
3686*59bfda1fSAndroid Build Coastguard Worker printf(" [Fail]\n");
3687*59bfda1fSAndroid Build Coastguard Worker ret = EXIT_ERR_CODE;
3688*59bfda1fSAndroid Build Coastguard Worker }
3689*59bfda1fSAndroid Build Coastguard Worker
3690*59bfda1fSAndroid Build Coastguard Worker if (verify_failed) {
3691*59bfda1fSAndroid Build Coastguard Worker ret = EXIT_ERR_CODE;
3692*59bfda1fSAndroid Build Coastguard Worker c.bug_on = 1;
3693*59bfda1fSAndroid Build Coastguard Worker }
3694*59bfda1fSAndroid Build Coastguard Worker
3695*59bfda1fSAndroid Build Coastguard Worker #ifndef WITH_ANDROID
3696*59bfda1fSAndroid Build Coastguard Worker if (nr_unref_nid && !c.ro) {
3697*59bfda1fSAndroid Build Coastguard Worker char ans[255] = {0};
3698*59bfda1fSAndroid Build Coastguard Worker int res;
3699*59bfda1fSAndroid Build Coastguard Worker
3700*59bfda1fSAndroid Build Coastguard Worker printf("\nDo you want to restore lost files into ./lost_found/? [Y/N] ");
3701*59bfda1fSAndroid Build Coastguard Worker res = scanf("%s", ans);
3702*59bfda1fSAndroid Build Coastguard Worker ASSERT(res >= 0);
3703*59bfda1fSAndroid Build Coastguard Worker if (!strcasecmp(ans, "y")) {
3704*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < fsck->nr_nat_entries; i++) {
3705*59bfda1fSAndroid Build Coastguard Worker if (f2fs_test_bit(i, fsck->nat_area_bitmap))
3706*59bfda1fSAndroid Build Coastguard Worker dump_node(sbi, i, 1, NULL, 1, 0, NULL);
3707*59bfda1fSAndroid Build Coastguard Worker }
3708*59bfda1fSAndroid Build Coastguard Worker }
3709*59bfda1fSAndroid Build Coastguard Worker }
3710*59bfda1fSAndroid Build Coastguard Worker #endif
3711*59bfda1fSAndroid Build Coastguard Worker
3712*59bfda1fSAndroid Build Coastguard Worker /* fix global metadata */
3713*59bfda1fSAndroid Build Coastguard Worker if (force || (c.fix_on && f2fs_dev_is_writable())) {
3714*59bfda1fSAndroid Build Coastguard Worker struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
3715*59bfda1fSAndroid Build Coastguard Worker struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
3716*59bfda1fSAndroid Build Coastguard Worker
3717*59bfda1fSAndroid Build Coastguard Worker if (force || c.bug_on || c.bug_nat_bits || c.quota_fixed) {
3718*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model != F2FS_ZONED_HM) {
3719*59bfda1fSAndroid Build Coastguard Worker /* flush nats to write_nit_bits below */
3720*59bfda1fSAndroid Build Coastguard Worker flush_journal_entries(sbi);
3721*59bfda1fSAndroid Build Coastguard Worker }
3722*59bfda1fSAndroid Build Coastguard Worker fix_hard_links(sbi);
3723*59bfda1fSAndroid Build Coastguard Worker fix_nat_entries(sbi);
3724*59bfda1fSAndroid Build Coastguard Worker rewrite_sit_area_bitmap(sbi);
3725*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model == F2FS_ZONED_HM) {
3726*59bfda1fSAndroid Build Coastguard Worker struct curseg_info *curseg;
3727*59bfda1fSAndroid Build Coastguard Worker u64 ssa_blk;
3728*59bfda1fSAndroid Build Coastguard Worker
3729*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < NO_CHECK_TYPE; i++) {
3730*59bfda1fSAndroid Build Coastguard Worker curseg = CURSEG_I(sbi, i);
3731*59bfda1fSAndroid Build Coastguard Worker ssa_blk = GET_SUM_BLKADDR(sbi,
3732*59bfda1fSAndroid Build Coastguard Worker curseg->segno);
3733*59bfda1fSAndroid Build Coastguard Worker ret = dev_write_block(curseg->sum_blk,
3734*59bfda1fSAndroid Build Coastguard Worker ssa_blk,
3735*59bfda1fSAndroid Build Coastguard Worker WRITE_LIFE_NONE);
3736*59bfda1fSAndroid Build Coastguard Worker ASSERT(ret >= 0);
3737*59bfda1fSAndroid Build Coastguard Worker }
3738*59bfda1fSAndroid Build Coastguard Worker if (c.roll_forward)
3739*59bfda1fSAndroid Build Coastguard Worker restore_curseg_warm_node_info(sbi);
3740*59bfda1fSAndroid Build Coastguard Worker write_curseg_info(sbi);
3741*59bfda1fSAndroid Build Coastguard Worker } else {
3742*59bfda1fSAndroid Build Coastguard Worker fix_curseg_info(sbi, false);
3743*59bfda1fSAndroid Build Coastguard Worker }
3744*59bfda1fSAndroid Build Coastguard Worker fix_checksum(sbi);
3745*59bfda1fSAndroid Build Coastguard Worker fix_checkpoints(sbi);
3746*59bfda1fSAndroid Build Coastguard Worker } else if (is_set_ckpt_flags(cp, CP_FSCK_FLAG) ||
3747*59bfda1fSAndroid Build Coastguard Worker is_set_ckpt_flags(cp, CP_QUOTA_NEED_FSCK_FLAG)) {
3748*59bfda1fSAndroid Build Coastguard Worker write_checkpoints(sbi);
3749*59bfda1fSAndroid Build Coastguard Worker }
3750*59bfda1fSAndroid Build Coastguard Worker
3751*59bfda1fSAndroid Build Coastguard Worker if (c.invalid_sb & SB_ABNORMAL_STOP)
3752*59bfda1fSAndroid Build Coastguard Worker memset(sb->s_stop_reason, 0, MAX_STOP_REASON);
3753*59bfda1fSAndroid Build Coastguard Worker
3754*59bfda1fSAndroid Build Coastguard Worker if (c.invalid_sb & SB_FS_ERRORS)
3755*59bfda1fSAndroid Build Coastguard Worker memset(sb->s_errors, 0, MAX_F2FS_ERRORS);
3756*59bfda1fSAndroid Build Coastguard Worker
3757*59bfda1fSAndroid Build Coastguard Worker if (c.invalid_sb & SB_NEED_FIX)
3758*59bfda1fSAndroid Build Coastguard Worker update_superblock(sb, SB_MASK_ALL);
3759*59bfda1fSAndroid Build Coastguard Worker
3760*59bfda1fSAndroid Build Coastguard Worker /* to return FSCK_ERROR_CORRECTED */
3761*59bfda1fSAndroid Build Coastguard Worker ret = 0;
3762*59bfda1fSAndroid Build Coastguard Worker }
3763*59bfda1fSAndroid Build Coastguard Worker return ret;
3764*59bfda1fSAndroid Build Coastguard Worker }
3765*59bfda1fSAndroid Build Coastguard Worker
fsck_free(struct f2fs_sb_info * sbi)3766*59bfda1fSAndroid Build Coastguard Worker void fsck_free(struct f2fs_sb_info *sbi)
3767*59bfda1fSAndroid Build Coastguard Worker {
3768*59bfda1fSAndroid Build Coastguard Worker struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
3769*59bfda1fSAndroid Build Coastguard Worker
3770*59bfda1fSAndroid Build Coastguard Worker if (fsck->qctx)
3771*59bfda1fSAndroid Build Coastguard Worker quota_release_context(&fsck->qctx);
3772*59bfda1fSAndroid Build Coastguard Worker
3773*59bfda1fSAndroid Build Coastguard Worker if (fsck->main_area_bitmap)
3774*59bfda1fSAndroid Build Coastguard Worker free(fsck->main_area_bitmap);
3775*59bfda1fSAndroid Build Coastguard Worker
3776*59bfda1fSAndroid Build Coastguard Worker if (fsck->nat_area_bitmap)
3777*59bfda1fSAndroid Build Coastguard Worker free(fsck->nat_area_bitmap);
3778*59bfda1fSAndroid Build Coastguard Worker
3779*59bfda1fSAndroid Build Coastguard Worker if (fsck->sit_area_bitmap)
3780*59bfda1fSAndroid Build Coastguard Worker free(fsck->sit_area_bitmap);
3781*59bfda1fSAndroid Build Coastguard Worker
3782*59bfda1fSAndroid Build Coastguard Worker if (fsck->entries)
3783*59bfda1fSAndroid Build Coastguard Worker free(fsck->entries);
3784*59bfda1fSAndroid Build Coastguard Worker
3785*59bfda1fSAndroid Build Coastguard Worker if (tree_mark)
3786*59bfda1fSAndroid Build Coastguard Worker free(tree_mark);
3787*59bfda1fSAndroid Build Coastguard Worker
3788*59bfda1fSAndroid Build Coastguard Worker while (fsck->dentry) {
3789*59bfda1fSAndroid Build Coastguard Worker struct f2fs_dentry *dentry = fsck->dentry;
3790*59bfda1fSAndroid Build Coastguard Worker
3791*59bfda1fSAndroid Build Coastguard Worker fsck->dentry = fsck->dentry->next;
3792*59bfda1fSAndroid Build Coastguard Worker free(dentry);
3793*59bfda1fSAndroid Build Coastguard Worker }
3794*59bfda1fSAndroid Build Coastguard Worker }
3795