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_super_block *sb = F2FS_RAW_SUPER(sbi);
65 struct f2fs_node *f2fs_inode;
66 struct f2fs_node *node_blk;
67 struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
68 struct f2fs_summary sum;
69 struct node_info ni;
70 block_t blkaddr = NULL_ADDR;
71 int type;
72 int ret;
73
74 f2fs_inode = dn->inode_blk;
75
76 node_blk = calloc(BLOCK_SZ, 1);
77 ASSERT(node_blk);
78
79 node_blk->footer.nid = cpu_to_le32(dn->nid);
80 node_blk->footer.ino = f2fs_inode->footer.ino;
81 node_blk->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT);
82 node_blk->footer.cp_ver = ckpt->checkpoint_ver;
83 set_cold_node(node_blk, S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)));
84
85 type = CURSEG_COLD_NODE;
86 if (IS_DNODE(node_blk)) {
87 if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode)))
88 type = CURSEG_HOT_NODE;
89 else
90 type = CURSEG_WARM_NODE;
91 }
92
93 if ((get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) &&
94 type != CURSEG_HOT_NODE)
95 type = CURSEG_HOT_NODE;
96
97 get_node_info(sbi, dn->nid, &ni);
98 set_summary(&sum, dn->nid, 0, ni.version);
99 ret = reserve_new_block(sbi, &blkaddr, &sum, type, !ofs);
100 if (ret) {
101 free(node_blk);
102 return 0;
103 }
104
105 /* update nat info */
106 update_nat_blkaddr(sbi, le32_to_cpu(f2fs_inode->footer.ino),
107 dn->nid, blkaddr);
108
109 dn->node_blk = node_blk;
110 inc_inode_blocks(dn);
111 return blkaddr;
112 }
113
114 /*
115 * get_node_path - Get the index path of pgoff_t block
116 * @offset: offset in the current index node block.
117 * @noffset: NO. of the index block within a file.
118 * return: depth of the index path.
119 *
120 * By default, it sets inline_xattr and inline_data
121 */
get_node_path(struct f2fs_node * node,long block,int offset[4],unsigned int noffset[4])122 static int get_node_path(struct f2fs_node *node, long block,
123 int offset[4], unsigned int noffset[4])
124 {
125 const long direct_index = ADDRS_PER_INODE(&node->i);
126 const long direct_blks = ADDRS_PER_BLOCK(&node->i);
127 const long dptrs_per_blk = NIDS_PER_BLOCK;
128 const long indirect_blks = ADDRS_PER_BLOCK(&node->i) * NIDS_PER_BLOCK;
129 const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
130 int n = 0;
131 int level = 0;
132
133 noffset[0] = 0;
134 if (block < direct_index) {
135 offset[n] = block;
136 goto got;
137 }
138
139 block -= direct_index;
140 if (block < direct_blks) {
141 offset[n++] = NODE_DIR1_BLOCK;
142 noffset[n]= 1;
143 offset[n] = block;
144 level = 1;
145 goto got;
146 }
147 block -= direct_blks;
148 if (block < direct_blks) {
149 offset[n++] = NODE_DIR2_BLOCK;
150 noffset[n] = 2;
151 offset[n] = block;
152 level = 1;
153 goto got;
154 }
155 block -= direct_blks;
156 if (block < indirect_blks) {
157 offset[n++] = NODE_IND1_BLOCK;
158 noffset[n] = 3;
159 offset[n++] = block / direct_blks;
160 noffset[n] = 4 + offset[n - 1];
161 offset[n] = block % direct_blks;
162 level = 2;
163 goto got;
164 }
165 block -= indirect_blks;
166 if (block < indirect_blks) {
167 offset[n++] = NODE_IND2_BLOCK;
168 noffset[n] = 4 + dptrs_per_blk;
169 offset[n++] = block / direct_blks;
170 noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
171 offset[n] = block % direct_blks;
172 level = 2;
173 goto got;
174 }
175 block -= indirect_blks;
176 if (block < dindirect_blks) {
177 offset[n++] = NODE_DIND_BLOCK;
178 noffset[n] = 5 + (dptrs_per_blk * 2);
179 offset[n++] = block / indirect_blks;
180 noffset[n] = 6 + (dptrs_per_blk * 2) +
181 offset[n - 1] * (dptrs_per_blk + 1);
182 offset[n++] = (block / direct_blks) % dptrs_per_blk;
183 noffset[n] = 7 + (dptrs_per_blk * 2) +
184 offset[n - 2] * (dptrs_per_blk + 1) +
185 offset[n - 1];
186 offset[n] = block % direct_blks;
187 level = 3;
188 goto got;
189 } else {
190 ASSERT(0);
191 }
192 got:
193 return level;
194 }
195
get_dnode_of_data(struct f2fs_sb_info * sbi,struct dnode_of_data * dn,pgoff_t index,int mode)196 int get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
197 pgoff_t index, int mode)
198 {
199 int offset[4];
200 unsigned int noffset[4];
201 struct f2fs_node *parent = NULL;
202 nid_t nids[4];
203 block_t nblk[4];
204 struct node_info ni;
205 int level, i;
206 int ret;
207
208 level = get_node_path(dn->inode_blk, index, offset, noffset);
209
210 nids[0] = dn->nid;
211 parent = dn->inode_blk;
212 if (level != 0)
213 nids[1] = get_nid(parent, offset[0], 1);
214 else
215 dn->node_blk = dn->inode_blk;
216
217 get_node_info(sbi, nids[0], &ni);
218 nblk[0] = ni.blk_addr;
219
220 for (i = 1; i <= level; i++) {
221 if (!nids[i] && mode == ALLOC_NODE) {
222 f2fs_alloc_nid(sbi, &nids[i]);
223
224 dn->nid = nids[i];
225
226 /* Function new_node_blk get a new f2fs_node blk and update*/
227 /* We should make sure that dn->node_blk == NULL*/
228 nblk[i] = new_node_block(sbi, dn, noffset[i]);
229 if (!nblk[i]) {
230 f2fs_release_nid(sbi, nids[i]);
231 c.alloc_failed = 1;
232 return -EINVAL;
233 }
234
235 set_nid(parent, offset[i - 1], nids[i], i == 1);
236 } else {
237 /* If Sparse file no read API, */
238 struct node_info ni;
239
240 get_node_info(sbi, nids[i], &ni);
241 dn->node_blk = calloc(BLOCK_SZ, 1);
242 ASSERT(dn->node_blk);
243
244 ret = dev_read_block(dn->node_blk, ni.blk_addr);
245 ASSERT(ret >= 0);
246
247 nblk[i] = ni.blk_addr;
248 }
249
250 if (mode == ALLOC_NODE){
251 /* Parent node may have changed */
252 ret = dev_write_block(parent, nblk[i - 1]);
253 ASSERT(ret >= 0);
254 }
255 if (i != 1)
256 free(parent);
257
258 if (i < level) {
259 parent = dn->node_blk;
260 nids[i + 1] = get_nid(parent, offset[i], 0);
261 }
262 }
263
264 dn->nid = nids[level];
265 dn->ofs_in_node = offset[level];
266 dn->data_blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
267 dn->node_blkaddr = nblk[level];
268 return 0;
269 }
270