xref: /aosp_15_r20/external/f2fs-tools/lib/libf2fs_io.c (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
1*59bfda1fSAndroid Build Coastguard Worker /**
2*59bfda1fSAndroid Build Coastguard Worker  * libf2fs.c
3*59bfda1fSAndroid Build Coastguard Worker  *
4*59bfda1fSAndroid Build Coastguard Worker  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5*59bfda1fSAndroid Build Coastguard Worker  *             http://www.samsung.com/
6*59bfda1fSAndroid Build Coastguard Worker  * Copyright (c) 2019 Google Inc.
7*59bfda1fSAndroid Build Coastguard Worker  *             http://www.google.com/
8*59bfda1fSAndroid Build Coastguard Worker  * Copyright (c) 2020 Google Inc.
9*59bfda1fSAndroid Build Coastguard Worker  *   Robin Hsu <[email protected]>
10*59bfda1fSAndroid Build Coastguard Worker  *  : add quick-buffer for sload compression support
11*59bfda1fSAndroid Build Coastguard Worker  *
12*59bfda1fSAndroid Build Coastguard Worker  * Dual licensed under the GPL or LGPL version 2 licenses.
13*59bfda1fSAndroid Build Coastguard Worker  */
14*59bfda1fSAndroid Build Coastguard Worker #include <stdio.h>
15*59bfda1fSAndroid Build Coastguard Worker #include <stdlib.h>
16*59bfda1fSAndroid Build Coastguard Worker #include <string.h>
17*59bfda1fSAndroid Build Coastguard Worker #include <errno.h>
18*59bfda1fSAndroid Build Coastguard Worker #include <unistd.h>
19*59bfda1fSAndroid Build Coastguard Worker #include <fcntl.h>
20*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_MNTENT_H
21*59bfda1fSAndroid Build Coastguard Worker #include <mntent.h>
22*59bfda1fSAndroid Build Coastguard Worker #endif
23*59bfda1fSAndroid Build Coastguard Worker #include <time.h>
24*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_STAT_H
25*59bfda1fSAndroid Build Coastguard Worker #include <sys/stat.h>
26*59bfda1fSAndroid Build Coastguard Worker #endif
27*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_MOUNT_H
28*59bfda1fSAndroid Build Coastguard Worker #include <sys/mount.h>
29*59bfda1fSAndroid Build Coastguard Worker #endif
30*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
31*59bfda1fSAndroid Build Coastguard Worker #include <sys/ioctl.h>
32*59bfda1fSAndroid Build Coastguard Worker #endif
33*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_HDREG_H
34*59bfda1fSAndroid Build Coastguard Worker #include <linux/hdreg.h>
35*59bfda1fSAndroid Build Coastguard Worker #endif
36*59bfda1fSAndroid Build Coastguard Worker 
37*59bfda1fSAndroid Build Coastguard Worker #ifndef F_SET_RW_HINT
38*59bfda1fSAndroid Build Coastguard Worker #define F_LINUX_SPECIFIC_BASE 	1024
39*59bfda1fSAndroid Build Coastguard Worker #define F_SET_RW_HINT		(F_LINUX_SPECIFIC_BASE + 12)
40*59bfda1fSAndroid Build Coastguard Worker #endif
41*59bfda1fSAndroid Build Coastguard Worker 
42*59bfda1fSAndroid Build Coastguard Worker #include <stdbool.h>
43*59bfda1fSAndroid Build Coastguard Worker #include <assert.h>
44*59bfda1fSAndroid Build Coastguard Worker #include <inttypes.h>
45*59bfda1fSAndroid Build Coastguard Worker #include "f2fs_fs.h"
46*59bfda1fSAndroid Build Coastguard Worker 
47*59bfda1fSAndroid Build Coastguard Worker struct f2fs_configuration c;
48*59bfda1fSAndroid Build Coastguard Worker 
49*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SPARSE_SPARSE_H
50*59bfda1fSAndroid Build Coastguard Worker #include <sparse/sparse.h>
51*59bfda1fSAndroid Build Coastguard Worker struct sparse_file *f2fs_sparse_file;
52*59bfda1fSAndroid Build Coastguard Worker static char **blocks;
53*59bfda1fSAndroid Build Coastguard Worker uint64_t blocks_count;
54*59bfda1fSAndroid Build Coastguard Worker static char *zeroed_block;
55*59bfda1fSAndroid Build Coastguard Worker #endif
56*59bfda1fSAndroid Build Coastguard Worker 
__get_device_fd(__u64 * offset)57*59bfda1fSAndroid Build Coastguard Worker static int __get_device_fd(__u64 *offset)
58*59bfda1fSAndroid Build Coastguard Worker {
59*59bfda1fSAndroid Build Coastguard Worker 	__u64 blk_addr = *offset >> F2FS_BLKSIZE_BITS;
60*59bfda1fSAndroid Build Coastguard Worker 	int i;
61*59bfda1fSAndroid Build Coastguard Worker 
62*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < c.ndevs; i++) {
63*59bfda1fSAndroid Build Coastguard Worker 		if (c.devices[i].start_blkaddr <= blk_addr &&
64*59bfda1fSAndroid Build Coastguard Worker 				c.devices[i].end_blkaddr >= blk_addr) {
65*59bfda1fSAndroid Build Coastguard Worker 			*offset -=
66*59bfda1fSAndroid Build Coastguard Worker 				c.devices[i].start_blkaddr << F2FS_BLKSIZE_BITS;
67*59bfda1fSAndroid Build Coastguard Worker 			return c.devices[i].fd;
68*59bfda1fSAndroid Build Coastguard Worker 		}
69*59bfda1fSAndroid Build Coastguard Worker 	}
70*59bfda1fSAndroid Build Coastguard Worker 	return -1;
71*59bfda1fSAndroid Build Coastguard Worker }
72*59bfda1fSAndroid Build Coastguard Worker 
73*59bfda1fSAndroid Build Coastguard Worker /* ---------- dev_cache, Least Used First (LUF) policy  ------------------- */
74*59bfda1fSAndroid Build Coastguard Worker /*
75*59bfda1fSAndroid Build Coastguard Worker  * Least used block will be the first victim to be replaced when max hash
76*59bfda1fSAndroid Build Coastguard Worker  * collision exceeds
77*59bfda1fSAndroid Build Coastguard Worker  */
78*59bfda1fSAndroid Build Coastguard Worker static bool *dcache_valid; /* is the cached block valid? */
79*59bfda1fSAndroid Build Coastguard Worker static off_t  *dcache_blk; /* which block it cached */
80*59bfda1fSAndroid Build Coastguard Worker static uint64_t *dcache_lastused; /* last used ticks for cache entries */
81*59bfda1fSAndroid Build Coastguard Worker static char *dcache_buf; /* cached block data */
82*59bfda1fSAndroid Build Coastguard Worker static uint64_t dcache_usetick; /* current use tick */
83*59bfda1fSAndroid Build Coastguard Worker 
84*59bfda1fSAndroid Build Coastguard Worker static uint64_t dcache_raccess;
85*59bfda1fSAndroid Build Coastguard Worker static uint64_t dcache_rhit;
86*59bfda1fSAndroid Build Coastguard Worker static uint64_t dcache_rmiss;
87*59bfda1fSAndroid Build Coastguard Worker static uint64_t dcache_rreplace;
88*59bfda1fSAndroid Build Coastguard Worker 
89*59bfda1fSAndroid Build Coastguard Worker static bool dcache_exit_registered = false;
90*59bfda1fSAndroid Build Coastguard Worker 
91*59bfda1fSAndroid Build Coastguard Worker /*
92*59bfda1fSAndroid Build Coastguard Worker  *  Shadow config:
93*59bfda1fSAndroid Build Coastguard Worker  *
94*59bfda1fSAndroid Build Coastguard Worker  *  Active set of the configurations.
95*59bfda1fSAndroid Build Coastguard Worker  *  Global configuration 'dcache_config' will be transferred here when
96*59bfda1fSAndroid Build Coastguard Worker  *  when dcache_init() is called
97*59bfda1fSAndroid Build Coastguard Worker  */
98*59bfda1fSAndroid Build Coastguard Worker static dev_cache_config_t dcache_config = {0, 16, 1};
99*59bfda1fSAndroid Build Coastguard Worker static bool dcache_initialized = false;
100*59bfda1fSAndroid Build Coastguard Worker 
101*59bfda1fSAndroid Build Coastguard Worker #define MIN_NUM_CACHE_ENTRY  1024L
102*59bfda1fSAndroid Build Coastguard Worker #define MAX_MAX_HASH_COLLISION  16
103*59bfda1fSAndroid Build Coastguard Worker 
104*59bfda1fSAndroid Build Coastguard Worker static long dcache_relocate_offset0[] = {
105*59bfda1fSAndroid Build Coastguard Worker 	20, -20, 40, -40, 80, -80, 160, -160,
106*59bfda1fSAndroid Build Coastguard Worker 	320, -320, 640, -640, 1280, -1280, 2560, -2560,
107*59bfda1fSAndroid Build Coastguard Worker };
108*59bfda1fSAndroid Build Coastguard Worker static int dcache_relocate_offset[16];
109*59bfda1fSAndroid Build Coastguard Worker 
dcache_print_statistics(void)110*59bfda1fSAndroid Build Coastguard Worker static void dcache_print_statistics(void)
111*59bfda1fSAndroid Build Coastguard Worker {
112*59bfda1fSAndroid Build Coastguard Worker 	long i;
113*59bfda1fSAndroid Build Coastguard Worker 	long useCnt;
114*59bfda1fSAndroid Build Coastguard Worker 
115*59bfda1fSAndroid Build Coastguard Worker 	/* Number of used cache entries */
116*59bfda1fSAndroid Build Coastguard Worker 	useCnt = 0;
117*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < dcache_config.num_cache_entry; i++)
118*59bfda1fSAndroid Build Coastguard Worker 		if (dcache_valid[i])
119*59bfda1fSAndroid Build Coastguard Worker 			++useCnt;
120*59bfda1fSAndroid Build Coastguard Worker 
121*59bfda1fSAndroid Build Coastguard Worker 	/*
122*59bfda1fSAndroid Build Coastguard Worker 	 *  c: number of cache entries
123*59bfda1fSAndroid Build Coastguard Worker 	 *  u: used entries
124*59bfda1fSAndroid Build Coastguard Worker 	 *  RA: number of read access blocks
125*59bfda1fSAndroid Build Coastguard Worker 	 *  CH: cache hit
126*59bfda1fSAndroid Build Coastguard Worker 	 *  CM: cache miss
127*59bfda1fSAndroid Build Coastguard Worker 	 *  Repl: read cache replaced
128*59bfda1fSAndroid Build Coastguard Worker 	 */
129*59bfda1fSAndroid Build Coastguard Worker 	printf ("\nc, u, RA, CH, CM, Repl=\n");
130*59bfda1fSAndroid Build Coastguard Worker 	printf ("%ld %ld %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
131*59bfda1fSAndroid Build Coastguard Worker 			dcache_config.num_cache_entry,
132*59bfda1fSAndroid Build Coastguard Worker 			useCnt,
133*59bfda1fSAndroid Build Coastguard Worker 			dcache_raccess,
134*59bfda1fSAndroid Build Coastguard Worker 			dcache_rhit,
135*59bfda1fSAndroid Build Coastguard Worker 			dcache_rmiss,
136*59bfda1fSAndroid Build Coastguard Worker 			dcache_rreplace);
137*59bfda1fSAndroid Build Coastguard Worker }
138*59bfda1fSAndroid Build Coastguard Worker 
dcache_release(void)139*59bfda1fSAndroid Build Coastguard Worker void dcache_release(void)
140*59bfda1fSAndroid Build Coastguard Worker {
141*59bfda1fSAndroid Build Coastguard Worker 	if (!dcache_initialized)
142*59bfda1fSAndroid Build Coastguard Worker 		return;
143*59bfda1fSAndroid Build Coastguard Worker 
144*59bfda1fSAndroid Build Coastguard Worker 	dcache_initialized = false;
145*59bfda1fSAndroid Build Coastguard Worker 
146*59bfda1fSAndroid Build Coastguard Worker 	if (c.cache_config.dbg_en)
147*59bfda1fSAndroid Build Coastguard Worker 		dcache_print_statistics();
148*59bfda1fSAndroid Build Coastguard Worker 
149*59bfda1fSAndroid Build Coastguard Worker 	if (dcache_blk != NULL)
150*59bfda1fSAndroid Build Coastguard Worker 		free(dcache_blk);
151*59bfda1fSAndroid Build Coastguard Worker 	if (dcache_lastused != NULL)
152*59bfda1fSAndroid Build Coastguard Worker 		free(dcache_lastused);
153*59bfda1fSAndroid Build Coastguard Worker 	if (dcache_buf != NULL)
154*59bfda1fSAndroid Build Coastguard Worker 		free(dcache_buf);
155*59bfda1fSAndroid Build Coastguard Worker 	if (dcache_valid != NULL)
156*59bfda1fSAndroid Build Coastguard Worker 		free(dcache_valid);
157*59bfda1fSAndroid Build Coastguard Worker 	dcache_config.num_cache_entry = 0;
158*59bfda1fSAndroid Build Coastguard Worker 	dcache_blk = NULL;
159*59bfda1fSAndroid Build Coastguard Worker 	dcache_lastused = NULL;
160*59bfda1fSAndroid Build Coastguard Worker 	dcache_buf = NULL;
161*59bfda1fSAndroid Build Coastguard Worker 	dcache_valid = NULL;
162*59bfda1fSAndroid Build Coastguard Worker }
163*59bfda1fSAndroid Build Coastguard Worker 
164*59bfda1fSAndroid Build Coastguard Worker // return 0 for success, error code for failure.
dcache_alloc_all(long n)165*59bfda1fSAndroid Build Coastguard Worker static int dcache_alloc_all(long n)
166*59bfda1fSAndroid Build Coastguard Worker {
167*59bfda1fSAndroid Build Coastguard Worker 	if (n <= 0)
168*59bfda1fSAndroid Build Coastguard Worker 		return -1;
169*59bfda1fSAndroid Build Coastguard Worker 	if ((dcache_blk = (off_t *) malloc(sizeof(off_t) * n)) == NULL
170*59bfda1fSAndroid Build Coastguard Worker 		|| (dcache_lastused = (uint64_t *)
171*59bfda1fSAndroid Build Coastguard Worker 				malloc(sizeof(uint64_t) * n)) == NULL
172*59bfda1fSAndroid Build Coastguard Worker 		|| (dcache_buf = (char *) malloc (F2FS_BLKSIZE * n)) == NULL
173*59bfda1fSAndroid Build Coastguard Worker 		|| (dcache_valid = (bool *) calloc(sizeof(bool) * n, 1)) == NULL)
174*59bfda1fSAndroid Build Coastguard Worker 	{
175*59bfda1fSAndroid Build Coastguard Worker 		dcache_release();
176*59bfda1fSAndroid Build Coastguard Worker 		return -1;
177*59bfda1fSAndroid Build Coastguard Worker 	}
178*59bfda1fSAndroid Build Coastguard Worker 	dcache_config.num_cache_entry = n;
179*59bfda1fSAndroid Build Coastguard Worker 	return 0;
180*59bfda1fSAndroid Build Coastguard Worker }
181*59bfda1fSAndroid Build Coastguard Worker 
dcache_relocate_init(void)182*59bfda1fSAndroid Build Coastguard Worker static void dcache_relocate_init(void)
183*59bfda1fSAndroid Build Coastguard Worker {
184*59bfda1fSAndroid Build Coastguard Worker 	int i;
185*59bfda1fSAndroid Build Coastguard Worker 	int n0 = (sizeof(dcache_relocate_offset0)
186*59bfda1fSAndroid Build Coastguard Worker 			/ sizeof(dcache_relocate_offset0[0]));
187*59bfda1fSAndroid Build Coastguard Worker 	int n = (sizeof(dcache_relocate_offset)
188*59bfda1fSAndroid Build Coastguard Worker 			/ sizeof(dcache_relocate_offset[0]));
189*59bfda1fSAndroid Build Coastguard Worker 
190*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(n == n0);
191*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < n && i < dcache_config.max_hash_collision; i++) {
192*59bfda1fSAndroid Build Coastguard Worker 		if (labs(dcache_relocate_offset0[i])
193*59bfda1fSAndroid Build Coastguard Worker 				> dcache_config.num_cache_entry / 2) {
194*59bfda1fSAndroid Build Coastguard Worker 			dcache_config.max_hash_collision = i;
195*59bfda1fSAndroid Build Coastguard Worker 			break;
196*59bfda1fSAndroid Build Coastguard Worker 		}
197*59bfda1fSAndroid Build Coastguard Worker 		dcache_relocate_offset[i] =
198*59bfda1fSAndroid Build Coastguard Worker 				dcache_config.num_cache_entry
199*59bfda1fSAndroid Build Coastguard Worker 				+ dcache_relocate_offset0[i];
200*59bfda1fSAndroid Build Coastguard Worker 	}
201*59bfda1fSAndroid Build Coastguard Worker }
202*59bfda1fSAndroid Build Coastguard Worker 
dcache_init(void)203*59bfda1fSAndroid Build Coastguard Worker void dcache_init(void)
204*59bfda1fSAndroid Build Coastguard Worker {
205*59bfda1fSAndroid Build Coastguard Worker 	long n;
206*59bfda1fSAndroid Build Coastguard Worker 
207*59bfda1fSAndroid Build Coastguard Worker 	if (c.cache_config.num_cache_entry <= 0)
208*59bfda1fSAndroid Build Coastguard Worker 		return;
209*59bfda1fSAndroid Build Coastguard Worker 
210*59bfda1fSAndroid Build Coastguard Worker 	/* release previous cache init, if any */
211*59bfda1fSAndroid Build Coastguard Worker 	dcache_release();
212*59bfda1fSAndroid Build Coastguard Worker 
213*59bfda1fSAndroid Build Coastguard Worker 	dcache_blk = NULL;
214*59bfda1fSAndroid Build Coastguard Worker 	dcache_lastused = NULL;
215*59bfda1fSAndroid Build Coastguard Worker 	dcache_buf = NULL;
216*59bfda1fSAndroid Build Coastguard Worker 	dcache_valid = NULL;
217*59bfda1fSAndroid Build Coastguard Worker 
218*59bfda1fSAndroid Build Coastguard Worker 	dcache_config = c.cache_config;
219*59bfda1fSAndroid Build Coastguard Worker 
220*59bfda1fSAndroid Build Coastguard Worker 	n = max(MIN_NUM_CACHE_ENTRY, dcache_config.num_cache_entry);
221*59bfda1fSAndroid Build Coastguard Worker 
222*59bfda1fSAndroid Build Coastguard Worker 	/* halve alloc size until alloc succeed, or min cache reached */
223*59bfda1fSAndroid Build Coastguard Worker 	while (dcache_alloc_all(n) != 0 && n !=  MIN_NUM_CACHE_ENTRY)
224*59bfda1fSAndroid Build Coastguard Worker 		n = max(MIN_NUM_CACHE_ENTRY, n/2);
225*59bfda1fSAndroid Build Coastguard Worker 
226*59bfda1fSAndroid Build Coastguard Worker 	/* must be the last: data dependent on num_cache_entry */
227*59bfda1fSAndroid Build Coastguard Worker 	dcache_relocate_init();
228*59bfda1fSAndroid Build Coastguard Worker 	dcache_initialized = true;
229*59bfda1fSAndroid Build Coastguard Worker 
230*59bfda1fSAndroid Build Coastguard Worker 	if (!dcache_exit_registered) {
231*59bfda1fSAndroid Build Coastguard Worker 		dcache_exit_registered = true;
232*59bfda1fSAndroid Build Coastguard Worker 		atexit(dcache_release); /* auto release */
233*59bfda1fSAndroid Build Coastguard Worker 	}
234*59bfda1fSAndroid Build Coastguard Worker 
235*59bfda1fSAndroid Build Coastguard Worker 	dcache_raccess = 0;
236*59bfda1fSAndroid Build Coastguard Worker 	dcache_rhit = 0;
237*59bfda1fSAndroid Build Coastguard Worker 	dcache_rmiss = 0;
238*59bfda1fSAndroid Build Coastguard Worker 	dcache_rreplace = 0;
239*59bfda1fSAndroid Build Coastguard Worker }
240*59bfda1fSAndroid Build Coastguard Worker 
dcache_addr(long entry)241*59bfda1fSAndroid Build Coastguard Worker static inline char *dcache_addr(long entry)
242*59bfda1fSAndroid Build Coastguard Worker {
243*59bfda1fSAndroid Build Coastguard Worker 	return dcache_buf + F2FS_BLKSIZE * entry;
244*59bfda1fSAndroid Build Coastguard Worker }
245*59bfda1fSAndroid Build Coastguard Worker 
246*59bfda1fSAndroid Build Coastguard Worker /* relocate on (n+1)-th collision */
dcache_relocate(long entry,int n)247*59bfda1fSAndroid Build Coastguard Worker static inline long dcache_relocate(long entry, int n)
248*59bfda1fSAndroid Build Coastguard Worker {
249*59bfda1fSAndroid Build Coastguard Worker 	assert(dcache_config.num_cache_entry != 0);
250*59bfda1fSAndroid Build Coastguard Worker 	return (entry + dcache_relocate_offset[n]) %
251*59bfda1fSAndroid Build Coastguard Worker 			dcache_config.num_cache_entry;
252*59bfda1fSAndroid Build Coastguard Worker }
253*59bfda1fSAndroid Build Coastguard Worker 
dcache_find(__u64 blk)254*59bfda1fSAndroid Build Coastguard Worker static long dcache_find(__u64 blk)
255*59bfda1fSAndroid Build Coastguard Worker {
256*59bfda1fSAndroid Build Coastguard Worker 	register long n = dcache_config.num_cache_entry;
257*59bfda1fSAndroid Build Coastguard Worker 	register unsigned m = dcache_config.max_hash_collision;
258*59bfda1fSAndroid Build Coastguard Worker 	long entry, least_used, target;
259*59bfda1fSAndroid Build Coastguard Worker 	unsigned try;
260*59bfda1fSAndroid Build Coastguard Worker 
261*59bfda1fSAndroid Build Coastguard Worker 	assert(n > 0);
262*59bfda1fSAndroid Build Coastguard Worker 	target = least_used = entry = blk % n; /* simple modulo hash */
263*59bfda1fSAndroid Build Coastguard Worker 
264*59bfda1fSAndroid Build Coastguard Worker 	for (try = 0; try < m; try++) {
265*59bfda1fSAndroid Build Coastguard Worker 		if (!dcache_valid[target] || dcache_blk[target] == blk)
266*59bfda1fSAndroid Build Coastguard Worker 			return target;  /* found target or empty cache slot */
267*59bfda1fSAndroid Build Coastguard Worker 		if (dcache_lastused[target] < dcache_lastused[least_used])
268*59bfda1fSAndroid Build Coastguard Worker 			least_used = target;
269*59bfda1fSAndroid Build Coastguard Worker 		target = dcache_relocate(entry, try); /* next target */
270*59bfda1fSAndroid Build Coastguard Worker 	}
271*59bfda1fSAndroid Build Coastguard Worker 	return least_used;  /* max search reached, return least used slot */
272*59bfda1fSAndroid Build Coastguard Worker }
273*59bfda1fSAndroid Build Coastguard Worker 
274*59bfda1fSAndroid Build Coastguard Worker /* Physical read into cache */
dcache_io_read(long entry,__u64 offset,off_t blk)275*59bfda1fSAndroid Build Coastguard Worker static int dcache_io_read(long entry, __u64 offset, off_t blk)
276*59bfda1fSAndroid Build Coastguard Worker {
277*59bfda1fSAndroid Build Coastguard Worker 	int fd = __get_device_fd(&offset);
278*59bfda1fSAndroid Build Coastguard Worker 
279*59bfda1fSAndroid Build Coastguard Worker 	if (fd < 0)
280*59bfda1fSAndroid Build Coastguard Worker 		return fd;
281*59bfda1fSAndroid Build Coastguard Worker 
282*59bfda1fSAndroid Build Coastguard Worker 	if (lseek(fd, offset, SEEK_SET) < 0) {
283*59bfda1fSAndroid Build Coastguard Worker 		MSG(0, "\n lseek fail.\n");
284*59bfda1fSAndroid Build Coastguard Worker 		return -1;
285*59bfda1fSAndroid Build Coastguard Worker 	}
286*59bfda1fSAndroid Build Coastguard Worker 	if (read(fd, dcache_buf + entry * F2FS_BLKSIZE, F2FS_BLKSIZE) < 0) {
287*59bfda1fSAndroid Build Coastguard Worker 		MSG(0, "\n read() fail.\n");
288*59bfda1fSAndroid Build Coastguard Worker 		return -1;
289*59bfda1fSAndroid Build Coastguard Worker 	}
290*59bfda1fSAndroid Build Coastguard Worker 	dcache_lastused[entry] = ++dcache_usetick;
291*59bfda1fSAndroid Build Coastguard Worker 	dcache_valid[entry] = true;
292*59bfda1fSAndroid Build Coastguard Worker 	dcache_blk[entry] = blk;
293*59bfda1fSAndroid Build Coastguard Worker 	return 0;
294*59bfda1fSAndroid Build Coastguard Worker }
295*59bfda1fSAndroid Build Coastguard Worker 
296*59bfda1fSAndroid Build Coastguard Worker /*
297*59bfda1fSAndroid Build Coastguard Worker  *  - Note: Read/Write are not symmetric:
298*59bfda1fSAndroid Build Coastguard Worker  *       For read, we need to do it block by block, due to the cache nature:
299*59bfda1fSAndroid Build Coastguard Worker  *           some blocks may be cached, and others don't.
300*59bfda1fSAndroid Build Coastguard Worker  *       For write, since we always do a write-thru, we can join all writes into one,
301*59bfda1fSAndroid Build Coastguard Worker  *       and write it once at the caller.  This function updates the cache for write, but
302*59bfda1fSAndroid Build Coastguard Worker  *       not the do a physical write.  The caller is responsible for the physical write.
303*59bfda1fSAndroid Build Coastguard Worker  *  - Note: We concentrate read/write together, due to the fact of similar structure to find
304*59bfda1fSAndroid Build Coastguard Worker  *          the relavant cache entries
305*59bfda1fSAndroid Build Coastguard Worker  *  - Return values:
306*59bfda1fSAndroid Build Coastguard Worker  *       0: success
307*59bfda1fSAndroid Build Coastguard Worker  *       1: cache not available (uninitialized)
308*59bfda1fSAndroid Build Coastguard Worker  *      -1: error
309*59bfda1fSAndroid Build Coastguard Worker  */
dcache_update_rw(void * buf,__u64 offset,size_t byte_count,bool is_write)310*59bfda1fSAndroid Build Coastguard Worker static int dcache_update_rw(void *buf, __u64 offset,
311*59bfda1fSAndroid Build Coastguard Worker 		size_t byte_count, bool is_write)
312*59bfda1fSAndroid Build Coastguard Worker {
313*59bfda1fSAndroid Build Coastguard Worker 	__u64 blk, start;
314*59bfda1fSAndroid Build Coastguard Worker 	int addr_in_blk;
315*59bfda1fSAndroid Build Coastguard Worker 
316*59bfda1fSAndroid Build Coastguard Worker 	if (!dcache_initialized)
317*59bfda1fSAndroid Build Coastguard Worker 		dcache_init(); /* auto initialize */
318*59bfda1fSAndroid Build Coastguard Worker 
319*59bfda1fSAndroid Build Coastguard Worker 	if (!dcache_initialized)
320*59bfda1fSAndroid Build Coastguard Worker 		return 1; /* not available */
321*59bfda1fSAndroid Build Coastguard Worker 
322*59bfda1fSAndroid Build Coastguard Worker 	blk = offset / F2FS_BLKSIZE;
323*59bfda1fSAndroid Build Coastguard Worker 	addr_in_blk = offset % F2FS_BLKSIZE;
324*59bfda1fSAndroid Build Coastguard Worker 	start = blk * F2FS_BLKSIZE;
325*59bfda1fSAndroid Build Coastguard Worker 
326*59bfda1fSAndroid Build Coastguard Worker 	while (byte_count != 0) {
327*59bfda1fSAndroid Build Coastguard Worker 		size_t cur_size = min(byte_count,
328*59bfda1fSAndroid Build Coastguard Worker 				(size_t)(F2FS_BLKSIZE - addr_in_blk));
329*59bfda1fSAndroid Build Coastguard Worker 		long entry = dcache_find(blk);
330*59bfda1fSAndroid Build Coastguard Worker 
331*59bfda1fSAndroid Build Coastguard Worker 		if (!is_write)
332*59bfda1fSAndroid Build Coastguard Worker 			++dcache_raccess;
333*59bfda1fSAndroid Build Coastguard Worker 
334*59bfda1fSAndroid Build Coastguard Worker 		if (dcache_valid[entry] && dcache_blk[entry] == blk) {
335*59bfda1fSAndroid Build Coastguard Worker 			/* cache hit */
336*59bfda1fSAndroid Build Coastguard Worker 			if (is_write)  /* write: update cache */
337*59bfda1fSAndroid Build Coastguard Worker 				memcpy(dcache_addr(entry) + addr_in_blk,
338*59bfda1fSAndroid Build Coastguard Worker 					buf, cur_size);
339*59bfda1fSAndroid Build Coastguard Worker 			else
340*59bfda1fSAndroid Build Coastguard Worker 				++dcache_rhit;
341*59bfda1fSAndroid Build Coastguard Worker 		} else {
342*59bfda1fSAndroid Build Coastguard Worker 			/* cache miss */
343*59bfda1fSAndroid Build Coastguard Worker 			if (!is_write) {
344*59bfda1fSAndroid Build Coastguard Worker 				int err;
345*59bfda1fSAndroid Build Coastguard Worker 				++dcache_rmiss;
346*59bfda1fSAndroid Build Coastguard Worker 				if (dcache_valid[entry])
347*59bfda1fSAndroid Build Coastguard Worker 					++dcache_rreplace;
348*59bfda1fSAndroid Build Coastguard Worker 				/* read: physical I/O read into cache */
349*59bfda1fSAndroid Build Coastguard Worker 				err = dcache_io_read(entry, start, blk);
350*59bfda1fSAndroid Build Coastguard Worker 				if (err)
351*59bfda1fSAndroid Build Coastguard Worker 					return err;
352*59bfda1fSAndroid Build Coastguard Worker 			}
353*59bfda1fSAndroid Build Coastguard Worker 		}
354*59bfda1fSAndroid Build Coastguard Worker 
355*59bfda1fSAndroid Build Coastguard Worker 		/* read: copy data from cache */
356*59bfda1fSAndroid Build Coastguard Worker 		/* write: nothing to do, since we don't do physical write. */
357*59bfda1fSAndroid Build Coastguard Worker 		if (!is_write)
358*59bfda1fSAndroid Build Coastguard Worker 			memcpy(buf, dcache_addr(entry) + addr_in_blk,
359*59bfda1fSAndroid Build Coastguard Worker 				cur_size);
360*59bfda1fSAndroid Build Coastguard Worker 
361*59bfda1fSAndroid Build Coastguard Worker 		/* next block */
362*59bfda1fSAndroid Build Coastguard Worker 		++blk;
363*59bfda1fSAndroid Build Coastguard Worker 		buf += cur_size;
364*59bfda1fSAndroid Build Coastguard Worker 		start += F2FS_BLKSIZE;
365*59bfda1fSAndroid Build Coastguard Worker 		byte_count -= cur_size;
366*59bfda1fSAndroid Build Coastguard Worker 		addr_in_blk = 0;
367*59bfda1fSAndroid Build Coastguard Worker 	}
368*59bfda1fSAndroid Build Coastguard Worker 	return 0;
369*59bfda1fSAndroid Build Coastguard Worker }
370*59bfda1fSAndroid Build Coastguard Worker 
371*59bfda1fSAndroid Build Coastguard Worker /*
372*59bfda1fSAndroid Build Coastguard Worker  * dcache_update_cache() just update cache, won't do physical I/O.
373*59bfda1fSAndroid Build Coastguard Worker  * Thus even no error, we need normal non-cache I/O for actual write
374*59bfda1fSAndroid Build Coastguard Worker  *
375*59bfda1fSAndroid Build Coastguard Worker  * return value: 1: cache not available
376*59bfda1fSAndroid Build Coastguard Worker  *               0: success, -1: I/O error
377*59bfda1fSAndroid Build Coastguard Worker  */
dcache_update_cache(void * buf,__u64 offset,size_t count)378*59bfda1fSAndroid Build Coastguard Worker int dcache_update_cache(void *buf, __u64 offset, size_t count)
379*59bfda1fSAndroid Build Coastguard Worker {
380*59bfda1fSAndroid Build Coastguard Worker 	return dcache_update_rw(buf, offset, count, true);
381*59bfda1fSAndroid Build Coastguard Worker }
382*59bfda1fSAndroid Build Coastguard Worker 
383*59bfda1fSAndroid Build Coastguard Worker /* handles read into cache + read into buffer  */
dcache_read(void * buf,__u64 offset,size_t count)384*59bfda1fSAndroid Build Coastguard Worker int dcache_read(void *buf, __u64 offset, size_t count)
385*59bfda1fSAndroid Build Coastguard Worker {
386*59bfda1fSAndroid Build Coastguard Worker 	return dcache_update_rw(buf, offset, count, false);
387*59bfda1fSAndroid Build Coastguard Worker }
388*59bfda1fSAndroid Build Coastguard Worker 
389*59bfda1fSAndroid Build Coastguard Worker /*
390*59bfda1fSAndroid Build Coastguard Worker  * IO interfaces
391*59bfda1fSAndroid Build Coastguard Worker  */
dev_read_version(void * buf,__u64 offset,size_t len)392*59bfda1fSAndroid Build Coastguard Worker int dev_read_version(void *buf, __u64 offset, size_t len)
393*59bfda1fSAndroid Build Coastguard Worker {
394*59bfda1fSAndroid Build Coastguard Worker 	if (c.sparse_mode)
395*59bfda1fSAndroid Build Coastguard Worker 		return 0;
396*59bfda1fSAndroid Build Coastguard Worker 	if (lseek(c.kd, (off_t)offset, SEEK_SET) < 0)
397*59bfda1fSAndroid Build Coastguard Worker 		return -1;
398*59bfda1fSAndroid Build Coastguard Worker 	if (read(c.kd, buf, len) < 0)
399*59bfda1fSAndroid Build Coastguard Worker 		return -1;
400*59bfda1fSAndroid Build Coastguard Worker 	return 0;
401*59bfda1fSAndroid Build Coastguard Worker }
402*59bfda1fSAndroid Build Coastguard Worker 
403*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SPARSE_SPARSE_H
sparse_read_blk(__u64 block,int count,void * buf)404*59bfda1fSAndroid Build Coastguard Worker static int sparse_read_blk(__u64 block, int count, void *buf)
405*59bfda1fSAndroid Build Coastguard Worker {
406*59bfda1fSAndroid Build Coastguard Worker 	int i;
407*59bfda1fSAndroid Build Coastguard Worker 	char *out = buf;
408*59bfda1fSAndroid Build Coastguard Worker 	__u64 cur_block;
409*59bfda1fSAndroid Build Coastguard Worker 
410*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < count; ++i) {
411*59bfda1fSAndroid Build Coastguard Worker 		cur_block = block + i;
412*59bfda1fSAndroid Build Coastguard Worker 		if (blocks[cur_block])
413*59bfda1fSAndroid Build Coastguard Worker 			memcpy(out + (i * F2FS_BLKSIZE),
414*59bfda1fSAndroid Build Coastguard Worker 					blocks[cur_block], F2FS_BLKSIZE);
415*59bfda1fSAndroid Build Coastguard Worker 		else if (blocks)
416*59bfda1fSAndroid Build Coastguard Worker 			memset(out + (i * F2FS_BLKSIZE), 0, F2FS_BLKSIZE);
417*59bfda1fSAndroid Build Coastguard Worker 	}
418*59bfda1fSAndroid Build Coastguard Worker 	return 0;
419*59bfda1fSAndroid Build Coastguard Worker }
420*59bfda1fSAndroid Build Coastguard Worker 
sparse_write_blk(__u64 block,int count,const void * buf)421*59bfda1fSAndroid Build Coastguard Worker static int sparse_write_blk(__u64 block, int count, const void *buf)
422*59bfda1fSAndroid Build Coastguard Worker {
423*59bfda1fSAndroid Build Coastguard Worker 	int i;
424*59bfda1fSAndroid Build Coastguard Worker 	__u64 cur_block;
425*59bfda1fSAndroid Build Coastguard Worker 	const char *in = buf;
426*59bfda1fSAndroid Build Coastguard Worker 
427*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < count; ++i) {
428*59bfda1fSAndroid Build Coastguard Worker 		cur_block = block + i;
429*59bfda1fSAndroid Build Coastguard Worker 		if (blocks[cur_block] == zeroed_block)
430*59bfda1fSAndroid Build Coastguard Worker 			blocks[cur_block] = NULL;
431*59bfda1fSAndroid Build Coastguard Worker 		if (!blocks[cur_block]) {
432*59bfda1fSAndroid Build Coastguard Worker 			blocks[cur_block] = calloc(1, F2FS_BLKSIZE);
433*59bfda1fSAndroid Build Coastguard Worker 			if (!blocks[cur_block])
434*59bfda1fSAndroid Build Coastguard Worker 				return -ENOMEM;
435*59bfda1fSAndroid Build Coastguard Worker 		}
436*59bfda1fSAndroid Build Coastguard Worker 		memcpy(blocks[cur_block], in + (i * F2FS_BLKSIZE),
437*59bfda1fSAndroid Build Coastguard Worker 				F2FS_BLKSIZE);
438*59bfda1fSAndroid Build Coastguard Worker 	}
439*59bfda1fSAndroid Build Coastguard Worker 	return 0;
440*59bfda1fSAndroid Build Coastguard Worker }
441*59bfda1fSAndroid Build Coastguard Worker 
sparse_write_zeroed_blk(__u64 block,int count)442*59bfda1fSAndroid Build Coastguard Worker static int sparse_write_zeroed_blk(__u64 block, int count)
443*59bfda1fSAndroid Build Coastguard Worker {
444*59bfda1fSAndroid Build Coastguard Worker 	int i;
445*59bfda1fSAndroid Build Coastguard Worker 	__u64 cur_block;
446*59bfda1fSAndroid Build Coastguard Worker 
447*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < count; ++i) {
448*59bfda1fSAndroid Build Coastguard Worker 		cur_block = block + i;
449*59bfda1fSAndroid Build Coastguard Worker 		if (blocks[cur_block])
450*59bfda1fSAndroid Build Coastguard Worker 			continue;
451*59bfda1fSAndroid Build Coastguard Worker 		blocks[cur_block] = zeroed_block;
452*59bfda1fSAndroid Build Coastguard Worker 	}
453*59bfda1fSAndroid Build Coastguard Worker 	return 0;
454*59bfda1fSAndroid Build Coastguard Worker }
455*59bfda1fSAndroid Build Coastguard Worker 
456*59bfda1fSAndroid Build Coastguard Worker #ifdef SPARSE_CALLBACK_USES_SIZE_T
sparse_import_segment(void * UNUSED (priv),const void * data,size_t len,unsigned int block,unsigned int nr_blocks)457*59bfda1fSAndroid Build Coastguard Worker static int sparse_import_segment(void *UNUSED(priv), const void *data,
458*59bfda1fSAndroid Build Coastguard Worker 		size_t len, unsigned int block, unsigned int nr_blocks)
459*59bfda1fSAndroid Build Coastguard Worker #else
460*59bfda1fSAndroid Build Coastguard Worker static int sparse_import_segment(void *UNUSED(priv), const void *data, int len,
461*59bfda1fSAndroid Build Coastguard Worker 		unsigned int block, unsigned int nr_blocks)
462*59bfda1fSAndroid Build Coastguard Worker #endif
463*59bfda1fSAndroid Build Coastguard Worker {
464*59bfda1fSAndroid Build Coastguard Worker 	/* Ignore chunk headers, only write the data */
465*59bfda1fSAndroid Build Coastguard Worker 	if (!nr_blocks || len % F2FS_BLKSIZE)
466*59bfda1fSAndroid Build Coastguard Worker 		return 0;
467*59bfda1fSAndroid Build Coastguard Worker 
468*59bfda1fSAndroid Build Coastguard Worker 	return sparse_write_blk(block, nr_blocks, data);
469*59bfda1fSAndroid Build Coastguard Worker }
470*59bfda1fSAndroid Build Coastguard Worker 
sparse_merge_blocks(uint64_t start,uint64_t num,int zero)471*59bfda1fSAndroid Build Coastguard Worker static int sparse_merge_blocks(uint64_t start, uint64_t num, int zero)
472*59bfda1fSAndroid Build Coastguard Worker {
473*59bfda1fSAndroid Build Coastguard Worker 	char *buf;
474*59bfda1fSAndroid Build Coastguard Worker 	uint64_t i;
475*59bfda1fSAndroid Build Coastguard Worker 
476*59bfda1fSAndroid Build Coastguard Worker 	if (zero) {
477*59bfda1fSAndroid Build Coastguard Worker 		blocks[start] = NULL;
478*59bfda1fSAndroid Build Coastguard Worker 		return sparse_file_add_fill(f2fs_sparse_file, 0x0,
479*59bfda1fSAndroid Build Coastguard Worker 					F2FS_BLKSIZE * num, start);
480*59bfda1fSAndroid Build Coastguard Worker 	}
481*59bfda1fSAndroid Build Coastguard Worker 
482*59bfda1fSAndroid Build Coastguard Worker 	buf = calloc(num, F2FS_BLKSIZE);
483*59bfda1fSAndroid Build Coastguard Worker 	if (!buf) {
484*59bfda1fSAndroid Build Coastguard Worker 		fprintf(stderr, "failed to alloc %llu\n",
485*59bfda1fSAndroid Build Coastguard Worker 			(unsigned long long)num * F2FS_BLKSIZE);
486*59bfda1fSAndroid Build Coastguard Worker 		return -ENOMEM;
487*59bfda1fSAndroid Build Coastguard Worker 	}
488*59bfda1fSAndroid Build Coastguard Worker 
489*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < num; i++) {
490*59bfda1fSAndroid Build Coastguard Worker 		memcpy(buf + i * F2FS_BLKSIZE, blocks[start + i], F2FS_BLKSIZE);
491*59bfda1fSAndroid Build Coastguard Worker 		free(blocks[start + i]);
492*59bfda1fSAndroid Build Coastguard Worker 		blocks[start + i] = NULL;
493*59bfda1fSAndroid Build Coastguard Worker 	}
494*59bfda1fSAndroid Build Coastguard Worker 
495*59bfda1fSAndroid Build Coastguard Worker 	/* free_sparse_blocks will release this buf. */
496*59bfda1fSAndroid Build Coastguard Worker 	blocks[start] = buf;
497*59bfda1fSAndroid Build Coastguard Worker 
498*59bfda1fSAndroid Build Coastguard Worker 	return sparse_file_add_data(f2fs_sparse_file, blocks[start],
499*59bfda1fSAndroid Build Coastguard Worker 					F2FS_BLKSIZE * num, start);
500*59bfda1fSAndroid Build Coastguard Worker }
501*59bfda1fSAndroid Build Coastguard Worker #else
sparse_read_blk(__u64 UNUSED (block),int UNUSED (count),void * UNUSED (buf))502*59bfda1fSAndroid Build Coastguard Worker static int sparse_read_blk(__u64 UNUSED(block),
503*59bfda1fSAndroid Build Coastguard Worker 				int UNUSED(count), void *UNUSED(buf))
504*59bfda1fSAndroid Build Coastguard Worker {
505*59bfda1fSAndroid Build Coastguard Worker 	return 0;
506*59bfda1fSAndroid Build Coastguard Worker }
507*59bfda1fSAndroid Build Coastguard Worker 
sparse_write_blk(__u64 UNUSED (block),int UNUSED (count),const void * UNUSED (buf))508*59bfda1fSAndroid Build Coastguard Worker static int sparse_write_blk(__u64 UNUSED(block),
509*59bfda1fSAndroid Build Coastguard Worker 				int UNUSED(count), const void *UNUSED(buf))
510*59bfda1fSAndroid Build Coastguard Worker {
511*59bfda1fSAndroid Build Coastguard Worker 	return 0;
512*59bfda1fSAndroid Build Coastguard Worker }
513*59bfda1fSAndroid Build Coastguard Worker 
sparse_write_zeroed_blk(__u64 UNUSED (block),int UNUSED (count))514*59bfda1fSAndroid Build Coastguard Worker static int sparse_write_zeroed_blk(__u64 UNUSED(block), int UNUSED(count))
515*59bfda1fSAndroid Build Coastguard Worker {
516*59bfda1fSAndroid Build Coastguard Worker 	return 0;
517*59bfda1fSAndroid Build Coastguard Worker }
518*59bfda1fSAndroid Build Coastguard Worker #endif
519*59bfda1fSAndroid Build Coastguard Worker 
dev_read(void * buf,__u64 offset,size_t len)520*59bfda1fSAndroid Build Coastguard Worker int dev_read(void *buf, __u64 offset, size_t len)
521*59bfda1fSAndroid Build Coastguard Worker {
522*59bfda1fSAndroid Build Coastguard Worker 	int fd;
523*59bfda1fSAndroid Build Coastguard Worker 	int err;
524*59bfda1fSAndroid Build Coastguard Worker 
525*59bfda1fSAndroid Build Coastguard Worker 	if (c.sparse_mode)
526*59bfda1fSAndroid Build Coastguard Worker 		return sparse_read_blk(offset / F2FS_BLKSIZE,
527*59bfda1fSAndroid Build Coastguard Worker 					len / F2FS_BLKSIZE, buf);
528*59bfda1fSAndroid Build Coastguard Worker 
529*59bfda1fSAndroid Build Coastguard Worker 	/* err = 1: cache not available, fall back to non-cache R/W */
530*59bfda1fSAndroid Build Coastguard Worker 	/* err = 0: success, err=-1: I/O error */
531*59bfda1fSAndroid Build Coastguard Worker 	err = dcache_read(buf, offset, len);
532*59bfda1fSAndroid Build Coastguard Worker 	if (err <= 0)
533*59bfda1fSAndroid Build Coastguard Worker 		return err;
534*59bfda1fSAndroid Build Coastguard Worker 
535*59bfda1fSAndroid Build Coastguard Worker 	fd = __get_device_fd(&offset);
536*59bfda1fSAndroid Build Coastguard Worker 	if (fd < 0)
537*59bfda1fSAndroid Build Coastguard Worker 		return fd;
538*59bfda1fSAndroid Build Coastguard Worker 	if (lseek(fd, (off_t)offset, SEEK_SET) < 0)
539*59bfda1fSAndroid Build Coastguard Worker 		return -1;
540*59bfda1fSAndroid Build Coastguard Worker 	if (read(fd, buf, len) < 0)
541*59bfda1fSAndroid Build Coastguard Worker 		return -1;
542*59bfda1fSAndroid Build Coastguard Worker 	return 0;
543*59bfda1fSAndroid Build Coastguard Worker }
544*59bfda1fSAndroid Build Coastguard Worker 
545*59bfda1fSAndroid Build Coastguard Worker #ifdef POSIX_FADV_WILLNEED
dev_readahead(__u64 offset,size_t len)546*59bfda1fSAndroid Build Coastguard Worker int dev_readahead(__u64 offset, size_t len)
547*59bfda1fSAndroid Build Coastguard Worker #else
548*59bfda1fSAndroid Build Coastguard Worker int dev_readahead(__u64 offset, size_t UNUSED(len))
549*59bfda1fSAndroid Build Coastguard Worker #endif
550*59bfda1fSAndroid Build Coastguard Worker {
551*59bfda1fSAndroid Build Coastguard Worker 	int fd = __get_device_fd(&offset);
552*59bfda1fSAndroid Build Coastguard Worker 
553*59bfda1fSAndroid Build Coastguard Worker 	if (fd < 0)
554*59bfda1fSAndroid Build Coastguard Worker 		return fd;
555*59bfda1fSAndroid Build Coastguard Worker #ifdef POSIX_FADV_WILLNEED
556*59bfda1fSAndroid Build Coastguard Worker 	return posix_fadvise(fd, offset, len, POSIX_FADV_WILLNEED);
557*59bfda1fSAndroid Build Coastguard Worker #else
558*59bfda1fSAndroid Build Coastguard Worker 	return 0;
559*59bfda1fSAndroid Build Coastguard Worker #endif
560*59bfda1fSAndroid Build Coastguard Worker }
561*59bfda1fSAndroid Build Coastguard Worker /*
562*59bfda1fSAndroid Build Coastguard Worker  * Copied from fs/f2fs/segment.c
563*59bfda1fSAndroid Build Coastguard Worker  */
564*59bfda1fSAndroid Build Coastguard Worker /*
565*59bfda1fSAndroid Build Coastguard Worker  * This returns write hints for each segment type. This hints will be
566*59bfda1fSAndroid Build Coastguard Worker  * passed down to block layer as below by default.
567*59bfda1fSAndroid Build Coastguard Worker  *
568*59bfda1fSAndroid Build Coastguard Worker  * User                  F2FS                     Block
569*59bfda1fSAndroid Build Coastguard Worker  * ----                  ----                     -----
570*59bfda1fSAndroid Build Coastguard Worker  *                       META                     WRITE_LIFE_NONE|REQ_META
571*59bfda1fSAndroid Build Coastguard Worker  *                       HOT_NODE                 WRITE_LIFE_NONE
572*59bfda1fSAndroid Build Coastguard Worker  *                       WARM_NODE                WRITE_LIFE_MEDIUM
573*59bfda1fSAndroid Build Coastguard Worker  *                       COLD_NODE                WRITE_LIFE_LONG
574*59bfda1fSAndroid Build Coastguard Worker  * ioctl(COLD)           COLD_DATA                WRITE_LIFE_EXTREME
575*59bfda1fSAndroid Build Coastguard Worker  * extension list        "                        "
576*59bfda1fSAndroid Build Coastguard Worker  *
577*59bfda1fSAndroid Build Coastguard Worker  * -- buffered io
578*59bfda1fSAndroid Build Coastguard Worker  *                       COLD_DATA                WRITE_LIFE_EXTREME
579*59bfda1fSAndroid Build Coastguard Worker  *                       HOT_DATA                 WRITE_LIFE_SHORT
580*59bfda1fSAndroid Build Coastguard Worker  *                       WARM_DATA                WRITE_LIFE_NOT_SET
581*59bfda1fSAndroid Build Coastguard Worker  *
582*59bfda1fSAndroid Build Coastguard Worker  * -- direct io
583*59bfda1fSAndroid Build Coastguard Worker  * WRITE_LIFE_EXTREME    COLD_DATA                WRITE_LIFE_EXTREME
584*59bfda1fSAndroid Build Coastguard Worker  * WRITE_LIFE_SHORT      HOT_DATA                 WRITE_LIFE_SHORT
585*59bfda1fSAndroid Build Coastguard Worker  * WRITE_LIFE_NOT_SET    WARM_DATA                WRITE_LIFE_NOT_SET
586*59bfda1fSAndroid Build Coastguard Worker  * WRITE_LIFE_NONE       "                        WRITE_LIFE_NONE
587*59bfda1fSAndroid Build Coastguard Worker  * WRITE_LIFE_MEDIUM     "                        WRITE_LIFE_MEDIUM
588*59bfda1fSAndroid Build Coastguard Worker  * WRITE_LIFE_LONG       "                        WRITE_LIFE_LONG
589*59bfda1fSAndroid Build Coastguard Worker  */
f2fs_io_type_to_rw_hint(int seg_type)590*59bfda1fSAndroid Build Coastguard Worker enum rw_hint f2fs_io_type_to_rw_hint(int seg_type)
591*59bfda1fSAndroid Build Coastguard Worker {
592*59bfda1fSAndroid Build Coastguard Worker 	switch (seg_type) {
593*59bfda1fSAndroid Build Coastguard Worker 	case CURSEG_WARM_DATA:
594*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_NOT_SET;
595*59bfda1fSAndroid Build Coastguard Worker 	case CURSEG_HOT_DATA:
596*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_SHORT;
597*59bfda1fSAndroid Build Coastguard Worker 	case CURSEG_COLD_DATA:
598*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_EXTREME;
599*59bfda1fSAndroid Build Coastguard Worker 	case CURSEG_WARM_NODE:
600*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_MEDIUM;
601*59bfda1fSAndroid Build Coastguard Worker 	case CURSEG_HOT_NODE:
602*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_NONE;
603*59bfda1fSAndroid Build Coastguard Worker 	case CURSEG_COLD_NODE:
604*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_LONG;
605*59bfda1fSAndroid Build Coastguard Worker 	default:
606*59bfda1fSAndroid Build Coastguard Worker 		return WRITE_LIFE_NONE;
607*59bfda1fSAndroid Build Coastguard Worker 	}
608*59bfda1fSAndroid Build Coastguard Worker }
609*59bfda1fSAndroid Build Coastguard Worker 
__dev_write(void * buf,__u64 offset,size_t len,enum rw_hint whint)610*59bfda1fSAndroid Build Coastguard Worker static int __dev_write(void *buf, __u64 offset, size_t len, enum rw_hint whint)
611*59bfda1fSAndroid Build Coastguard Worker {
612*59bfda1fSAndroid Build Coastguard Worker 	int fd;
613*59bfda1fSAndroid Build Coastguard Worker 
614*59bfda1fSAndroid Build Coastguard Worker 	fd = __get_device_fd(&offset);
615*59bfda1fSAndroid Build Coastguard Worker 	if (fd < 0)
616*59bfda1fSAndroid Build Coastguard Worker 		return fd;
617*59bfda1fSAndroid Build Coastguard Worker 
618*59bfda1fSAndroid Build Coastguard Worker 	if (lseek(fd, (off_t)offset, SEEK_SET) < 0)
619*59bfda1fSAndroid Build Coastguard Worker 		return -1;
620*59bfda1fSAndroid Build Coastguard Worker 
621*59bfda1fSAndroid Build Coastguard Worker #if ! defined(__MINGW32__)
622*59bfda1fSAndroid Build Coastguard Worker 	if (c.need_whint && (c.whint != whint)) {
623*59bfda1fSAndroid Build Coastguard Worker 		u64 hint = whint;
624*59bfda1fSAndroid Build Coastguard Worker 		int ret;
625*59bfda1fSAndroid Build Coastguard Worker 
626*59bfda1fSAndroid Build Coastguard Worker 		ret = fcntl(fd, F_SET_RW_HINT, &hint);
627*59bfda1fSAndroid Build Coastguard Worker 		if (ret != -1)
628*59bfda1fSAndroid Build Coastguard Worker 			c.whint = whint;
629*59bfda1fSAndroid Build Coastguard Worker 	}
630*59bfda1fSAndroid Build Coastguard Worker #endif
631*59bfda1fSAndroid Build Coastguard Worker 
632*59bfda1fSAndroid Build Coastguard Worker 	if (write(fd, buf, len) < 0)
633*59bfda1fSAndroid Build Coastguard Worker 		return -1;
634*59bfda1fSAndroid Build Coastguard Worker 
635*59bfda1fSAndroid Build Coastguard Worker 	c.need_fsync = true;
636*59bfda1fSAndroid Build Coastguard Worker 
637*59bfda1fSAndroid Build Coastguard Worker 	return 0;
638*59bfda1fSAndroid Build Coastguard Worker }
639*59bfda1fSAndroid Build Coastguard Worker 
dev_write(void * buf,__u64 offset,size_t len,enum rw_hint whint)640*59bfda1fSAndroid Build Coastguard Worker int dev_write(void *buf, __u64 offset, size_t len, enum rw_hint whint)
641*59bfda1fSAndroid Build Coastguard Worker {
642*59bfda1fSAndroid Build Coastguard Worker 	if (c.dry_run)
643*59bfda1fSAndroid Build Coastguard Worker 		return 0;
644*59bfda1fSAndroid Build Coastguard Worker 
645*59bfda1fSAndroid Build Coastguard Worker 	if (c.sparse_mode)
646*59bfda1fSAndroid Build Coastguard Worker 		return sparse_write_blk(offset / F2FS_BLKSIZE,
647*59bfda1fSAndroid Build Coastguard Worker 					len / F2FS_BLKSIZE, buf);
648*59bfda1fSAndroid Build Coastguard Worker 
649*59bfda1fSAndroid Build Coastguard Worker 	/*
650*59bfda1fSAndroid Build Coastguard Worker 	 * dcache_update_cache() just update cache, won't do I/O.
651*59bfda1fSAndroid Build Coastguard Worker 	 * Thus even no error, we need normal non-cache I/O for actual write
652*59bfda1fSAndroid Build Coastguard Worker 	 */
653*59bfda1fSAndroid Build Coastguard Worker 	if (dcache_update_cache(buf, offset, len) < 0)
654*59bfda1fSAndroid Build Coastguard Worker 		return -1;
655*59bfda1fSAndroid Build Coastguard Worker 
656*59bfda1fSAndroid Build Coastguard Worker 	return __dev_write(buf, offset, len, whint);
657*59bfda1fSAndroid Build Coastguard Worker }
658*59bfda1fSAndroid Build Coastguard Worker 
dev_write_block(void * buf,__u64 blk_addr,enum rw_hint whint)659*59bfda1fSAndroid Build Coastguard Worker int dev_write_block(void *buf, __u64 blk_addr, enum rw_hint whint)
660*59bfda1fSAndroid Build Coastguard Worker {
661*59bfda1fSAndroid Build Coastguard Worker 	return dev_write(buf, blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE, whint);
662*59bfda1fSAndroid Build Coastguard Worker }
663*59bfda1fSAndroid Build Coastguard Worker 
dev_write_dump(void * buf,__u64 offset,size_t len)664*59bfda1fSAndroid Build Coastguard Worker int dev_write_dump(void *buf, __u64 offset, size_t len)
665*59bfda1fSAndroid Build Coastguard Worker {
666*59bfda1fSAndroid Build Coastguard Worker 	if (lseek(c.dump_fd, (off_t)offset, SEEK_SET) < 0)
667*59bfda1fSAndroid Build Coastguard Worker 		return -1;
668*59bfda1fSAndroid Build Coastguard Worker 	if (write(c.dump_fd, buf, len) < 0)
669*59bfda1fSAndroid Build Coastguard Worker 		return -1;
670*59bfda1fSAndroid Build Coastguard Worker 	return 0;
671*59bfda1fSAndroid Build Coastguard Worker }
672*59bfda1fSAndroid Build Coastguard Worker 
673*59bfda1fSAndroid Build Coastguard Worker #if !defined(__MINGW32__)
dev_write_symlink(char * buf,size_t len)674*59bfda1fSAndroid Build Coastguard Worker int dev_write_symlink(char *buf, size_t len)
675*59bfda1fSAndroid Build Coastguard Worker {
676*59bfda1fSAndroid Build Coastguard Worker 	buf[len] = 0;
677*59bfda1fSAndroid Build Coastguard Worker 	if (symlink(buf, c.dump_symlink))
678*59bfda1fSAndroid Build Coastguard Worker 		return -1;
679*59bfda1fSAndroid Build Coastguard Worker 	return 0;
680*59bfda1fSAndroid Build Coastguard Worker }
681*59bfda1fSAndroid Build Coastguard Worker #endif
682*59bfda1fSAndroid Build Coastguard Worker 
dev_fill(void * buf,__u64 offset,size_t len,enum rw_hint whint)683*59bfda1fSAndroid Build Coastguard Worker int dev_fill(void *buf, __u64 offset, size_t len, enum rw_hint whint)
684*59bfda1fSAndroid Build Coastguard Worker {
685*59bfda1fSAndroid Build Coastguard Worker 	if (c.sparse_mode)
686*59bfda1fSAndroid Build Coastguard Worker 		return sparse_write_zeroed_blk(offset / F2FS_BLKSIZE,
687*59bfda1fSAndroid Build Coastguard Worker 						len / F2FS_BLKSIZE);
688*59bfda1fSAndroid Build Coastguard Worker 
689*59bfda1fSAndroid Build Coastguard Worker 	/* Only allow fill to zero */
690*59bfda1fSAndroid Build Coastguard Worker 	if (*((__u8*)buf))
691*59bfda1fSAndroid Build Coastguard Worker 		return -1;
692*59bfda1fSAndroid Build Coastguard Worker 
693*59bfda1fSAndroid Build Coastguard Worker 	return __dev_write(buf, offset, len, whint);
694*59bfda1fSAndroid Build Coastguard Worker }
695*59bfda1fSAndroid Build Coastguard Worker 
dev_fill_block(void * buf,__u64 blk_addr,enum rw_hint whint)696*59bfda1fSAndroid Build Coastguard Worker int dev_fill_block(void *buf, __u64 blk_addr, enum rw_hint whint)
697*59bfda1fSAndroid Build Coastguard Worker {
698*59bfda1fSAndroid Build Coastguard Worker 	return dev_fill(buf, blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE, whint);
699*59bfda1fSAndroid Build Coastguard Worker }
700*59bfda1fSAndroid Build Coastguard Worker 
dev_read_block(void * buf,__u64 blk_addr)701*59bfda1fSAndroid Build Coastguard Worker int dev_read_block(void *buf, __u64 blk_addr)
702*59bfda1fSAndroid Build Coastguard Worker {
703*59bfda1fSAndroid Build Coastguard Worker 	return dev_read(buf, blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE);
704*59bfda1fSAndroid Build Coastguard Worker }
705*59bfda1fSAndroid Build Coastguard Worker 
dev_reada_block(__u64 blk_addr)706*59bfda1fSAndroid Build Coastguard Worker int dev_reada_block(__u64 blk_addr)
707*59bfda1fSAndroid Build Coastguard Worker {
708*59bfda1fSAndroid Build Coastguard Worker 	return dev_readahead(blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE);
709*59bfda1fSAndroid Build Coastguard Worker }
710*59bfda1fSAndroid Build Coastguard Worker 
f2fs_fsync_device(void)711*59bfda1fSAndroid Build Coastguard Worker int f2fs_fsync_device(void)
712*59bfda1fSAndroid Build Coastguard Worker {
713*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_FSYNC
714*59bfda1fSAndroid Build Coastguard Worker 	int i;
715*59bfda1fSAndroid Build Coastguard Worker 
716*59bfda1fSAndroid Build Coastguard Worker 	if (!c.need_fsync)
717*59bfda1fSAndroid Build Coastguard Worker 		return 0;
718*59bfda1fSAndroid Build Coastguard Worker 
719*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < c.ndevs; i++) {
720*59bfda1fSAndroid Build Coastguard Worker 		if (fsync(c.devices[i].fd) < 0) {
721*59bfda1fSAndroid Build Coastguard Worker 			MSG(0, "\tError: Could not conduct fsync!!!\n");
722*59bfda1fSAndroid Build Coastguard Worker 			return -1;
723*59bfda1fSAndroid Build Coastguard Worker 		}
724*59bfda1fSAndroid Build Coastguard Worker 	}
725*59bfda1fSAndroid Build Coastguard Worker #endif
726*59bfda1fSAndroid Build Coastguard Worker 	return 0;
727*59bfda1fSAndroid Build Coastguard Worker }
728*59bfda1fSAndroid Build Coastguard Worker 
f2fs_init_sparse_file(void)729*59bfda1fSAndroid Build Coastguard Worker int f2fs_init_sparse_file(void)
730*59bfda1fSAndroid Build Coastguard Worker {
731*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SPARSE_SPARSE_H
732*59bfda1fSAndroid Build Coastguard Worker 	if (c.func == MKFS) {
733*59bfda1fSAndroid Build Coastguard Worker 		f2fs_sparse_file = sparse_file_new(F2FS_BLKSIZE, c.device_size);
734*59bfda1fSAndroid Build Coastguard Worker 		if (!f2fs_sparse_file)
735*59bfda1fSAndroid Build Coastguard Worker 			return -1;
736*59bfda1fSAndroid Build Coastguard Worker 	} else {
737*59bfda1fSAndroid Build Coastguard Worker 		f2fs_sparse_file = sparse_file_import(c.devices[0].fd,
738*59bfda1fSAndroid Build Coastguard Worker 							true, false);
739*59bfda1fSAndroid Build Coastguard Worker 		if (!f2fs_sparse_file)
740*59bfda1fSAndroid Build Coastguard Worker 			return -1;
741*59bfda1fSAndroid Build Coastguard Worker 
742*59bfda1fSAndroid Build Coastguard Worker 		c.blksize = sparse_file_block_size(f2fs_sparse_file);
743*59bfda1fSAndroid Build Coastguard Worker 		c.blksize_bits = log_base_2(c.blksize);
744*59bfda1fSAndroid Build Coastguard Worker 		if (c.blksize_bits == -1) {
745*59bfda1fSAndroid Build Coastguard Worker 			MSG(0, "\tError: Sparse file blocksize not a power of 2.\n");
746*59bfda1fSAndroid Build Coastguard Worker 			return -1;
747*59bfda1fSAndroid Build Coastguard Worker 		}
748*59bfda1fSAndroid Build Coastguard Worker 
749*59bfda1fSAndroid Build Coastguard Worker 		c.device_size = sparse_file_len(f2fs_sparse_file, 0, 0);
750*59bfda1fSAndroid Build Coastguard Worker 		c.device_size &= (~((uint64_t)(F2FS_BLKSIZE - 1)));
751*59bfda1fSAndroid Build Coastguard Worker 	}
752*59bfda1fSAndroid Build Coastguard Worker 
753*59bfda1fSAndroid Build Coastguard Worker 	blocks_count = c.device_size / F2FS_BLKSIZE;
754*59bfda1fSAndroid Build Coastguard Worker 	blocks = calloc(blocks_count, sizeof(char *));
755*59bfda1fSAndroid Build Coastguard Worker 	if (!blocks) {
756*59bfda1fSAndroid Build Coastguard Worker 		MSG(0, "\tError: Calloc Failed for blocks!!!\n");
757*59bfda1fSAndroid Build Coastguard Worker 		return -1;
758*59bfda1fSAndroid Build Coastguard Worker 	}
759*59bfda1fSAndroid Build Coastguard Worker 
760*59bfda1fSAndroid Build Coastguard Worker 	zeroed_block = calloc(1, F2FS_BLKSIZE);
761*59bfda1fSAndroid Build Coastguard Worker 	if (!zeroed_block) {
762*59bfda1fSAndroid Build Coastguard Worker 		MSG(0, "\tError: Calloc Failed for zeroed block!!!\n");
763*59bfda1fSAndroid Build Coastguard Worker 		return -1;
764*59bfda1fSAndroid Build Coastguard Worker 	}
765*59bfda1fSAndroid Build Coastguard Worker 
766*59bfda1fSAndroid Build Coastguard Worker 	return sparse_file_foreach_chunk(f2fs_sparse_file, true, false,
767*59bfda1fSAndroid Build Coastguard Worker 				sparse_import_segment, NULL);
768*59bfda1fSAndroid Build Coastguard Worker #else
769*59bfda1fSAndroid Build Coastguard Worker 	MSG(0, "\tError: Sparse mode is only supported for android\n");
770*59bfda1fSAndroid Build Coastguard Worker 	return -1;
771*59bfda1fSAndroid Build Coastguard Worker #endif
772*59bfda1fSAndroid Build Coastguard Worker }
773*59bfda1fSAndroid Build Coastguard Worker 
f2fs_release_sparse_resource(void)774*59bfda1fSAndroid Build Coastguard Worker void f2fs_release_sparse_resource(void)
775*59bfda1fSAndroid Build Coastguard Worker {
776*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SPARSE_SPARSE_H
777*59bfda1fSAndroid Build Coastguard Worker 	int j;
778*59bfda1fSAndroid Build Coastguard Worker 
779*59bfda1fSAndroid Build Coastguard Worker 	if (c.sparse_mode) {
780*59bfda1fSAndroid Build Coastguard Worker 		if (f2fs_sparse_file != NULL) {
781*59bfda1fSAndroid Build Coastguard Worker 			sparse_file_destroy(f2fs_sparse_file);
782*59bfda1fSAndroid Build Coastguard Worker 			f2fs_sparse_file = NULL;
783*59bfda1fSAndroid Build Coastguard Worker 		}
784*59bfda1fSAndroid Build Coastguard Worker 		for (j = 0; j < blocks_count; j++)
785*59bfda1fSAndroid Build Coastguard Worker 			free(blocks[j]);
786*59bfda1fSAndroid Build Coastguard Worker 		free(blocks);
787*59bfda1fSAndroid Build Coastguard Worker 		blocks = NULL;
788*59bfda1fSAndroid Build Coastguard Worker 		free(zeroed_block);
789*59bfda1fSAndroid Build Coastguard Worker 		zeroed_block = NULL;
790*59bfda1fSAndroid Build Coastguard Worker 	}
791*59bfda1fSAndroid Build Coastguard Worker #endif
792*59bfda1fSAndroid Build Coastguard Worker }
793*59bfda1fSAndroid Build Coastguard Worker 
794*59bfda1fSAndroid Build Coastguard Worker #define MAX_CHUNK_SIZE		(1 * 1024 * 1024 * 1024ULL)
795*59bfda1fSAndroid Build Coastguard Worker #define MAX_CHUNK_COUNT		(MAX_CHUNK_SIZE / F2FS_BLKSIZE)
f2fs_finalize_device(void)796*59bfda1fSAndroid Build Coastguard Worker int f2fs_finalize_device(void)
797*59bfda1fSAndroid Build Coastguard Worker {
798*59bfda1fSAndroid Build Coastguard Worker 	int i;
799*59bfda1fSAndroid Build Coastguard Worker 	int ret = 0;
800*59bfda1fSAndroid Build Coastguard Worker 
801*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SPARSE_SPARSE_H
802*59bfda1fSAndroid Build Coastguard Worker 	if (c.sparse_mode) {
803*59bfda1fSAndroid Build Coastguard Worker 		int64_t chunk_start = (blocks[0] == NULL) ? -1 : 0;
804*59bfda1fSAndroid Build Coastguard Worker 		uint64_t j;
805*59bfda1fSAndroid Build Coastguard Worker 
806*59bfda1fSAndroid Build Coastguard Worker 		if (c.func != MKFS) {
807*59bfda1fSAndroid Build Coastguard Worker 			sparse_file_destroy(f2fs_sparse_file);
808*59bfda1fSAndroid Build Coastguard Worker 			ret = ftruncate(c.devices[0].fd, 0);
809*59bfda1fSAndroid Build Coastguard Worker 			ASSERT(!ret);
810*59bfda1fSAndroid Build Coastguard Worker 			lseek(c.devices[0].fd, 0, SEEK_SET);
811*59bfda1fSAndroid Build Coastguard Worker 			f2fs_sparse_file = sparse_file_new(F2FS_BLKSIZE,
812*59bfda1fSAndroid Build Coastguard Worker 							c.device_size);
813*59bfda1fSAndroid Build Coastguard Worker 		}
814*59bfda1fSAndroid Build Coastguard Worker 
815*59bfda1fSAndroid Build Coastguard Worker 		for (j = 0; j < blocks_count; ++j) {
816*59bfda1fSAndroid Build Coastguard Worker 			if (chunk_start != -1) {
817*59bfda1fSAndroid Build Coastguard Worker 				if (j - chunk_start >= MAX_CHUNK_COUNT) {
818*59bfda1fSAndroid Build Coastguard Worker 					ret = sparse_merge_blocks(chunk_start,
819*59bfda1fSAndroid Build Coastguard Worker 							j - chunk_start, 0);
820*59bfda1fSAndroid Build Coastguard Worker 					ASSERT(!ret);
821*59bfda1fSAndroid Build Coastguard Worker 					chunk_start = -1;
822*59bfda1fSAndroid Build Coastguard Worker 				}
823*59bfda1fSAndroid Build Coastguard Worker 			}
824*59bfda1fSAndroid Build Coastguard Worker 
825*59bfda1fSAndroid Build Coastguard Worker 			if (chunk_start == -1) {
826*59bfda1fSAndroid Build Coastguard Worker 				if (!blocks[j])
827*59bfda1fSAndroid Build Coastguard Worker 					continue;
828*59bfda1fSAndroid Build Coastguard Worker 
829*59bfda1fSAndroid Build Coastguard Worker 				if (blocks[j] == zeroed_block) {
830*59bfda1fSAndroid Build Coastguard Worker 					ret = sparse_merge_blocks(j, 1, 1);
831*59bfda1fSAndroid Build Coastguard Worker 					ASSERT(!ret);
832*59bfda1fSAndroid Build Coastguard Worker 				} else {
833*59bfda1fSAndroid Build Coastguard Worker 					chunk_start = j;
834*59bfda1fSAndroid Build Coastguard Worker 				}
835*59bfda1fSAndroid Build Coastguard Worker 			} else {
836*59bfda1fSAndroid Build Coastguard Worker 				if (blocks[j] && blocks[j] != zeroed_block)
837*59bfda1fSAndroid Build Coastguard Worker 					continue;
838*59bfda1fSAndroid Build Coastguard Worker 
839*59bfda1fSAndroid Build Coastguard Worker 				ret = sparse_merge_blocks(chunk_start,
840*59bfda1fSAndroid Build Coastguard Worker 						j - chunk_start, 0);
841*59bfda1fSAndroid Build Coastguard Worker 				ASSERT(!ret);
842*59bfda1fSAndroid Build Coastguard Worker 
843*59bfda1fSAndroid Build Coastguard Worker 				if (blocks[j] == zeroed_block) {
844*59bfda1fSAndroid Build Coastguard Worker 					ret = sparse_merge_blocks(j, 1, 1);
845*59bfda1fSAndroid Build Coastguard Worker 					ASSERT(!ret);
846*59bfda1fSAndroid Build Coastguard Worker 				}
847*59bfda1fSAndroid Build Coastguard Worker 
848*59bfda1fSAndroid Build Coastguard Worker 				chunk_start = -1;
849*59bfda1fSAndroid Build Coastguard Worker 			}
850*59bfda1fSAndroid Build Coastguard Worker 		}
851*59bfda1fSAndroid Build Coastguard Worker 		if (chunk_start != -1) {
852*59bfda1fSAndroid Build Coastguard Worker 			ret = sparse_merge_blocks(chunk_start,
853*59bfda1fSAndroid Build Coastguard Worker 						blocks_count - chunk_start, 0);
854*59bfda1fSAndroid Build Coastguard Worker 			ASSERT(!ret);
855*59bfda1fSAndroid Build Coastguard Worker 		}
856*59bfda1fSAndroid Build Coastguard Worker 
857*59bfda1fSAndroid Build Coastguard Worker 		sparse_file_write(f2fs_sparse_file, c.devices[0].fd,
858*59bfda1fSAndroid Build Coastguard Worker 				/*gzip*/0, /*sparse*/1, /*crc*/0);
859*59bfda1fSAndroid Build Coastguard Worker 
860*59bfda1fSAndroid Build Coastguard Worker 		f2fs_release_sparse_resource();
861*59bfda1fSAndroid Build Coastguard Worker 	}
862*59bfda1fSAndroid Build Coastguard Worker #endif
863*59bfda1fSAndroid Build Coastguard Worker 	/*
864*59bfda1fSAndroid Build Coastguard Worker 	 * We should call fsync() to flush out all the dirty pages
865*59bfda1fSAndroid Build Coastguard Worker 	 * in the block device page cache.
866*59bfda1fSAndroid Build Coastguard Worker 	 */
867*59bfda1fSAndroid Build Coastguard Worker 	for (i = 0; i < c.ndevs; i++) {
868*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_FSYNC
869*59bfda1fSAndroid Build Coastguard Worker 		if (c.need_fsync) {
870*59bfda1fSAndroid Build Coastguard Worker 			ret = fsync(c.devices[i].fd);
871*59bfda1fSAndroid Build Coastguard Worker 			if (ret < 0) {
872*59bfda1fSAndroid Build Coastguard Worker 				MSG(0, "\tError: Could not conduct fsync!!!\n");
873*59bfda1fSAndroid Build Coastguard Worker 				break;
874*59bfda1fSAndroid Build Coastguard Worker 			}
875*59bfda1fSAndroid Build Coastguard Worker 		}
876*59bfda1fSAndroid Build Coastguard Worker #endif
877*59bfda1fSAndroid Build Coastguard Worker 		ret = close(c.devices[i].fd);
878*59bfda1fSAndroid Build Coastguard Worker 		if (ret < 0) {
879*59bfda1fSAndroid Build Coastguard Worker 			MSG(0, "\tError: Failed to close device file!!!\n");
880*59bfda1fSAndroid Build Coastguard Worker 			break;
881*59bfda1fSAndroid Build Coastguard Worker 		}
882*59bfda1fSAndroid Build Coastguard Worker 		free(c.devices[i].path);
883*59bfda1fSAndroid Build Coastguard Worker 		free(c.devices[i].zone_cap_blocks);
884*59bfda1fSAndroid Build Coastguard Worker 	}
885*59bfda1fSAndroid Build Coastguard Worker 	close(c.kd);
886*59bfda1fSAndroid Build Coastguard Worker 
887*59bfda1fSAndroid Build Coastguard Worker 	return ret;
888*59bfda1fSAndroid Build Coastguard Worker }
889