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