xref: /aosp_15_r20/external/f2fs-tools/fsck/segment.c (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
1*59bfda1fSAndroid Build Coastguard Worker /**
2*59bfda1fSAndroid Build Coastguard Worker  * segment.c
3*59bfda1fSAndroid Build Coastguard Worker  *
4*59bfda1fSAndroid Build Coastguard Worker  * Many parts of codes are copied from Linux kernel/fs/f2fs.
5*59bfda1fSAndroid Build Coastguard Worker  *
6*59bfda1fSAndroid Build Coastguard Worker  * Copyright (C) 2015 Huawei Ltd.
7*59bfda1fSAndroid Build Coastguard Worker  * Witten by:
8*59bfda1fSAndroid Build Coastguard Worker  *   Hou Pengyang <[email protected]>
9*59bfda1fSAndroid Build Coastguard Worker  *   Liu Shuoran <[email protected]>
10*59bfda1fSAndroid Build Coastguard Worker  *   Jaegeuk Kim <[email protected]>
11*59bfda1fSAndroid Build Coastguard Worker  * Copyright (c) 2020 Google Inc.
12*59bfda1fSAndroid Build Coastguard Worker  *   Robin Hsu <[email protected]>
13*59bfda1fSAndroid Build Coastguard Worker  *  : add sload compression support
14*59bfda1fSAndroid Build Coastguard Worker  *
15*59bfda1fSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
16*59bfda1fSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License version 2 as
17*59bfda1fSAndroid Build Coastguard Worker  * published by the Free Software Foundation.
18*59bfda1fSAndroid Build Coastguard Worker  */
19*59bfda1fSAndroid Build Coastguard Worker #include "fsck.h"
20*59bfda1fSAndroid Build Coastguard Worker #include "node.h"
21*59bfda1fSAndroid Build Coastguard Worker #include "quotaio.h"
22*59bfda1fSAndroid Build Coastguard Worker 
reserve_new_block(struct f2fs_sb_info * sbi,block_t * to,struct f2fs_summary * sum,int type,bool is_inode)23*59bfda1fSAndroid Build Coastguard Worker int reserve_new_block(struct f2fs_sb_info *sbi, block_t *to,
24*59bfda1fSAndroid Build Coastguard Worker 			struct f2fs_summary *sum, int type, bool is_inode)
25*59bfda1fSAndroid Build Coastguard Worker {
26*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
27*59bfda1fSAndroid Build Coastguard Worker 	struct seg_entry *se;
28*59bfda1fSAndroid Build Coastguard Worker 	u64 blkaddr, offset;
29*59bfda1fSAndroid Build Coastguard Worker 	u64 old_blkaddr = *to;
30*59bfda1fSAndroid Build Coastguard Worker 	bool is_node = IS_NODESEG(type);
31*59bfda1fSAndroid Build Coastguard Worker 	int left = 0;
32*59bfda1fSAndroid Build Coastguard Worker 
33*59bfda1fSAndroid Build Coastguard Worker 	if (old_blkaddr == NULL_ADDR) {
34*59bfda1fSAndroid Build Coastguard Worker 		if (c.func == FSCK) {
35*59bfda1fSAndroid Build Coastguard Worker 			if (fsck->chk.valid_blk_cnt >= sbi->user_block_count) {
36*59bfda1fSAndroid Build Coastguard Worker 				ERR_MSG("Not enough space\n");
37*59bfda1fSAndroid Build Coastguard Worker 				return -ENOSPC;
38*59bfda1fSAndroid Build Coastguard Worker 			}
39*59bfda1fSAndroid Build Coastguard Worker 			if (is_node && fsck->chk.valid_node_cnt >=
40*59bfda1fSAndroid Build Coastguard Worker 						sbi->total_node_count) {
41*59bfda1fSAndroid Build Coastguard Worker 				ERR_MSG("Not enough space for node block\n");
42*59bfda1fSAndroid Build Coastguard Worker 				return -ENOSPC;
43*59bfda1fSAndroid Build Coastguard Worker 			}
44*59bfda1fSAndroid Build Coastguard Worker 		} else {
45*59bfda1fSAndroid Build Coastguard Worker 			if (sbi->total_valid_block_count >=
46*59bfda1fSAndroid Build Coastguard Worker 						sbi->user_block_count) {
47*59bfda1fSAndroid Build Coastguard Worker 				ERR_MSG("Not enough space\n");
48*59bfda1fSAndroid Build Coastguard Worker 				return -ENOSPC;
49*59bfda1fSAndroid Build Coastguard Worker 			}
50*59bfda1fSAndroid Build Coastguard Worker 			if (is_node && sbi->total_valid_node_count >=
51*59bfda1fSAndroid Build Coastguard Worker 						sbi->total_node_count) {
52*59bfda1fSAndroid Build Coastguard Worker 				ERR_MSG("Not enough space for node block\n");
53*59bfda1fSAndroid Build Coastguard Worker 				return -ENOSPC;
54*59bfda1fSAndroid Build Coastguard Worker 			}
55*59bfda1fSAndroid Build Coastguard Worker 		}
56*59bfda1fSAndroid Build Coastguard Worker 	}
57*59bfda1fSAndroid Build Coastguard Worker 
58*59bfda1fSAndroid Build Coastguard Worker 	blkaddr = SM_I(sbi)->main_blkaddr;
59*59bfda1fSAndroid Build Coastguard Worker 
60*59bfda1fSAndroid Build Coastguard Worker 	if (le32_to_cpu(sbi->raw_super->feature) & F2FS_FEATURE_RO) {
61*59bfda1fSAndroid Build Coastguard Worker 		if (IS_NODESEG(type)) {
62*59bfda1fSAndroid Build Coastguard Worker 			type = CURSEG_HOT_NODE;
63*59bfda1fSAndroid Build Coastguard Worker 			blkaddr = __end_block_addr(sbi);
64*59bfda1fSAndroid Build Coastguard Worker 			left = 1;
65*59bfda1fSAndroid Build Coastguard Worker 		} else if (IS_DATASEG(type)) {
66*59bfda1fSAndroid Build Coastguard Worker 			type = CURSEG_HOT_DATA;
67*59bfda1fSAndroid Build Coastguard Worker 			blkaddr = SM_I(sbi)->main_blkaddr;
68*59bfda1fSAndroid Build Coastguard Worker 			left = 0;
69*59bfda1fSAndroid Build Coastguard Worker 		}
70*59bfda1fSAndroid Build Coastguard Worker 	}
71*59bfda1fSAndroid Build Coastguard Worker 
72*59bfda1fSAndroid Build Coastguard Worker 	if (find_next_free_block(sbi, &blkaddr, left, type, false)) {
73*59bfda1fSAndroid Build Coastguard Worker 		ERR_MSG("Can't find free block");
74*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(0);
75*59bfda1fSAndroid Build Coastguard Worker 	}
76*59bfda1fSAndroid Build Coastguard Worker 
77*59bfda1fSAndroid Build Coastguard Worker 	se = get_seg_entry(sbi, GET_SEGNO(sbi, blkaddr));
78*59bfda1fSAndroid Build Coastguard Worker 	offset = OFFSET_IN_SEG(sbi, blkaddr);
79*59bfda1fSAndroid Build Coastguard Worker 	se->type = se->orig_type = type;
80*59bfda1fSAndroid Build Coastguard Worker 	if (se->valid_blocks == 0)
81*59bfda1fSAndroid Build Coastguard Worker 		SM_I(sbi)->free_segments--;
82*59bfda1fSAndroid Build Coastguard Worker 	se->valid_blocks++;
83*59bfda1fSAndroid Build Coastguard Worker 	f2fs_set_bit(offset, (char *)se->cur_valid_map);
84*59bfda1fSAndroid Build Coastguard Worker 	if (need_fsync_data_record(sbi)) {
85*59bfda1fSAndroid Build Coastguard Worker 		se->ckpt_type = type;
86*59bfda1fSAndroid Build Coastguard Worker 		se->ckpt_valid_blocks++;
87*59bfda1fSAndroid Build Coastguard Worker 		f2fs_set_bit(offset, (char *)se->ckpt_valid_map);
88*59bfda1fSAndroid Build Coastguard Worker 	}
89*59bfda1fSAndroid Build Coastguard Worker 	if (c.func == FSCK) {
90*59bfda1fSAndroid Build Coastguard Worker 		f2fs_set_main_bitmap(sbi, blkaddr, type);
91*59bfda1fSAndroid Build Coastguard Worker 		f2fs_set_sit_bitmap(sbi, blkaddr);
92*59bfda1fSAndroid Build Coastguard Worker 	}
93*59bfda1fSAndroid Build Coastguard Worker 
94*59bfda1fSAndroid Build Coastguard Worker 	if (old_blkaddr == NULL_ADDR) {
95*59bfda1fSAndroid Build Coastguard Worker 		sbi->total_valid_block_count++;
96*59bfda1fSAndroid Build Coastguard Worker 		if (is_node) {
97*59bfda1fSAndroid Build Coastguard Worker 			sbi->total_valid_node_count++;
98*59bfda1fSAndroid Build Coastguard Worker 			if (is_inode)
99*59bfda1fSAndroid Build Coastguard Worker 				sbi->total_valid_inode_count++;
100*59bfda1fSAndroid Build Coastguard Worker 		}
101*59bfda1fSAndroid Build Coastguard Worker 		if (c.func == FSCK) {
102*59bfda1fSAndroid Build Coastguard Worker 			fsck->chk.valid_blk_cnt++;
103*59bfda1fSAndroid Build Coastguard Worker 			if (is_node) {
104*59bfda1fSAndroid Build Coastguard Worker 				fsck->chk.valid_nat_entry_cnt++;
105*59bfda1fSAndroid Build Coastguard Worker 				fsck->chk.valid_node_cnt++;
106*59bfda1fSAndroid Build Coastguard Worker 				if (is_inode)
107*59bfda1fSAndroid Build Coastguard Worker 					fsck->chk.valid_inode_cnt++;
108*59bfda1fSAndroid Build Coastguard Worker 			}
109*59bfda1fSAndroid Build Coastguard Worker 		}
110*59bfda1fSAndroid Build Coastguard Worker 	}
111*59bfda1fSAndroid Build Coastguard Worker 	se->dirty = 1;
112*59bfda1fSAndroid Build Coastguard Worker 
113*59bfda1fSAndroid Build Coastguard Worker 	/* read/write SSA */
114*59bfda1fSAndroid Build Coastguard Worker 	*to = (block_t)blkaddr;
115*59bfda1fSAndroid Build Coastguard Worker 	update_sum_entry(sbi, *to, sum);
116*59bfda1fSAndroid Build Coastguard Worker 
117*59bfda1fSAndroid Build Coastguard Worker 	return 0;
118*59bfda1fSAndroid Build Coastguard Worker }
119*59bfda1fSAndroid Build Coastguard Worker 
new_data_block(struct f2fs_sb_info * sbi,void * block,struct dnode_of_data * dn,int type)120*59bfda1fSAndroid Build Coastguard Worker int new_data_block(struct f2fs_sb_info *sbi, void *block,
121*59bfda1fSAndroid Build Coastguard Worker 				struct dnode_of_data *dn, int type)
122*59bfda1fSAndroid Build Coastguard Worker {
123*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
124*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_summary sum;
125*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
126*59bfda1fSAndroid Build Coastguard Worker 	unsigned int blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
127*59bfda1fSAndroid Build Coastguard Worker 	int ret;
128*59bfda1fSAndroid Build Coastguard Worker 
129*59bfda1fSAndroid Build Coastguard Worker 	if ((get_sb(feature) & F2FS_FEATURE_RO) &&
130*59bfda1fSAndroid Build Coastguard Worker 					type != CURSEG_HOT_DATA)
131*59bfda1fSAndroid Build Coastguard Worker 		type = CURSEG_HOT_DATA;
132*59bfda1fSAndroid Build Coastguard Worker 
133*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(dn->node_blk);
134*59bfda1fSAndroid Build Coastguard Worker 	memset(block, 0, F2FS_BLKSIZE);
135*59bfda1fSAndroid Build Coastguard Worker 
136*59bfda1fSAndroid Build Coastguard Worker 	get_node_info(sbi, dn->nid, &ni);
137*59bfda1fSAndroid Build Coastguard Worker 	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
138*59bfda1fSAndroid Build Coastguard Worker 
139*59bfda1fSAndroid Build Coastguard Worker 	dn->data_blkaddr = blkaddr;
140*59bfda1fSAndroid Build Coastguard Worker 	ret = reserve_new_block(sbi, &dn->data_blkaddr, &sum, type, 0);
141*59bfda1fSAndroid Build Coastguard Worker 	if (ret) {
142*59bfda1fSAndroid Build Coastguard Worker 		c.alloc_failed = 1;
143*59bfda1fSAndroid Build Coastguard Worker 		return ret;
144*59bfda1fSAndroid Build Coastguard Worker 	}
145*59bfda1fSAndroid Build Coastguard Worker 
146*59bfda1fSAndroid Build Coastguard Worker 	if (blkaddr == NULL_ADDR)
147*59bfda1fSAndroid Build Coastguard Worker 		inc_inode_blocks(dn);
148*59bfda1fSAndroid Build Coastguard Worker 	else if (blkaddr == NEW_ADDR)
149*59bfda1fSAndroid Build Coastguard Worker 		dn->idirty = 1;
150*59bfda1fSAndroid Build Coastguard Worker 	set_data_blkaddr(dn);
151*59bfda1fSAndroid Build Coastguard Worker 	return 0;
152*59bfda1fSAndroid Build Coastguard Worker }
153*59bfda1fSAndroid Build Coastguard Worker 
f2fs_quota_size(struct quota_file * qf)154*59bfda1fSAndroid Build Coastguard Worker u64 f2fs_quota_size(struct quota_file *qf)
155*59bfda1fSAndroid Build Coastguard Worker {
156*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
157*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_node *inode;
158*59bfda1fSAndroid Build Coastguard Worker 	u64 filesize;
159*59bfda1fSAndroid Build Coastguard Worker 
160*59bfda1fSAndroid Build Coastguard Worker 	inode = (struct f2fs_node *) calloc(F2FS_BLKSIZE, 1);
161*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(inode);
162*59bfda1fSAndroid Build Coastguard Worker 
163*59bfda1fSAndroid Build Coastguard Worker 	/* Read inode */
164*59bfda1fSAndroid Build Coastguard Worker 	get_node_info(qf->sbi, qf->ino, &ni);
165*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
166*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(S_ISREG(le16_to_cpu(inode->i.i_mode)));
167*59bfda1fSAndroid Build Coastguard Worker 
168*59bfda1fSAndroid Build Coastguard Worker 	filesize = le64_to_cpu(inode->i.i_size);
169*59bfda1fSAndroid Build Coastguard Worker 	free(inode);
170*59bfda1fSAndroid Build Coastguard Worker 	return filesize;
171*59bfda1fSAndroid Build Coastguard Worker }
172*59bfda1fSAndroid Build Coastguard Worker 
f2fs_read(struct f2fs_sb_info * sbi,nid_t ino,u8 * buffer,u64 count,pgoff_t offset)173*59bfda1fSAndroid Build Coastguard Worker u64 f2fs_read(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
174*59bfda1fSAndroid Build Coastguard Worker 					u64 count, pgoff_t offset)
175*59bfda1fSAndroid Build Coastguard Worker {
176*59bfda1fSAndroid Build Coastguard Worker 	struct dnode_of_data dn;
177*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
178*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_node *inode;
179*59bfda1fSAndroid Build Coastguard Worker 	char *blk_buffer;
180*59bfda1fSAndroid Build Coastguard Worker 	u64 filesize;
181*59bfda1fSAndroid Build Coastguard Worker 	u64 off_in_blk;
182*59bfda1fSAndroid Build Coastguard Worker 	u64 len_in_blk;
183*59bfda1fSAndroid Build Coastguard Worker 	u64 read_count;
184*59bfda1fSAndroid Build Coastguard Worker 	u64 remained_blkentries;
185*59bfda1fSAndroid Build Coastguard Worker 	block_t blkaddr;
186*59bfda1fSAndroid Build Coastguard Worker 	void *index_node = NULL;
187*59bfda1fSAndroid Build Coastguard Worker 
188*59bfda1fSAndroid Build Coastguard Worker 	memset(&dn, 0, sizeof(dn));
189*59bfda1fSAndroid Build Coastguard Worker 
190*59bfda1fSAndroid Build Coastguard Worker 	/* Memory allocation for block buffer and inode. */
191*59bfda1fSAndroid Build Coastguard Worker 	blk_buffer = calloc(F2FS_BLKSIZE, 2);
192*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(blk_buffer);
193*59bfda1fSAndroid Build Coastguard Worker 	inode = (struct f2fs_node*)(blk_buffer + F2FS_BLKSIZE);
194*59bfda1fSAndroid Build Coastguard Worker 
195*59bfda1fSAndroid Build Coastguard Worker 	/* Read inode */
196*59bfda1fSAndroid Build Coastguard Worker 	get_node_info(sbi, ino, &ni);
197*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
198*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
199*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
200*59bfda1fSAndroid Build Coastguard Worker 
201*59bfda1fSAndroid Build Coastguard Worker 	/* Adjust count with file length. */
202*59bfda1fSAndroid Build Coastguard Worker 	filesize = le64_to_cpu(inode->i.i_size);
203*59bfda1fSAndroid Build Coastguard Worker 	if (offset > filesize)
204*59bfda1fSAndroid Build Coastguard Worker 		count = 0;
205*59bfda1fSAndroid Build Coastguard Worker 	else if (count + offset > filesize)
206*59bfda1fSAndroid Build Coastguard Worker 		count = filesize - offset;
207*59bfda1fSAndroid Build Coastguard Worker 
208*59bfda1fSAndroid Build Coastguard Worker 	/* Main loop for file blocks */
209*59bfda1fSAndroid Build Coastguard Worker 	read_count = remained_blkentries = 0;
210*59bfda1fSAndroid Build Coastguard Worker 	while (count > 0) {
211*59bfda1fSAndroid Build Coastguard Worker 		if (remained_blkentries == 0) {
212*59bfda1fSAndroid Build Coastguard Worker 			set_new_dnode(&dn, inode, NULL, ino);
213*59bfda1fSAndroid Build Coastguard Worker 			get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset),
214*59bfda1fSAndroid Build Coastguard Worker 					LOOKUP_NODE);
215*59bfda1fSAndroid Build Coastguard Worker 			if (index_node)
216*59bfda1fSAndroid Build Coastguard Worker 				free(index_node);
217*59bfda1fSAndroid Build Coastguard Worker 			index_node = (dn.node_blk == dn.inode_blk) ?
218*59bfda1fSAndroid Build Coastguard Worker 							NULL : dn.node_blk;
219*59bfda1fSAndroid Build Coastguard Worker 			remained_blkentries = ADDRS_PER_PAGE(sbi,
220*59bfda1fSAndroid Build Coastguard Worker 						dn.node_blk, dn.inode_blk);
221*59bfda1fSAndroid Build Coastguard Worker 		}
222*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(remained_blkentries > 0);
223*59bfda1fSAndroid Build Coastguard Worker 
224*59bfda1fSAndroid Build Coastguard Worker 		blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
225*59bfda1fSAndroid Build Coastguard Worker 		if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR)
226*59bfda1fSAndroid Build Coastguard Worker 			break;
227*59bfda1fSAndroid Build Coastguard Worker 
228*59bfda1fSAndroid Build Coastguard Worker 		off_in_blk = offset % F2FS_BLKSIZE;
229*59bfda1fSAndroid Build Coastguard Worker 		len_in_blk = F2FS_BLKSIZE - off_in_blk;
230*59bfda1fSAndroid Build Coastguard Worker 		if (len_in_blk > count)
231*59bfda1fSAndroid Build Coastguard Worker 			len_in_blk = count;
232*59bfda1fSAndroid Build Coastguard Worker 
233*59bfda1fSAndroid Build Coastguard Worker 		/* Read data from single block. */
234*59bfda1fSAndroid Build Coastguard Worker 		if (len_in_blk < F2FS_BLKSIZE) {
235*59bfda1fSAndroid Build Coastguard Worker 			ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0);
236*59bfda1fSAndroid Build Coastguard Worker 			memcpy(buffer, blk_buffer + off_in_blk, len_in_blk);
237*59bfda1fSAndroid Build Coastguard Worker 		} else {
238*59bfda1fSAndroid Build Coastguard Worker 			/* Direct read */
239*59bfda1fSAndroid Build Coastguard Worker 			ASSERT(dev_read_block(buffer, blkaddr) >= 0);
240*59bfda1fSAndroid Build Coastguard Worker 		}
241*59bfda1fSAndroid Build Coastguard Worker 
242*59bfda1fSAndroid Build Coastguard Worker 		offset += len_in_blk;
243*59bfda1fSAndroid Build Coastguard Worker 		count -= len_in_blk;
244*59bfda1fSAndroid Build Coastguard Worker 		buffer += len_in_blk;
245*59bfda1fSAndroid Build Coastguard Worker 		read_count += len_in_blk;
246*59bfda1fSAndroid Build Coastguard Worker 
247*59bfda1fSAndroid Build Coastguard Worker 		dn.ofs_in_node++;
248*59bfda1fSAndroid Build Coastguard Worker 		remained_blkentries--;
249*59bfda1fSAndroid Build Coastguard Worker 	}
250*59bfda1fSAndroid Build Coastguard Worker 	if (index_node)
251*59bfda1fSAndroid Build Coastguard Worker 		free(index_node);
252*59bfda1fSAndroid Build Coastguard Worker 	free(blk_buffer);
253*59bfda1fSAndroid Build Coastguard Worker 
254*59bfda1fSAndroid Build Coastguard Worker 	return read_count;
255*59bfda1fSAndroid Build Coastguard Worker }
256*59bfda1fSAndroid Build Coastguard Worker 
257*59bfda1fSAndroid Build Coastguard Worker /*
258*59bfda1fSAndroid Build Coastguard Worker  * Do not call this function directly.  Instead, call one of the following:
259*59bfda1fSAndroid Build Coastguard Worker  *     u64 f2fs_write();
260*59bfda1fSAndroid Build Coastguard Worker  *     u64 f2fs_write_compress_data();
261*59bfda1fSAndroid Build Coastguard Worker  *     u64 f2fs_write_addrtag();
262*59bfda1fSAndroid Build Coastguard Worker  */
f2fs_write_ex(struct f2fs_sb_info * sbi,nid_t ino,u8 * buffer,u64 count,pgoff_t offset,enum wr_addr_type addr_type)263*59bfda1fSAndroid Build Coastguard Worker static u64 f2fs_write_ex(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
264*59bfda1fSAndroid Build Coastguard Worker 		u64 count, pgoff_t offset, enum wr_addr_type addr_type)
265*59bfda1fSAndroid Build Coastguard Worker {
266*59bfda1fSAndroid Build Coastguard Worker 	struct dnode_of_data dn;
267*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
268*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_node *inode;
269*59bfda1fSAndroid Build Coastguard Worker 	char *blk_buffer;
270*59bfda1fSAndroid Build Coastguard Worker 	void *wbuf;
271*59bfda1fSAndroid Build Coastguard Worker 	u64 off_in_blk;
272*59bfda1fSAndroid Build Coastguard Worker 	u64 len_in_blk;
273*59bfda1fSAndroid Build Coastguard Worker 	u64 written_count;
274*59bfda1fSAndroid Build Coastguard Worker 	u64 remained_blkentries;
275*59bfda1fSAndroid Build Coastguard Worker 	block_t blkaddr;
276*59bfda1fSAndroid Build Coastguard Worker 	void* index_node = NULL;
277*59bfda1fSAndroid Build Coastguard Worker 	int idirty = 0;
278*59bfda1fSAndroid Build Coastguard Worker 	int err, ret;
279*59bfda1fSAndroid Build Coastguard Worker 	bool datablk_alloced = false;
280*59bfda1fSAndroid Build Coastguard Worker 	bool has_data = (addr_type == WR_NORMAL
281*59bfda1fSAndroid Build Coastguard Worker 			|| addr_type == WR_COMPRESS_DATA);
282*59bfda1fSAndroid Build Coastguard Worker 
283*59bfda1fSAndroid Build Coastguard Worker 	if (count == 0)
284*59bfda1fSAndroid Build Coastguard Worker 		return 0;
285*59bfda1fSAndroid Build Coastguard Worker 
286*59bfda1fSAndroid Build Coastguard Worker 	/*
287*59bfda1fSAndroid Build Coastguard Worker 	 * Enforce calling from f2fs_write(), f2fs_write_compress_data(),
288*59bfda1fSAndroid Build Coastguard Worker 	 * and f2fs_write_addrtag().   Beside, check if is properly called.
289*59bfda1fSAndroid Build Coastguard Worker 	 */
290*59bfda1fSAndroid Build Coastguard Worker 	ASSERT((!has_data && buffer == NULL) || (has_data && buffer != NULL));
291*59bfda1fSAndroid Build Coastguard Worker 	if (addr_type != WR_NORMAL)
292*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(offset % F2FS_BLKSIZE == 0); /* block boundary only */
293*59bfda1fSAndroid Build Coastguard Worker 
294*59bfda1fSAndroid Build Coastguard Worker 	/* Memory allocation for block buffer and inode. */
295*59bfda1fSAndroid Build Coastguard Worker 	blk_buffer = calloc(F2FS_BLKSIZE, 2);
296*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(blk_buffer);
297*59bfda1fSAndroid Build Coastguard Worker 	inode = (struct f2fs_node*)(blk_buffer + F2FS_BLKSIZE);
298*59bfda1fSAndroid Build Coastguard Worker 
299*59bfda1fSAndroid Build Coastguard Worker 	/* Read inode */
300*59bfda1fSAndroid Build Coastguard Worker 	get_node_info(sbi, ino, &ni);
301*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
302*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
303*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
304*59bfda1fSAndroid Build Coastguard Worker 
305*59bfda1fSAndroid Build Coastguard Worker 	/* Main loop for file blocks */
306*59bfda1fSAndroid Build Coastguard Worker 	written_count = remained_blkentries = 0;
307*59bfda1fSAndroid Build Coastguard Worker 	while (count > 0) {
308*59bfda1fSAndroid Build Coastguard Worker 		if (remained_blkentries == 0) {
309*59bfda1fSAndroid Build Coastguard Worker 			set_new_dnode(&dn, inode, NULL, ino);
310*59bfda1fSAndroid Build Coastguard Worker 			err = get_dnode_of_data(sbi, &dn,
311*59bfda1fSAndroid Build Coastguard Worker 					F2FS_BYTES_TO_BLK(offset), ALLOC_NODE);
312*59bfda1fSAndroid Build Coastguard Worker 			if (err)
313*59bfda1fSAndroid Build Coastguard Worker 				break;
314*59bfda1fSAndroid Build Coastguard Worker 			idirty |= dn.idirty;
315*59bfda1fSAndroid Build Coastguard Worker 			free(index_node);
316*59bfda1fSAndroid Build Coastguard Worker 			index_node = (dn.node_blk == dn.inode_blk) ?
317*59bfda1fSAndroid Build Coastguard Worker 					NULL : dn.node_blk;
318*59bfda1fSAndroid Build Coastguard Worker 			remained_blkentries = ADDRS_PER_PAGE(sbi,
319*59bfda1fSAndroid Build Coastguard Worker 					dn.node_blk, dn.inode_blk) -
320*59bfda1fSAndroid Build Coastguard Worker 					dn.ofs_in_node;
321*59bfda1fSAndroid Build Coastguard Worker 		}
322*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(remained_blkentries > 0);
323*59bfda1fSAndroid Build Coastguard Worker 
324*59bfda1fSAndroid Build Coastguard Worker 		if (!has_data) {
325*59bfda1fSAndroid Build Coastguard Worker 			struct seg_entry *se;
326*59bfda1fSAndroid Build Coastguard Worker 
327*59bfda1fSAndroid Build Coastguard Worker 			se = get_seg_entry(sbi, GET_SEGNO(sbi, dn.node_blkaddr));
328*59bfda1fSAndroid Build Coastguard Worker 			dn.data_blkaddr = addr_type;
329*59bfda1fSAndroid Build Coastguard Worker 			set_data_blkaddr(&dn);
330*59bfda1fSAndroid Build Coastguard Worker 			idirty |= dn.idirty;
331*59bfda1fSAndroid Build Coastguard Worker 			if (dn.ndirty) {
332*59bfda1fSAndroid Build Coastguard Worker 				ret = dn.alloced ? dev_write_block(dn.node_blk,
333*59bfda1fSAndroid Build Coastguard Worker 					dn.node_blkaddr,
334*59bfda1fSAndroid Build Coastguard Worker 					f2fs_io_type_to_rw_hint(se->type)) :
335*59bfda1fSAndroid Build Coastguard Worker 					update_block(sbi, dn.node_blk,
336*59bfda1fSAndroid Build Coastguard Worker 					&dn.node_blkaddr, NULL);
337*59bfda1fSAndroid Build Coastguard Worker 				ASSERT(ret >= 0);
338*59bfda1fSAndroid Build Coastguard Worker 			}
339*59bfda1fSAndroid Build Coastguard Worker 			written_count = 0;
340*59bfda1fSAndroid Build Coastguard Worker 			break;
341*59bfda1fSAndroid Build Coastguard Worker 		}
342*59bfda1fSAndroid Build Coastguard Worker 
343*59bfda1fSAndroid Build Coastguard Worker 		datablk_alloced = false;
344*59bfda1fSAndroid Build Coastguard Worker 		blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
345*59bfda1fSAndroid Build Coastguard Worker 		if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) {
346*59bfda1fSAndroid Build Coastguard Worker 			err = new_data_block(sbi, blk_buffer,
347*59bfda1fSAndroid Build Coastguard Worker 						&dn, CURSEG_WARM_DATA);
348*59bfda1fSAndroid Build Coastguard Worker 			if (err)
349*59bfda1fSAndroid Build Coastguard Worker 				break;
350*59bfda1fSAndroid Build Coastguard Worker 			blkaddr = dn.data_blkaddr;
351*59bfda1fSAndroid Build Coastguard Worker 			idirty |= dn.idirty;
352*59bfda1fSAndroid Build Coastguard Worker 			datablk_alloced = true;
353*59bfda1fSAndroid Build Coastguard Worker 		}
354*59bfda1fSAndroid Build Coastguard Worker 
355*59bfda1fSAndroid Build Coastguard Worker 		off_in_blk = offset % F2FS_BLKSIZE;
356*59bfda1fSAndroid Build Coastguard Worker 		len_in_blk = F2FS_BLKSIZE - off_in_blk;
357*59bfda1fSAndroid Build Coastguard Worker 		if (len_in_blk > count)
358*59bfda1fSAndroid Build Coastguard Worker 			len_in_blk = count;
359*59bfda1fSAndroid Build Coastguard Worker 
360*59bfda1fSAndroid Build Coastguard Worker 		/* Write data to single block. */
361*59bfda1fSAndroid Build Coastguard Worker 		if (len_in_blk < F2FS_BLKSIZE) {
362*59bfda1fSAndroid Build Coastguard Worker 			ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0);
363*59bfda1fSAndroid Build Coastguard Worker 			memcpy(blk_buffer + off_in_blk, buffer, len_in_blk);
364*59bfda1fSAndroid Build Coastguard Worker 			wbuf = blk_buffer;
365*59bfda1fSAndroid Build Coastguard Worker 		} else {
366*59bfda1fSAndroid Build Coastguard Worker 			/* Direct write */
367*59bfda1fSAndroid Build Coastguard Worker 			wbuf = buffer;
368*59bfda1fSAndroid Build Coastguard Worker 		}
369*59bfda1fSAndroid Build Coastguard Worker 
370*59bfda1fSAndroid Build Coastguard Worker 		if (c.zoned_model == F2FS_ZONED_HM) {
371*59bfda1fSAndroid Build Coastguard Worker 			if (datablk_alloced) {
372*59bfda1fSAndroid Build Coastguard Worker 				ret = dev_write_block(wbuf, blkaddr,
373*59bfda1fSAndroid Build Coastguard Worker 					f2fs_io_type_to_rw_hint(CURSEG_WARM_DATA));
374*59bfda1fSAndroid Build Coastguard Worker 			} else {
375*59bfda1fSAndroid Build Coastguard Worker 				ret = update_block(sbi, wbuf, &blkaddr,
376*59bfda1fSAndroid Build Coastguard Worker 						dn.node_blk);
377*59bfda1fSAndroid Build Coastguard Worker 				if (dn.inode_blk == dn.node_blk)
378*59bfda1fSAndroid Build Coastguard Worker 					idirty = 1;
379*59bfda1fSAndroid Build Coastguard Worker 				else
380*59bfda1fSAndroid Build Coastguard Worker 					dn.ndirty = 1;
381*59bfda1fSAndroid Build Coastguard Worker 			}
382*59bfda1fSAndroid Build Coastguard Worker 		} else {
383*59bfda1fSAndroid Build Coastguard Worker 			ret = dev_write_block(wbuf, blkaddr,
384*59bfda1fSAndroid Build Coastguard Worker 					f2fs_io_type_to_rw_hint(CURSEG_WARM_DATA));
385*59bfda1fSAndroid Build Coastguard Worker 		}
386*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(ret >= 0);
387*59bfda1fSAndroid Build Coastguard Worker 
388*59bfda1fSAndroid Build Coastguard Worker 		offset += len_in_blk;
389*59bfda1fSAndroid Build Coastguard Worker 		count -= len_in_blk;
390*59bfda1fSAndroid Build Coastguard Worker 		buffer += len_in_blk;
391*59bfda1fSAndroid Build Coastguard Worker 		written_count += len_in_blk;
392*59bfda1fSAndroid Build Coastguard Worker 
393*59bfda1fSAndroid Build Coastguard Worker 		dn.ofs_in_node++;
394*59bfda1fSAndroid Build Coastguard Worker 		if ((--remained_blkentries == 0 || count == 0) && (dn.ndirty)) {
395*59bfda1fSAndroid Build Coastguard Worker 			struct seg_entry *se;
396*59bfda1fSAndroid Build Coastguard Worker 			se = get_seg_entry(sbi, GET_SEGNO(sbi, dn.node_blkaddr));
397*59bfda1fSAndroid Build Coastguard Worker 			ret = dn.alloced ?
398*59bfda1fSAndroid Build Coastguard Worker 				dev_write_block(dn.node_blk, dn.node_blkaddr,
399*59bfda1fSAndroid Build Coastguard Worker 						f2fs_io_type_to_rw_hint(se->type)) :
400*59bfda1fSAndroid Build Coastguard Worker 				update_block(sbi, dn.node_blk, &dn.node_blkaddr, NULL);
401*59bfda1fSAndroid Build Coastguard Worker 			ASSERT(ret >= 0);
402*59bfda1fSAndroid Build Coastguard Worker 		}
403*59bfda1fSAndroid Build Coastguard Worker 	}
404*59bfda1fSAndroid Build Coastguard Worker 
405*59bfda1fSAndroid Build Coastguard Worker 	if (addr_type == WR_NORMAL && offset > le64_to_cpu(inode->i.i_size)) {
406*59bfda1fSAndroid Build Coastguard Worker 		inode->i.i_size = cpu_to_le64(offset);
407*59bfda1fSAndroid Build Coastguard Worker 		idirty = 1;
408*59bfda1fSAndroid Build Coastguard Worker 	}
409*59bfda1fSAndroid Build Coastguard Worker 	if (idirty) {
410*59bfda1fSAndroid Build Coastguard Worker 		get_node_info(sbi, ino, &ni);
411*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(inode == dn.inode_blk);
412*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(update_inode(sbi, inode, &ni.blk_addr) >= 0);
413*59bfda1fSAndroid Build Coastguard Worker 	}
414*59bfda1fSAndroid Build Coastguard Worker 
415*59bfda1fSAndroid Build Coastguard Worker 	free(index_node);
416*59bfda1fSAndroid Build Coastguard Worker 	free(blk_buffer);
417*59bfda1fSAndroid Build Coastguard Worker 
418*59bfda1fSAndroid Build Coastguard Worker 	return written_count;
419*59bfda1fSAndroid Build Coastguard Worker }
420*59bfda1fSAndroid Build Coastguard Worker 
f2fs_write(struct f2fs_sb_info * sbi,nid_t ino,u8 * buffer,u64 count,pgoff_t offset)421*59bfda1fSAndroid Build Coastguard Worker u64 f2fs_write(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
422*59bfda1fSAndroid Build Coastguard Worker 					u64 count, pgoff_t offset)
423*59bfda1fSAndroid Build Coastguard Worker {
424*59bfda1fSAndroid Build Coastguard Worker 	return f2fs_write_ex(sbi, ino, buffer, count, offset, WR_NORMAL);
425*59bfda1fSAndroid Build Coastguard Worker }
426*59bfda1fSAndroid Build Coastguard Worker 
f2fs_write_compress_data(struct f2fs_sb_info * sbi,nid_t ino,u8 * buffer,u64 count,pgoff_t offset)427*59bfda1fSAndroid Build Coastguard Worker u64 f2fs_write_compress_data(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
428*59bfda1fSAndroid Build Coastguard Worker 					u64 count, pgoff_t offset)
429*59bfda1fSAndroid Build Coastguard Worker {
430*59bfda1fSAndroid Build Coastguard Worker 	return f2fs_write_ex(sbi, ino, buffer, count, offset, WR_COMPRESS_DATA);
431*59bfda1fSAndroid Build Coastguard Worker }
432*59bfda1fSAndroid Build Coastguard Worker 
f2fs_write_addrtag(struct f2fs_sb_info * sbi,nid_t ino,pgoff_t offset,unsigned int addrtag)433*59bfda1fSAndroid Build Coastguard Worker u64 f2fs_write_addrtag(struct f2fs_sb_info *sbi, nid_t ino, pgoff_t offset,
434*59bfda1fSAndroid Build Coastguard Worker 		unsigned int addrtag)
435*59bfda1fSAndroid Build Coastguard Worker {
436*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(addrtag == COMPRESS_ADDR || addrtag == NEW_ADDR
437*59bfda1fSAndroid Build Coastguard Worker 			|| addrtag == NULL_ADDR);
438*59bfda1fSAndroid Build Coastguard Worker 	return f2fs_write_ex(sbi, ino, NULL, F2FS_BLKSIZE, offset, addrtag);
439*59bfda1fSAndroid Build Coastguard Worker }
440*59bfda1fSAndroid Build Coastguard Worker 
441*59bfda1fSAndroid Build Coastguard Worker /* This function updates only inode->i.i_size */
f2fs_filesize_update(struct f2fs_sb_info * sbi,nid_t ino,u64 filesize)442*59bfda1fSAndroid Build Coastguard Worker void f2fs_filesize_update(struct f2fs_sb_info *sbi, nid_t ino, u64 filesize)
443*59bfda1fSAndroid Build Coastguard Worker {
444*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
445*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_node *inode;
446*59bfda1fSAndroid Build Coastguard Worker 
447*59bfda1fSAndroid Build Coastguard Worker 	inode = calloc(F2FS_BLKSIZE, 1);
448*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(inode);
449*59bfda1fSAndroid Build Coastguard Worker 	get_node_info(sbi, ino, &ni);
450*59bfda1fSAndroid Build Coastguard Worker 
451*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
452*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
453*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
454*59bfda1fSAndroid Build Coastguard Worker 
455*59bfda1fSAndroid Build Coastguard Worker 	inode->i.i_size = cpu_to_le64(filesize);
456*59bfda1fSAndroid Build Coastguard Worker 
457*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(update_inode(sbi, inode, &ni.blk_addr) >= 0);
458*59bfda1fSAndroid Build Coastguard Worker 	free(inode);
459*59bfda1fSAndroid Build Coastguard Worker }
460*59bfda1fSAndroid Build Coastguard Worker 
461*59bfda1fSAndroid Build Coastguard Worker #define MAX_BULKR_RETRY 5
bulkread(int fd,void * rbuf,size_t rsize,bool * eof)462*59bfda1fSAndroid Build Coastguard Worker int bulkread(int fd, void *rbuf, size_t rsize, bool *eof)
463*59bfda1fSAndroid Build Coastguard Worker {
464*59bfda1fSAndroid Build Coastguard Worker 	int n = 0;
465*59bfda1fSAndroid Build Coastguard Worker 	int retry = MAX_BULKR_RETRY;
466*59bfda1fSAndroid Build Coastguard Worker 	int cur;
467*59bfda1fSAndroid Build Coastguard Worker 
468*59bfda1fSAndroid Build Coastguard Worker 	if (!rsize)
469*59bfda1fSAndroid Build Coastguard Worker 		return 0;
470*59bfda1fSAndroid Build Coastguard Worker 
471*59bfda1fSAndroid Build Coastguard Worker 	if (eof != NULL)
472*59bfda1fSAndroid Build Coastguard Worker 		*eof = false;
473*59bfda1fSAndroid Build Coastguard Worker 	while (rsize && (cur = read(fd, rbuf, rsize)) != 0) {
474*59bfda1fSAndroid Build Coastguard Worker 		if (cur == -1) {
475*59bfda1fSAndroid Build Coastguard Worker 			if (errno == EINTR && retry--)
476*59bfda1fSAndroid Build Coastguard Worker 				continue;
477*59bfda1fSAndroid Build Coastguard Worker 			return -1;
478*59bfda1fSAndroid Build Coastguard Worker 		}
479*59bfda1fSAndroid Build Coastguard Worker 		retry = MAX_BULKR_RETRY;
480*59bfda1fSAndroid Build Coastguard Worker 
481*59bfda1fSAndroid Build Coastguard Worker 		rsize -= cur;
482*59bfda1fSAndroid Build Coastguard Worker 		n += cur;
483*59bfda1fSAndroid Build Coastguard Worker 	}
484*59bfda1fSAndroid Build Coastguard Worker 	if (eof != NULL)
485*59bfda1fSAndroid Build Coastguard Worker 		*eof = (cur == 0);
486*59bfda1fSAndroid Build Coastguard Worker 	return n;
487*59bfda1fSAndroid Build Coastguard Worker }
488*59bfda1fSAndroid Build Coastguard Worker 
f2fs_fix_mutable(struct f2fs_sb_info * sbi,nid_t ino,pgoff_t offset,unsigned int compressed)489*59bfda1fSAndroid Build Coastguard Worker u64 f2fs_fix_mutable(struct f2fs_sb_info *sbi, nid_t ino, pgoff_t offset,
490*59bfda1fSAndroid Build Coastguard Worker 		unsigned int compressed)
491*59bfda1fSAndroid Build Coastguard Worker {
492*59bfda1fSAndroid Build Coastguard Worker 	unsigned int i;
493*59bfda1fSAndroid Build Coastguard Worker 	u64 wlen;
494*59bfda1fSAndroid Build Coastguard Worker 
495*59bfda1fSAndroid Build Coastguard Worker 	if (c.compress.readonly)
496*59bfda1fSAndroid Build Coastguard Worker 		return 0;
497*59bfda1fSAndroid Build Coastguard Worker 
498*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < compressed - 1; i++) {
499*59bfda1fSAndroid Build Coastguard Worker 		wlen = f2fs_write_addrtag(sbi, ino,
500*59bfda1fSAndroid Build Coastguard Worker 				offset + (i << F2FS_BLKSIZE_BITS), NEW_ADDR);
501*59bfda1fSAndroid Build Coastguard Worker 		if (wlen)
502*59bfda1fSAndroid Build Coastguard Worker 			return wlen;
503*59bfda1fSAndroid Build Coastguard Worker 	}
504*59bfda1fSAndroid Build Coastguard Worker 	return 0;
505*59bfda1fSAndroid Build Coastguard Worker }
506*59bfda1fSAndroid Build Coastguard Worker 
is_consecutive(u32 prev_addr,u32 cur_addr)507*59bfda1fSAndroid Build Coastguard Worker static inline int is_consecutive(u32 prev_addr, u32 cur_addr)
508*59bfda1fSAndroid Build Coastguard Worker {
509*59bfda1fSAndroid Build Coastguard Worker 	if (is_valid_data_blkaddr(cur_addr) && (cur_addr == prev_addr + 1))
510*59bfda1fSAndroid Build Coastguard Worker 		return 1;
511*59bfda1fSAndroid Build Coastguard Worker 	return 0;
512*59bfda1fSAndroid Build Coastguard Worker }
513*59bfda1fSAndroid Build Coastguard Worker 
copy_extent_info(struct extent_info * t_ext,struct extent_info * s_ext)514*59bfda1fSAndroid Build Coastguard Worker static inline void copy_extent_info(struct extent_info *t_ext,
515*59bfda1fSAndroid Build Coastguard Worker 				struct extent_info *s_ext)
516*59bfda1fSAndroid Build Coastguard Worker {
517*59bfda1fSAndroid Build Coastguard Worker 	t_ext->fofs = s_ext->fofs;
518*59bfda1fSAndroid Build Coastguard Worker 	t_ext->blk = s_ext->blk;
519*59bfda1fSAndroid Build Coastguard Worker 	t_ext->len = s_ext->len;
520*59bfda1fSAndroid Build Coastguard Worker }
521*59bfda1fSAndroid Build Coastguard Worker 
update_extent_info(struct f2fs_node * inode,struct extent_info * ext)522*59bfda1fSAndroid Build Coastguard Worker static inline void update_extent_info(struct f2fs_node *inode,
523*59bfda1fSAndroid Build Coastguard Worker 				struct extent_info *ext)
524*59bfda1fSAndroid Build Coastguard Worker {
525*59bfda1fSAndroid Build Coastguard Worker 	inode->i.i_ext.fofs = cpu_to_le32(ext->fofs);
526*59bfda1fSAndroid Build Coastguard Worker 	inode->i.i_ext.blk_addr = cpu_to_le32(ext->blk);
527*59bfda1fSAndroid Build Coastguard Worker 	inode->i.i_ext.len = cpu_to_le32(ext->len);
528*59bfda1fSAndroid Build Coastguard Worker }
529*59bfda1fSAndroid Build Coastguard Worker 
update_largest_extent(struct f2fs_sb_info * sbi,nid_t ino)530*59bfda1fSAndroid Build Coastguard Worker static void update_largest_extent(struct f2fs_sb_info *sbi, nid_t ino)
531*59bfda1fSAndroid Build Coastguard Worker {
532*59bfda1fSAndroid Build Coastguard Worker 	struct dnode_of_data dn;
533*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
534*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_node *inode;
535*59bfda1fSAndroid Build Coastguard Worker 	u32 blkaddr, prev_blkaddr, cur_blk = 0, end_blk;
536*59bfda1fSAndroid Build Coastguard Worker 	struct extent_info largest_ext = { 0, }, cur_ext = { 0, };
537*59bfda1fSAndroid Build Coastguard Worker 	u64 remained_blkentries = 0;
538*59bfda1fSAndroid Build Coastguard Worker 	u32 cluster_size;
539*59bfda1fSAndroid Build Coastguard Worker 	int count;
540*59bfda1fSAndroid Build Coastguard Worker 	void *index_node = NULL;
541*59bfda1fSAndroid Build Coastguard Worker 
542*59bfda1fSAndroid Build Coastguard Worker 	memset(&dn, 0, sizeof(dn));
543*59bfda1fSAndroid Build Coastguard Worker 	largest_ext.len = cur_ext.len = 0;
544*59bfda1fSAndroid Build Coastguard Worker 
545*59bfda1fSAndroid Build Coastguard Worker 	inode = (struct f2fs_node *) calloc(F2FS_BLKSIZE, 1);
546*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(inode);
547*59bfda1fSAndroid Build Coastguard Worker 
548*59bfda1fSAndroid Build Coastguard Worker 	/* Read inode info */
549*59bfda1fSAndroid Build Coastguard Worker 	get_node_info(sbi, ino, &ni);
550*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
551*59bfda1fSAndroid Build Coastguard Worker 	cluster_size = 1 << inode->i.i_log_cluster_size;
552*59bfda1fSAndroid Build Coastguard Worker 
553*59bfda1fSAndroid Build Coastguard Worker 	if (inode->i.i_inline & F2FS_INLINE_DATA)
554*59bfda1fSAndroid Build Coastguard Worker 		goto exit;
555*59bfda1fSAndroid Build Coastguard Worker 
556*59bfda1fSAndroid Build Coastguard Worker 	end_blk  = f2fs_max_file_offset(&inode->i) >> F2FS_BLKSIZE_BITS;
557*59bfda1fSAndroid Build Coastguard Worker 
558*59bfda1fSAndroid Build Coastguard Worker 	while (cur_blk <= end_blk) {
559*59bfda1fSAndroid Build Coastguard Worker 		if (remained_blkentries == 0) {
560*59bfda1fSAndroid Build Coastguard Worker 			set_new_dnode(&dn, inode, NULL, ino);
561*59bfda1fSAndroid Build Coastguard Worker 			get_dnode_of_data(sbi, &dn, cur_blk, LOOKUP_NODE);
562*59bfda1fSAndroid Build Coastguard Worker 			if (index_node)
563*59bfda1fSAndroid Build Coastguard Worker 				free(index_node);
564*59bfda1fSAndroid Build Coastguard Worker 			index_node = (dn.node_blk == dn.inode_blk) ?
565*59bfda1fSAndroid Build Coastguard Worker 				NULL : dn.node_blk;
566*59bfda1fSAndroid Build Coastguard Worker 			remained_blkentries = ADDRS_PER_PAGE(sbi,
567*59bfda1fSAndroid Build Coastguard Worker 					dn.node_blk, dn.inode_blk);
568*59bfda1fSAndroid Build Coastguard Worker 		}
569*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(remained_blkentries > 0);
570*59bfda1fSAndroid Build Coastguard Worker 
571*59bfda1fSAndroid Build Coastguard Worker 		blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
572*59bfda1fSAndroid Build Coastguard Worker 		if (cur_ext.len > 0) {
573*59bfda1fSAndroid Build Coastguard Worker 			if (is_consecutive(prev_blkaddr, blkaddr))
574*59bfda1fSAndroid Build Coastguard Worker 				cur_ext.len++;
575*59bfda1fSAndroid Build Coastguard Worker 			else {
576*59bfda1fSAndroid Build Coastguard Worker 				if (cur_ext.len > largest_ext.len)
577*59bfda1fSAndroid Build Coastguard Worker 					copy_extent_info(&largest_ext,
578*59bfda1fSAndroid Build Coastguard Worker 							&cur_ext);
579*59bfda1fSAndroid Build Coastguard Worker 				cur_ext.len = 0;
580*59bfda1fSAndroid Build Coastguard Worker 			}
581*59bfda1fSAndroid Build Coastguard Worker 		}
582*59bfda1fSAndroid Build Coastguard Worker 
583*59bfda1fSAndroid Build Coastguard Worker 		if (cur_ext.len == 0 && is_valid_data_blkaddr(blkaddr)) {
584*59bfda1fSAndroid Build Coastguard Worker 			cur_ext.fofs = cur_blk;
585*59bfda1fSAndroid Build Coastguard Worker 			cur_ext.len = 1;
586*59bfda1fSAndroid Build Coastguard Worker 			cur_ext.blk = blkaddr;
587*59bfda1fSAndroid Build Coastguard Worker 		}
588*59bfda1fSAndroid Build Coastguard Worker 
589*59bfda1fSAndroid Build Coastguard Worker 		prev_blkaddr = blkaddr;
590*59bfda1fSAndroid Build Coastguard Worker 		count = blkaddr == COMPRESS_ADDR ? cluster_size : 1;
591*59bfda1fSAndroid Build Coastguard Worker 		cur_blk += count;
592*59bfda1fSAndroid Build Coastguard Worker 		dn.ofs_in_node += count;
593*59bfda1fSAndroid Build Coastguard Worker 		remained_blkentries -= count;
594*59bfda1fSAndroid Build Coastguard Worker 	}
595*59bfda1fSAndroid Build Coastguard Worker 
596*59bfda1fSAndroid Build Coastguard Worker exit:
597*59bfda1fSAndroid Build Coastguard Worker 	if (cur_ext.len > largest_ext.len)
598*59bfda1fSAndroid Build Coastguard Worker 		copy_extent_info(&largest_ext, &cur_ext);
599*59bfda1fSAndroid Build Coastguard Worker 	if (largest_ext.len > 0) {
600*59bfda1fSAndroid Build Coastguard Worker 		update_extent_info(inode, &largest_ext);
601*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(update_inode(sbi, inode, &ni.blk_addr) >= 0);
602*59bfda1fSAndroid Build Coastguard Worker 	}
603*59bfda1fSAndroid Build Coastguard Worker 
604*59bfda1fSAndroid Build Coastguard Worker 	if (index_node)
605*59bfda1fSAndroid Build Coastguard Worker 		free(index_node);
606*59bfda1fSAndroid Build Coastguard Worker 	free(inode);
607*59bfda1fSAndroid Build Coastguard Worker }
608*59bfda1fSAndroid Build Coastguard Worker 
f2fs_build_file(struct f2fs_sb_info * sbi,struct dentry * de)609*59bfda1fSAndroid Build Coastguard Worker int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
610*59bfda1fSAndroid Build Coastguard Worker {
611*59bfda1fSAndroid Build Coastguard Worker 	int fd, n = -1;
612*59bfda1fSAndroid Build Coastguard Worker 	pgoff_t off = 0;
613*59bfda1fSAndroid Build Coastguard Worker 	u8 buffer[F2FS_BLKSIZE];
614*59bfda1fSAndroid Build Coastguard Worker 	struct node_info ni;
615*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_node *node_blk;
616*59bfda1fSAndroid Build Coastguard Worker 
617*59bfda1fSAndroid Build Coastguard Worker 	if (de->ino == 0)
618*59bfda1fSAndroid Build Coastguard Worker 		return -1;
619*59bfda1fSAndroid Build Coastguard Worker 
620*59bfda1fSAndroid Build Coastguard Worker 	if (de->from_devino) {
621*59bfda1fSAndroid Build Coastguard Worker 		struct hardlink_cache_entry *found_hardlink;
622*59bfda1fSAndroid Build Coastguard Worker 
623*59bfda1fSAndroid Build Coastguard Worker 		found_hardlink = f2fs_search_hardlink(sbi, de);
624*59bfda1fSAndroid Build Coastguard Worker 		if (found_hardlink && found_hardlink->to_ino &&
625*59bfda1fSAndroid Build Coastguard Worker 				found_hardlink->nbuild)
626*59bfda1fSAndroid Build Coastguard Worker 			return 0;
627*59bfda1fSAndroid Build Coastguard Worker 
628*59bfda1fSAndroid Build Coastguard Worker 		found_hardlink->nbuild++;
629*59bfda1fSAndroid Build Coastguard Worker 	}
630*59bfda1fSAndroid Build Coastguard Worker 
631*59bfda1fSAndroid Build Coastguard Worker 	fd = open(de->full_path, O_RDONLY);
632*59bfda1fSAndroid Build Coastguard Worker 	if (fd < 0) {
633*59bfda1fSAndroid Build Coastguard Worker 		MSG(0, "Skip: Fail to open %s\n", de->full_path);
634*59bfda1fSAndroid Build Coastguard Worker 		return -1;
635*59bfda1fSAndroid Build Coastguard Worker 	}
636*59bfda1fSAndroid Build Coastguard Worker 
637*59bfda1fSAndroid Build Coastguard Worker 	/* inline_data support */
638*59bfda1fSAndroid Build Coastguard Worker 	if (de->size <= DEF_MAX_INLINE_DATA) {
639*59bfda1fSAndroid Build Coastguard Worker 		int ret;
640*59bfda1fSAndroid Build Coastguard Worker 
641*59bfda1fSAndroid Build Coastguard Worker 		get_node_info(sbi, de->ino, &ni);
642*59bfda1fSAndroid Build Coastguard Worker 
643*59bfda1fSAndroid Build Coastguard Worker 		node_blk = calloc(F2FS_BLKSIZE, 1);
644*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(node_blk);
645*59bfda1fSAndroid Build Coastguard Worker 
646*59bfda1fSAndroid Build Coastguard Worker 		ret = dev_read_block(node_blk, ni.blk_addr);
647*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(ret >= 0);
648*59bfda1fSAndroid Build Coastguard Worker 
649*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_inline |= F2FS_INLINE_DATA;
650*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_inline |= F2FS_DATA_EXIST;
651*59bfda1fSAndroid Build Coastguard Worker 
652*59bfda1fSAndroid Build Coastguard Worker 		if (c.feature & F2FS_FEATURE_EXTRA_ATTR) {
653*59bfda1fSAndroid Build Coastguard Worker 			node_blk->i.i_inline |= F2FS_EXTRA_ATTR;
654*59bfda1fSAndroid Build Coastguard Worker 			node_blk->i.i_extra_isize =
655*59bfda1fSAndroid Build Coastguard Worker 					cpu_to_le16(calc_extra_isize());
656*59bfda1fSAndroid Build Coastguard Worker 		}
657*59bfda1fSAndroid Build Coastguard Worker 		n = read(fd, buffer, F2FS_BLKSIZE);
658*59bfda1fSAndroid Build Coastguard Worker 		ASSERT((unsigned long)n == de->size);
659*59bfda1fSAndroid Build Coastguard Worker 		memcpy(inline_data_addr(node_blk), buffer, de->size);
660*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_size = cpu_to_le64(de->size);
661*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(update_inode(sbi, node_blk, &ni.blk_addr) >= 0);
662*59bfda1fSAndroid Build Coastguard Worker 		free(node_blk);
663*59bfda1fSAndroid Build Coastguard Worker #ifdef WITH_SLOAD
664*59bfda1fSAndroid Build Coastguard Worker 	} else if (c.func == SLOAD && c.compress.enabled &&
665*59bfda1fSAndroid Build Coastguard Worker 			c.compress.filter_ops->filter(de->full_path)) {
666*59bfda1fSAndroid Build Coastguard Worker 		bool eof = false;
667*59bfda1fSAndroid Build Coastguard Worker 		u8 *rbuf = c.compress.cc.rbuf;
668*59bfda1fSAndroid Build Coastguard Worker 		unsigned int cblocks = 0;
669*59bfda1fSAndroid Build Coastguard Worker 
670*59bfda1fSAndroid Build Coastguard Worker 		node_blk = calloc(F2FS_BLKSIZE, 1);
671*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(node_blk);
672*59bfda1fSAndroid Build Coastguard Worker 
673*59bfda1fSAndroid Build Coastguard Worker 		/* read inode */
674*59bfda1fSAndroid Build Coastguard Worker 		get_node_info(sbi, de->ino, &ni);
675*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(dev_read_block(node_blk, ni.blk_addr) >= 0);
676*59bfda1fSAndroid Build Coastguard Worker 		/* update inode meta */
677*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_compress_algorithm = c.compress.alg;
678*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_log_cluster_size =
679*59bfda1fSAndroid Build Coastguard Worker 				c.compress.cc.log_cluster_size;
680*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_flags = cpu_to_le32(F2FS_COMPR_FL);
681*59bfda1fSAndroid Build Coastguard Worker 		if (c.compress.readonly)
682*59bfda1fSAndroid Build Coastguard Worker 			node_blk->i.i_inline |= F2FS_COMPRESS_RELEASED;
683*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(update_inode(sbi, node_blk, &ni.blk_addr) >= 0);
684*59bfda1fSAndroid Build Coastguard Worker 
685*59bfda1fSAndroid Build Coastguard Worker 		while (!eof && (n = bulkread(fd, rbuf, c.compress.cc.rlen,
686*59bfda1fSAndroid Build Coastguard Worker 				&eof)) > 0) {
687*59bfda1fSAndroid Build Coastguard Worker 			int ret = c.compress.ops->compress(&c.compress.cc);
688*59bfda1fSAndroid Build Coastguard Worker 			u64 wlen;
689*59bfda1fSAndroid Build Coastguard Worker 			u32 csize = ALIGN_UP(c.compress.cc.clen +
690*59bfda1fSAndroid Build Coastguard Worker 					COMPRESS_HEADER_SIZE, F2FS_BLKSIZE);
691*59bfda1fSAndroid Build Coastguard Worker 			unsigned int cur_cblk;
692*59bfda1fSAndroid Build Coastguard Worker 
693*59bfda1fSAndroid Build Coastguard Worker 			if (ret || n < c.compress.cc.rlen ||
694*59bfda1fSAndroid Build Coastguard Worker 				n < (int)(csize + F2FS_BLKSIZE *
695*59bfda1fSAndroid Build Coastguard Worker 						c.compress.min_blocks)) {
696*59bfda1fSAndroid Build Coastguard Worker 				wlen = f2fs_write(sbi, de->ino, rbuf, n, off);
697*59bfda1fSAndroid Build Coastguard Worker 				ASSERT((int)wlen == n);
698*59bfda1fSAndroid Build Coastguard Worker 			} else {
699*59bfda1fSAndroid Build Coastguard Worker 				wlen = f2fs_write_addrtag(sbi, de->ino, off,
700*59bfda1fSAndroid Build Coastguard Worker 						WR_COMPRESS_ADDR);
701*59bfda1fSAndroid Build Coastguard Worker 				ASSERT(!wlen);
702*59bfda1fSAndroid Build Coastguard Worker 				wlen = f2fs_write_compress_data(sbi, de->ino,
703*59bfda1fSAndroid Build Coastguard Worker 						(u8 *)c.compress.cc.cbuf,
704*59bfda1fSAndroid Build Coastguard Worker 						csize, off + F2FS_BLKSIZE);
705*59bfda1fSAndroid Build Coastguard Worker 				ASSERT(wlen == csize);
706*59bfda1fSAndroid Build Coastguard Worker 				c.compress.ops->reset(&c.compress.cc);
707*59bfda1fSAndroid Build Coastguard Worker 				cur_cblk = (c.compress.cc.rlen - csize) /
708*59bfda1fSAndroid Build Coastguard Worker 								F2FS_BLKSIZE;
709*59bfda1fSAndroid Build Coastguard Worker 				cblocks += cur_cblk;
710*59bfda1fSAndroid Build Coastguard Worker 				wlen = f2fs_fix_mutable(sbi, de->ino,
711*59bfda1fSAndroid Build Coastguard Worker 						off + F2FS_BLKSIZE + csize,
712*59bfda1fSAndroid Build Coastguard Worker 						cur_cblk);
713*59bfda1fSAndroid Build Coastguard Worker 				ASSERT(!wlen);
714*59bfda1fSAndroid Build Coastguard Worker 			}
715*59bfda1fSAndroid Build Coastguard Worker 			off += n;
716*59bfda1fSAndroid Build Coastguard Worker 		}
717*59bfda1fSAndroid Build Coastguard Worker 		if (n == -1) {
718*59bfda1fSAndroid Build Coastguard Worker 			fprintf(stderr, "Load file '%s' failed: ",
719*59bfda1fSAndroid Build Coastguard Worker 					de->full_path);
720*59bfda1fSAndroid Build Coastguard Worker 			perror(NULL);
721*59bfda1fSAndroid Build Coastguard Worker 		}
722*59bfda1fSAndroid Build Coastguard Worker 		/* read inode */
723*59bfda1fSAndroid Build Coastguard Worker 		get_node_info(sbi, de->ino, &ni);
724*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(dev_read_block(node_blk, ni.blk_addr) >= 0);
725*59bfda1fSAndroid Build Coastguard Worker 		/* update inode meta */
726*59bfda1fSAndroid Build Coastguard Worker 		node_blk->i.i_size = cpu_to_le64(off);
727*59bfda1fSAndroid Build Coastguard Worker 		if (!c.compress.readonly) {
728*59bfda1fSAndroid Build Coastguard Worker 			node_blk->i.i_compr_blocks = cpu_to_le64(cblocks);
729*59bfda1fSAndroid Build Coastguard Worker 			node_blk->i.i_blocks += cpu_to_le64(cblocks);
730*59bfda1fSAndroid Build Coastguard Worker 		}
731*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(update_inode(sbi, node_blk, &ni.blk_addr) >= 0);
732*59bfda1fSAndroid Build Coastguard Worker 		free(node_blk);
733*59bfda1fSAndroid Build Coastguard Worker 
734*59bfda1fSAndroid Build Coastguard Worker 		if (!c.compress.readonly) {
735*59bfda1fSAndroid Build Coastguard Worker 			sbi->total_valid_block_count += cblocks;
736*59bfda1fSAndroid Build Coastguard Worker 			if (sbi->total_valid_block_count >=
737*59bfda1fSAndroid Build Coastguard Worker 					sbi->user_block_count) {
738*59bfda1fSAndroid Build Coastguard Worker 				ERR_MSG("Not enough space\n");
739*59bfda1fSAndroid Build Coastguard Worker 				ASSERT(0);
740*59bfda1fSAndroid Build Coastguard Worker 			}
741*59bfda1fSAndroid Build Coastguard Worker 		}
742*59bfda1fSAndroid Build Coastguard Worker #endif
743*59bfda1fSAndroid Build Coastguard Worker 	} else {
744*59bfda1fSAndroid Build Coastguard Worker 		while ((n = read(fd, buffer, F2FS_BLKSIZE)) > 0) {
745*59bfda1fSAndroid Build Coastguard Worker 			f2fs_write(sbi, de->ino, buffer, n, off);
746*59bfda1fSAndroid Build Coastguard Worker 			off += n;
747*59bfda1fSAndroid Build Coastguard Worker 		}
748*59bfda1fSAndroid Build Coastguard Worker 	}
749*59bfda1fSAndroid Build Coastguard Worker 
750*59bfda1fSAndroid Build Coastguard Worker 	close(fd);
751*59bfda1fSAndroid Build Coastguard Worker 	if (n < 0)
752*59bfda1fSAndroid Build Coastguard Worker 		return -1;
753*59bfda1fSAndroid Build Coastguard Worker 
754*59bfda1fSAndroid Build Coastguard Worker 	if (!c.compress.enabled || (c.feature & F2FS_FEATURE_RO))
755*59bfda1fSAndroid Build Coastguard Worker 		update_largest_extent(sbi, de->ino);
756*59bfda1fSAndroid Build Coastguard Worker 	update_free_segments(sbi);
757*59bfda1fSAndroid Build Coastguard Worker 
758*59bfda1fSAndroid Build Coastguard Worker 	MSG(1, "Info: Create %s -> %s\n"
759*59bfda1fSAndroid Build Coastguard Worker 		"  -- ino=%x, type=%x, mode=%x, uid=%x, "
760*59bfda1fSAndroid Build Coastguard Worker 		"gid=%x, cap=%"PRIx64", size=%lu, pino=%x\n",
761*59bfda1fSAndroid Build Coastguard Worker 		de->full_path, de->path,
762*59bfda1fSAndroid Build Coastguard Worker 		de->ino, de->file_type, de->mode,
763*59bfda1fSAndroid Build Coastguard Worker 		de->uid, de->gid, de->capabilities, de->size, de->pino);
764*59bfda1fSAndroid Build Coastguard Worker 	return 0;
765*59bfda1fSAndroid Build Coastguard Worker }
766*59bfda1fSAndroid Build Coastguard Worker 
update_block(struct f2fs_sb_info * sbi,void * buf,u32 * blkaddr,struct f2fs_node * node_blk)767*59bfda1fSAndroid Build Coastguard Worker int update_block(struct f2fs_sb_info *sbi, void *buf, u32 *blkaddr,
768*59bfda1fSAndroid Build Coastguard Worker 		struct f2fs_node *node_blk)
769*59bfda1fSAndroid Build Coastguard Worker {
770*59bfda1fSAndroid Build Coastguard Worker 	struct seg_entry *se;
771*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_summary sum;
772*59bfda1fSAndroid Build Coastguard Worker 	u64 new_blkaddr, old_blkaddr = *blkaddr, offset;
773*59bfda1fSAndroid Build Coastguard Worker 	int ret, type;
774*59bfda1fSAndroid Build Coastguard Worker 
775*59bfda1fSAndroid Build Coastguard Worker 	if (c.zoned_model != F2FS_ZONED_HM)
776*59bfda1fSAndroid Build Coastguard Worker 		return dev_write_block(buf, old_blkaddr, WRITE_LIFE_NONE);
777*59bfda1fSAndroid Build Coastguard Worker 
778*59bfda1fSAndroid Build Coastguard Worker 	/* update sit bitmap & valid_blocks && se->type for old block*/
779*59bfda1fSAndroid Build Coastguard Worker 	se = get_seg_entry(sbi, GET_SEGNO(sbi, old_blkaddr));
780*59bfda1fSAndroid Build Coastguard Worker 	offset = OFFSET_IN_SEG(sbi, old_blkaddr);
781*59bfda1fSAndroid Build Coastguard Worker 	type = se->type;
782*59bfda1fSAndroid Build Coastguard Worker 	se->valid_blocks--;
783*59bfda1fSAndroid Build Coastguard Worker 	f2fs_clear_bit(offset, (char *)se->cur_valid_map);
784*59bfda1fSAndroid Build Coastguard Worker 	if (need_fsync_data_record(sbi))
785*59bfda1fSAndroid Build Coastguard Worker 		f2fs_clear_bit(offset, (char *)se->ckpt_valid_map);
786*59bfda1fSAndroid Build Coastguard Worker 	se->dirty = 1;
787*59bfda1fSAndroid Build Coastguard Worker 	f2fs_clear_main_bitmap(sbi, old_blkaddr);
788*59bfda1fSAndroid Build Coastguard Worker 	f2fs_clear_sit_bitmap(sbi, old_blkaddr);
789*59bfda1fSAndroid Build Coastguard Worker 
790*59bfda1fSAndroid Build Coastguard Worker 	new_blkaddr = SM_I(sbi)->main_blkaddr;
791*59bfda1fSAndroid Build Coastguard Worker 	if (find_next_free_block(sbi, &new_blkaddr, 0, type, false)) {
792*59bfda1fSAndroid Build Coastguard Worker 		ERR_MSG("Can't find free block for the update");
793*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(0);
794*59bfda1fSAndroid Build Coastguard Worker 	}
795*59bfda1fSAndroid Build Coastguard Worker 
796*59bfda1fSAndroid Build Coastguard Worker 	ret = dev_write_block(buf, new_blkaddr, f2fs_io_type_to_rw_hint(type));
797*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(ret >= 0);
798*59bfda1fSAndroid Build Coastguard Worker 
799*59bfda1fSAndroid Build Coastguard Worker 	*blkaddr = new_blkaddr;
800*59bfda1fSAndroid Build Coastguard Worker 
801*59bfda1fSAndroid Build Coastguard Worker 	/* update sit bitmap & valid_blocks && se->type for new block */
802*59bfda1fSAndroid Build Coastguard Worker 	se = get_seg_entry(sbi, GET_SEGNO(sbi, new_blkaddr));
803*59bfda1fSAndroid Build Coastguard Worker 	offset = OFFSET_IN_SEG(sbi, new_blkaddr);
804*59bfda1fSAndroid Build Coastguard Worker 	se->type = se->orig_type = type;
805*59bfda1fSAndroid Build Coastguard Worker 	se->valid_blocks++;
806*59bfda1fSAndroid Build Coastguard Worker 	f2fs_set_bit(offset, (char *)se->cur_valid_map);
807*59bfda1fSAndroid Build Coastguard Worker 	if (need_fsync_data_record(sbi))
808*59bfda1fSAndroid Build Coastguard Worker 		f2fs_set_bit(offset, (char *)se->ckpt_valid_map);
809*59bfda1fSAndroid Build Coastguard Worker 	se->dirty = 1;
810*59bfda1fSAndroid Build Coastguard Worker 	f2fs_set_main_bitmap(sbi, new_blkaddr, type);
811*59bfda1fSAndroid Build Coastguard Worker 	f2fs_set_sit_bitmap(sbi, new_blkaddr);
812*59bfda1fSAndroid Build Coastguard Worker 
813*59bfda1fSAndroid Build Coastguard Worker 	/* update SSA */
814*59bfda1fSAndroid Build Coastguard Worker 	get_sum_entry(sbi, old_blkaddr, &sum);
815*59bfda1fSAndroid Build Coastguard Worker 	update_sum_entry(sbi, new_blkaddr, &sum);
816*59bfda1fSAndroid Build Coastguard Worker 
817*59bfda1fSAndroid Build Coastguard Worker 	if (IS_DATASEG(type)) {
818*59bfda1fSAndroid Build Coastguard Worker 		update_data_blkaddr(sbi, le32_to_cpu(sum.nid),
819*59bfda1fSAndroid Build Coastguard Worker 				le16_to_cpu(sum.ofs_in_node), new_blkaddr, node_blk);
820*59bfda1fSAndroid Build Coastguard Worker 	} else
821*59bfda1fSAndroid Build Coastguard Worker 		update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), new_blkaddr);
822*59bfda1fSAndroid Build Coastguard Worker 
823*59bfda1fSAndroid Build Coastguard Worker 	DBG(1, "Update %s block %"PRIx64" -> %"PRIx64"\n",
824*59bfda1fSAndroid Build Coastguard Worker 		IS_DATASEG(type) ? "data" : "node", old_blkaddr, new_blkaddr);
825*59bfda1fSAndroid Build Coastguard Worker 	return ret;
826*59bfda1fSAndroid Build Coastguard Worker }
827