• 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 
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