• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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