• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * node.c
3  *
4  * Many parts of codes are copied from Linux kernel/fs/f2fs.
5  *
6  * Copyright (C) 2015 Huawei Ltd.
7  * Witten by:
8  *   Hou Pengyang <houpengyang@huawei.com>
9  *   Liu Shuoran <liushuoran@huawei.com>
10  *   Jaegeuk Kim <jaegeuk@kernel.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16 #include "fsck.h"
17 #include "node.h"
18 
f2fs_alloc_nid(struct f2fs_sb_info * sbi,nid_t * nid)19 void f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
20 {
21 	struct f2fs_nm_info *nm_i = NM_I(sbi);
22 	nid_t i;
23 
24 	for (i = 0; i < nm_i->max_nid; i++)
25 		if(f2fs_test_bit(i, nm_i->nid_bitmap) == 0)
26 			break;
27 
28 	ASSERT(i < nm_i->max_nid);
29 	f2fs_set_bit(i, nm_i->nid_bitmap);
30 	*nid = i;
31 }
32 
f2fs_release_nid(struct f2fs_sb_info * sbi,nid_t nid)33 void f2fs_release_nid(struct f2fs_sb_info *sbi, nid_t nid)
34 {
35 	struct f2fs_nm_info *nm_i = NM_I(sbi);
36 
37 	ASSERT(nid < nm_i->max_nid);
38 	ASSERT(f2fs_test_bit(nid, nm_i->nid_bitmap));
39 
40 	f2fs_clear_bit(nid, nm_i->nid_bitmap);
41 }
42 
set_data_blkaddr(struct dnode_of_data * dn)43 void set_data_blkaddr(struct dnode_of_data *dn)
44 {
45 	__le32 *addr_array;
46 	struct f2fs_node *node_blk = dn->node_blk;
47 	unsigned int ofs_in_node = dn->ofs_in_node;
48 
49 	addr_array = blkaddr_in_node(node_blk);
50 	addr_array[ofs_in_node] = cpu_to_le32(dn->data_blkaddr);
51 	if (dn->node_blk != dn->inode_blk)
52 		dn->ndirty = 1;
53 	else
54 		dn->idirty = 1;
55 }
56 
57 /*
58  * In this function, we get a new node blk, and write back
59  * node_blk would be sloadd in RAM, linked by dn->node_blk
60  */
new_node_block(struct f2fs_sb_info * sbi,struct dnode_of_data * dn,unsigned int ofs)61 block_t new_node_block(struct f2fs_sb_info *sbi,
62 				struct dnode_of_data *dn, unsigned int ofs)
63 {
64 	struct f2fs_node *f2fs_inode;
65 	struct f2fs_node *node_blk;
66 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
67 	struct f2fs_summary sum;
68 	struct node_info ni;
69 	block_t blkaddr = NULL_ADDR;
70 	int type;
71 	int ret;
72 
73 	f2fs_inode = dn->inode_blk;
74 
75 	node_blk = calloc(BLOCK_SZ, 1);
76 	ASSERT(node_blk);
77 
78 	node_blk->footer.nid = cpu_to_le32(dn->nid);
79 	node_blk->footer.ino = f2fs_inode->footer.ino;
80 	node_blk->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT);
81 	node_blk->footer.cp_ver = ckpt->checkpoint_ver;
82 	set_cold_node(node_blk, S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)));
83 
84 	type = CURSEG_COLD_NODE;
85 	if (IS_DNODE(node_blk)) {
86 		if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)))
87 			type = CURSEG_HOT_NODE;
88 		else
89 			type = CURSEG_WARM_NODE;
90 	}
91 
92 	get_node_info(sbi, dn->nid, &ni);
93 	set_summary(&sum, dn->nid, 0, ni.version);
94 	ret = reserve_new_block(sbi, &blkaddr, &sum, type, !ofs);
95 	if (ret) {
96 		free(node_blk);
97 		return 0;
98 	}
99 
100 	/* update nat info */
101 	update_nat_blkaddr(sbi, le32_to_cpu(f2fs_inode->footer.ino),
102 						dn->nid, blkaddr);
103 
104 	dn->node_blk = node_blk;
105 	inc_inode_blocks(dn);
106 	return blkaddr;
107 }
108 
109 /*
110  * get_node_path - Get the index path of pgoff_t block
111  * @offset: offset in the current index node block.
112  * @noffset: NO. of the index block within a file.
113  * return: depth of the index path.
114  *
115  * By default, it sets inline_xattr and inline_data
116  */
get_node_path(struct f2fs_node * node,long block,int offset[4],unsigned int noffset[4])117 static int get_node_path(struct f2fs_node *node, long block,
118 				int offset[4], unsigned int noffset[4])
119 {
120 	const long direct_index = ADDRS_PER_INODE(&node->i);
121 	const long direct_blks = ADDRS_PER_BLOCK(&node->i);
122 	const long dptrs_per_blk = NIDS_PER_BLOCK;
123 	const long indirect_blks = ADDRS_PER_BLOCK(&node->i) * NIDS_PER_BLOCK;
124 	const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
125 	int n = 0;
126 	int level = 0;
127 
128 	noffset[0] = 0;
129 	if (block < direct_index) {
130 		offset[n] = block;
131 		goto got;
132 	}
133 
134 	block -= direct_index;
135 	if (block < direct_blks) {
136 		offset[n++] = NODE_DIR1_BLOCK;
137 		noffset[n]= 1;
138 		offset[n] = block;
139 		level = 1;
140 		goto got;
141 	}
142 	block -= direct_blks;
143 	if (block < direct_blks) {
144 		offset[n++] = NODE_DIR2_BLOCK;
145 		noffset[n] = 2;
146 		offset[n] = block;
147 		level = 1;
148 		goto got;
149 	}
150 	block -= direct_blks;
151 	if (block < indirect_blks) {
152 		offset[n++] = NODE_IND1_BLOCK;
153 		noffset[n] = 3;
154 		offset[n++] = block / direct_blks;
155 		noffset[n] = 4 + offset[n - 1];
156 		offset[n] = block % direct_blks;
157 		level = 2;
158 		goto got;
159 	}
160 	block -= indirect_blks;
161 	if (block < indirect_blks) {
162 		offset[n++] = NODE_IND2_BLOCK;
163 		noffset[n] = 4 + dptrs_per_blk;
164 		offset[n++] = block / direct_blks;
165 		noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
166 		offset[n] = block % direct_blks;
167 		level = 2;
168 		goto got;
169 	}
170 	block -= indirect_blks;
171 	if (block < dindirect_blks) {
172 		offset[n++] = NODE_DIND_BLOCK;
173 		noffset[n] = 5 + (dptrs_per_blk * 2);
174 		offset[n++] = block / indirect_blks;
175 		noffset[n] = 6 + (dptrs_per_blk * 2) +
176 			offset[n - 1] * (dptrs_per_blk + 1);
177 		offset[n++] = (block / direct_blks) % dptrs_per_blk;
178 		noffset[n] = 7 + (dptrs_per_blk * 2) +
179 			offset[n - 2] * (dptrs_per_blk + 1) +
180 			offset[n - 1];
181 		offset[n] = block % direct_blks;
182 		level = 3;
183 		goto got;
184 	} else {
185 		ASSERT(0);
186 	}
187 got:
188 	return level;
189 }
190 
get_dnode_of_data(struct f2fs_sb_info * sbi,struct dnode_of_data * dn,pgoff_t index,int mode)191 int get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
192 						pgoff_t index, int mode)
193 {
194 	int offset[4];
195 	unsigned int noffset[4];
196 	struct f2fs_node *parent = NULL;
197 	nid_t nids[4];
198 	block_t nblk[4];
199 	struct node_info ni;
200 	int level, i;
201 	int ret;
202 
203 	level = get_node_path(dn->inode_blk, index, offset, noffset);
204 
205 	nids[0] = dn->nid;
206 	parent = dn->inode_blk;
207 	if (level != 0)
208 		nids[1] = get_nid(parent, offset[0], 1);
209 	else
210 		dn->node_blk = dn->inode_blk;
211 
212 	get_node_info(sbi, nids[0], &ni);
213 	nblk[0] = ni.blk_addr;
214 
215 	for (i = 1; i <= level; i++) {
216 		if (!nids[i] && mode == ALLOC_NODE) {
217 			f2fs_alloc_nid(sbi, &nids[i]);
218 
219 			dn->nid = nids[i];
220 
221 			/* Function new_node_blk get a new f2fs_node blk and update*/
222 			/* We should make sure that dn->node_blk == NULL*/
223 			nblk[i] = new_node_block(sbi, dn, noffset[i]);
224 			if (!nblk[i]) {
225 				f2fs_release_nid(sbi, nids[i]);
226 				c.alloc_failed = 1;
227 				return -EINVAL;
228 			}
229 
230 			set_nid(parent, offset[i - 1], nids[i], i == 1);
231 		} else {
232 			/* If Sparse file no read API, */
233 			struct node_info ni;
234 
235 			get_node_info(sbi, nids[i], &ni);
236 			dn->node_blk = calloc(BLOCK_SZ, 1);
237 			ASSERT(dn->node_blk);
238 
239 			ret = dev_read_block(dn->node_blk, ni.blk_addr);
240 			ASSERT(ret >= 0);
241 
242 			nblk[i] = ni.blk_addr;
243 		}
244 
245 		if (mode == ALLOC_NODE){
246 			/* Parent node may have changed */
247 			ret = dev_write_block(parent, nblk[i - 1]);
248 			ASSERT(ret >= 0);
249 		}
250 		if (i != 1)
251 			free(parent);
252 
253 		if (i < level) {
254 			parent = dn->node_blk;
255 			nids[i + 1] = get_nid(parent, offset[i], 0);
256 		}
257 	}
258 
259 	dn->nid = nids[level];
260 	dn->ofs_in_node = offset[level];
261 	dn->data_blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
262 	dn->node_blkaddr = nblk[level];
263 	return 0;
264 }
265