1 /**
2 * segment.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
reserve_new_block(struct f2fs_sb_info * sbi,block_t * to,struct f2fs_summary * sum,int type,bool is_inode)19 int reserve_new_block(struct f2fs_sb_info *sbi, block_t *to,
20 struct f2fs_summary *sum, int type, bool is_inode)
21 {
22 struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
23 struct seg_entry *se;
24 u64 blkaddr, offset;
25 u64 old_blkaddr = *to;
26 bool is_node = IS_NODESEG(type);
27
28 if (old_blkaddr == NULL_ADDR) {
29 if (c.func == FSCK) {
30 if (fsck->chk.valid_blk_cnt >= sbi->user_block_count) {
31 ERR_MSG("Not enough space\n");
32 return -ENOSPC;
33 }
34 if (is_node && fsck->chk.valid_node_cnt >=
35 sbi->total_valid_node_count) {
36 ERR_MSG("Not enough space for node block\n");
37 return -ENOSPC;
38 }
39 } else {
40 if (sbi->total_valid_block_count >=
41 sbi->user_block_count) {
42 ERR_MSG("Not enough space\n");
43 return -ENOSPC;
44 }
45 if (is_node && sbi->total_valid_node_count >=
46 sbi->total_node_count) {
47 ERR_MSG("Not enough space for node block\n");
48 return -ENOSPC;
49 }
50 }
51 }
52
53 blkaddr = SM_I(sbi)->main_blkaddr;
54
55 if (find_next_free_block(sbi, &blkaddr, 0, type, false)) {
56 ERR_MSG("Can't find free block");
57 ASSERT(0);
58 }
59
60 se = get_seg_entry(sbi, GET_SEGNO(sbi, blkaddr));
61 offset = OFFSET_IN_SEG(sbi, blkaddr);
62 se->type = type;
63 se->valid_blocks++;
64 f2fs_set_bit(offset, (char *)se->cur_valid_map);
65 if (need_fsync_data_record(sbi)) {
66 se->ckpt_type = type;
67 se->ckpt_valid_blocks++;
68 f2fs_set_bit(offset, (char *)se->ckpt_valid_map);
69 }
70 if (c.func == FSCK) {
71 f2fs_set_main_bitmap(sbi, blkaddr, type);
72 f2fs_set_sit_bitmap(sbi, blkaddr);
73 }
74
75 if (old_blkaddr == NULL_ADDR) {
76 sbi->total_valid_block_count++;
77 if (is_node) {
78 sbi->total_valid_node_count++;
79 if (is_inode)
80 sbi->total_valid_inode_count++;
81 }
82 if (c.func == FSCK) {
83 fsck->chk.valid_blk_cnt++;
84 if (is_node) {
85 fsck->chk.valid_node_cnt++;
86 if (is_inode)
87 fsck->chk.valid_inode_cnt++;
88 }
89 }
90 }
91 se->dirty = 1;
92
93 /* read/write SSA */
94 *to = (block_t)blkaddr;
95 update_sum_entry(sbi, *to, sum);
96
97 return 0;
98 }
99
new_data_block(struct f2fs_sb_info * sbi,void * block,struct dnode_of_data * dn,int type)100 int new_data_block(struct f2fs_sb_info *sbi, void *block,
101 struct dnode_of_data *dn, int type)
102 {
103 struct f2fs_summary sum;
104 struct node_info ni;
105 unsigned int blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
106 int ret;
107
108 ASSERT(dn->node_blk);
109 memset(block, 0, BLOCK_SZ);
110
111 get_node_info(sbi, dn->nid, &ni);
112 set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
113 ret = reserve_new_block(sbi, &dn->data_blkaddr, &sum, type, 0);
114 if (ret) {
115 c.alloc_failed = 1;
116 return ret;
117 }
118
119 if (blkaddr == NULL_ADDR)
120 inc_inode_blocks(dn);
121 else if (blkaddr == NEW_ADDR)
122 dn->idirty = 1;
123 set_data_blkaddr(dn);
124 return 0;
125 }
126
f2fs_read(struct f2fs_sb_info * sbi,nid_t ino,u8 * buffer,u64 count,pgoff_t offset)127 u64 f2fs_read(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
128 u64 count, pgoff_t offset)
129 {
130 struct dnode_of_data dn;
131 struct node_info ni;
132 struct f2fs_node *inode;
133 char *blk_buffer;
134 u64 filesize;
135 u64 off_in_blk;
136 u64 len_in_blk;
137 u64 read_count;
138 u64 remained_blkentries;
139 block_t blkaddr;
140 void *index_node = NULL;
141
142 memset(&dn, 0, sizeof(dn));
143
144 /* Memory allocation for block buffer and inode. */
145 blk_buffer = calloc(BLOCK_SZ, 2);
146 ASSERT(blk_buffer);
147 inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ);
148
149 /* Read inode */
150 get_node_info(sbi, ino, &ni);
151 ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
152 ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
153 ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
154
155 /* Adjust count with file length. */
156 filesize = le64_to_cpu(inode->i.i_size);
157 if (offset > filesize)
158 count = 0;
159 else if (count + offset > filesize)
160 count = filesize - offset;
161
162 /* Main loop for file blocks */
163 read_count = remained_blkentries = 0;
164 while (count > 0) {
165 if (remained_blkentries == 0) {
166 set_new_dnode(&dn, inode, NULL, ino);
167 get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset),
168 LOOKUP_NODE);
169 if (index_node)
170 free(index_node);
171 index_node = (dn.node_blk == dn.inode_blk) ?
172 NULL : dn.node_blk;
173 remained_blkentries = ADDRS_PER_PAGE(sbi,
174 dn.node_blk, dn.inode_blk);
175 }
176 ASSERT(remained_blkentries > 0);
177
178 blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
179 if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR)
180 break;
181
182 off_in_blk = offset % BLOCK_SZ;
183 len_in_blk = BLOCK_SZ - off_in_blk;
184 if (len_in_blk > count)
185 len_in_blk = count;
186
187 /* Read data from single block. */
188 if (len_in_blk < BLOCK_SZ) {
189 ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0);
190 memcpy(buffer, blk_buffer + off_in_blk, len_in_blk);
191 } else {
192 /* Direct read */
193 ASSERT(dev_read_block(buffer, blkaddr) >= 0);
194 }
195
196 offset += len_in_blk;
197 count -= len_in_blk;
198 buffer += len_in_blk;
199 read_count += len_in_blk;
200
201 dn.ofs_in_node++;
202 remained_blkentries--;
203 }
204 if (index_node)
205 free(index_node);
206 free(blk_buffer);
207
208 return read_count;
209 }
210
f2fs_write(struct f2fs_sb_info * sbi,nid_t ino,u8 * buffer,u64 count,pgoff_t offset)211 u64 f2fs_write(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
212 u64 count, pgoff_t offset)
213 {
214 struct dnode_of_data dn;
215 struct node_info ni;
216 struct f2fs_node *inode;
217 char *blk_buffer;
218 u64 off_in_blk;
219 u64 len_in_blk;
220 u64 written_count;
221 u64 remained_blkentries;
222 block_t blkaddr;
223 void* index_node = NULL;
224 int idirty = 0;
225 int err;
226
227 /* Memory allocation for block buffer and inode. */
228 blk_buffer = calloc(BLOCK_SZ, 2);
229 ASSERT(blk_buffer);
230 inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ);
231
232 /* Read inode */
233 get_node_info(sbi, ino, &ni);
234 ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
235 ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
236 ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
237
238 /* Main loop for file blocks */
239 written_count = remained_blkentries = 0;
240 while (count > 0) {
241 if (remained_blkentries == 0) {
242 set_new_dnode(&dn, inode, NULL, ino);
243 err = get_dnode_of_data(sbi, &dn,
244 F2FS_BYTES_TO_BLK(offset), ALLOC_NODE);
245 if (err)
246 break;
247 idirty |= dn.idirty;
248 if (index_node)
249 free(index_node);
250 index_node = (dn.node_blk == dn.inode_blk) ?
251 NULL : dn.node_blk;
252 remained_blkentries = ADDRS_PER_PAGE(sbi,
253 dn.node_blk, dn.inode_blk);
254 }
255 ASSERT(remained_blkentries > 0);
256
257 blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
258 if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) {
259 err = new_data_block(sbi, blk_buffer,
260 &dn, CURSEG_WARM_DATA);
261 if (err)
262 break;
263 blkaddr = dn.data_blkaddr;
264 }
265
266 off_in_blk = offset % BLOCK_SZ;
267 len_in_blk = BLOCK_SZ - off_in_blk;
268 if (len_in_blk > count)
269 len_in_blk = count;
270
271 /* Write data to single block. */
272 if (len_in_blk < BLOCK_SZ) {
273 ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0);
274 memcpy(blk_buffer + off_in_blk, buffer, len_in_blk);
275 ASSERT(dev_write_block(blk_buffer, blkaddr) >= 0);
276 } else {
277 /* Direct write */
278 ASSERT(dev_write_block(buffer, blkaddr) >= 0);
279 }
280
281 offset += len_in_blk;
282 count -= len_in_blk;
283 buffer += len_in_blk;
284 written_count += len_in_blk;
285
286 dn.ofs_in_node++;
287 if ((--remained_blkentries == 0 || count == 0) && (dn.ndirty))
288 ASSERT(dev_write_block(dn.node_blk, dn.node_blkaddr) >= 0);
289 }
290 if (offset > le64_to_cpu(inode->i.i_size)) {
291 inode->i.i_size = cpu_to_le64(offset);
292 idirty = 1;
293 }
294 if (idirty) {
295 ASSERT(inode == dn.inode_blk);
296 ASSERT(write_inode(inode, ni.blk_addr) >= 0);
297 }
298 if (index_node)
299 free(index_node);
300 free(blk_buffer);
301
302 return written_count;
303 }
304
305 /* This function updates only inode->i.i_size */
f2fs_filesize_update(struct f2fs_sb_info * sbi,nid_t ino,u64 filesize)306 void f2fs_filesize_update(struct f2fs_sb_info *sbi, nid_t ino, u64 filesize)
307 {
308 struct node_info ni;
309 struct f2fs_node *inode;
310
311 inode = calloc(BLOCK_SZ, 1);
312 ASSERT(inode);
313 get_node_info(sbi, ino, &ni);
314
315 ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
316 ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
317 ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
318
319 inode->i.i_size = cpu_to_le64(filesize);
320
321 ASSERT(write_inode(inode, ni.blk_addr) >= 0);
322 free(inode);
323 }
324
f2fs_build_file(struct f2fs_sb_info * sbi,struct dentry * de)325 int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
326 {
327 int fd, n;
328 pgoff_t off = 0;
329 u8 buffer[BLOCK_SZ];
330
331 if (de->ino == 0)
332 return -1;
333
334 fd = open(de->full_path, O_RDONLY);
335 if (fd < 0) {
336 MSG(0, "Skip: Fail to open %s\n", de->full_path);
337 return -1;
338 }
339
340 /* inline_data support */
341 if (de->size <= DEF_MAX_INLINE_DATA) {
342 struct node_info ni;
343 struct f2fs_node *node_blk;
344 int ret;
345
346 get_node_info(sbi, de->ino, &ni);
347
348 node_blk = calloc(BLOCK_SZ, 1);
349 ASSERT(node_blk);
350
351 ret = dev_read_block(node_blk, ni.blk_addr);
352 ASSERT(ret >= 0);
353
354 node_blk->i.i_inline |= F2FS_INLINE_DATA;
355 node_blk->i.i_inline |= F2FS_DATA_EXIST;
356
357 if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
358 node_blk->i.i_inline |= F2FS_EXTRA_ATTR;
359 node_blk->i.i_extra_isize =
360 cpu_to_le16(calc_extra_isize());
361 }
362 n = read(fd, buffer, BLOCK_SZ);
363 ASSERT((unsigned long)n == de->size);
364 memcpy(inline_data_addr(node_blk), buffer, de->size);
365 node_blk->i.i_size = cpu_to_le64(de->size);
366 ASSERT(write_inode(node_blk, ni.blk_addr) >= 0);
367 free(node_blk);
368 } else {
369 while ((n = read(fd, buffer, BLOCK_SZ)) > 0) {
370 f2fs_write(sbi, de->ino, buffer, n, off);
371 off += n;
372 }
373 }
374
375 close(fd);
376 if (n < 0)
377 return -1;
378
379 update_free_segments(sbi);
380
381 MSG(1, "Info: Create %s -> %s\n"
382 " -- ino=%x, type=%x, mode=%x, uid=%x, "
383 "gid=%x, cap=%"PRIx64", size=%lu, pino=%x\n",
384 de->full_path, de->path,
385 de->ino, de->file_type, de->mode,
386 de->uid, de->gid, de->capabilities, de->size, de->pino);
387 return 0;
388 }
389