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