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 *
7*59bfda1fSAndroid Build Coastguard Worker * Dual licensed under the GPL or LGPL version 2 licenses.
8*59bfda1fSAndroid Build Coastguard Worker */
9*59bfda1fSAndroid Build Coastguard Worker #include <f2fs_fs.h>
10*59bfda1fSAndroid Build Coastguard Worker #include <stdio.h>
11*59bfda1fSAndroid Build Coastguard Worker #include <stdlib.h>
12*59bfda1fSAndroid Build Coastguard Worker #include <string.h>
13*59bfda1fSAndroid Build Coastguard Worker #include <errno.h>
14*59bfda1fSAndroid Build Coastguard Worker #include <unistd.h>
15*59bfda1fSAndroid Build Coastguard Worker #include <fcntl.h>
16*59bfda1fSAndroid Build Coastguard Worker #include <libgen.h>
17*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_MNTENT_H
18*59bfda1fSAndroid Build Coastguard Worker #include <mntent.h>
19*59bfda1fSAndroid Build Coastguard Worker #endif
20*59bfda1fSAndroid Build Coastguard Worker #include <time.h>
21*59bfda1fSAndroid Build Coastguard Worker #include <sys/stat.h>
22*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_LOOP_H
23*59bfda1fSAndroid Build Coastguard Worker #include <linux/loop.h>
24*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_MAJOR_H
25*59bfda1fSAndroid Build Coastguard Worker #include <linux/major.h>
26*59bfda1fSAndroid Build Coastguard Worker #endif
27*59bfda1fSAndroid Build Coastguard Worker #endif
28*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
29*59bfda1fSAndroid Build Coastguard Worker #include <sys/ioctl.h>
30*59bfda1fSAndroid Build Coastguard Worker #endif
31*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_SYSMACROS_H
32*59bfda1fSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
33*59bfda1fSAndroid Build Coastguard Worker #endif
34*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_UTSNAME_H
35*59bfda1fSAndroid Build Coastguard Worker #include <sys/utsname.h>
36*59bfda1fSAndroid Build Coastguard Worker #endif
37*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SCSI_SG_H
38*59bfda1fSAndroid Build Coastguard Worker #include <scsi/sg.h>
39*59bfda1fSAndroid Build Coastguard Worker #endif
40*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_HDREG_H
41*59bfda1fSAndroid Build Coastguard Worker #include <linux/hdreg.h>
42*59bfda1fSAndroid Build Coastguard Worker #endif
43*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_LIMITS_H
44*59bfda1fSAndroid Build Coastguard Worker #include <linux/limits.h>
45*59bfda1fSAndroid Build Coastguard Worker #endif
46*59bfda1fSAndroid Build Coastguard Worker
47*59bfda1fSAndroid Build Coastguard Worker /* SCSI command for standard inquiry*/
48*59bfda1fSAndroid Build Coastguard Worker #define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00
49*59bfda1fSAndroid Build Coastguard Worker
50*59bfda1fSAndroid Build Coastguard Worker #ifndef _WIN32 /* O_BINARY is windows-specific flag */
51*59bfda1fSAndroid Build Coastguard Worker #define O_BINARY 0
52*59bfda1fSAndroid Build Coastguard Worker #else
53*59bfda1fSAndroid Build Coastguard Worker /* On Windows, wchar_t is 8 bit sized and it causes compilation errors. */
54*59bfda1fSAndroid Build Coastguard Worker #define wchar_t int
55*59bfda1fSAndroid Build Coastguard Worker #endif
56*59bfda1fSAndroid Build Coastguard Worker
57*59bfda1fSAndroid Build Coastguard Worker /*
58*59bfda1fSAndroid Build Coastguard Worker * UTF conversion codes are Copied from exfat tools.
59*59bfda1fSAndroid Build Coastguard Worker */
utf8_to_wchar(const char * input,wchar_t * wc,size_t insize)60*59bfda1fSAndroid Build Coastguard Worker static const char *utf8_to_wchar(const char *input, wchar_t *wc,
61*59bfda1fSAndroid Build Coastguard Worker size_t insize)
62*59bfda1fSAndroid Build Coastguard Worker {
63*59bfda1fSAndroid Build Coastguard Worker if ((input[0] & 0x80) == 0 && insize >= 1) {
64*59bfda1fSAndroid Build Coastguard Worker *wc = (wchar_t) input[0];
65*59bfda1fSAndroid Build Coastguard Worker return input + 1;
66*59bfda1fSAndroid Build Coastguard Worker }
67*59bfda1fSAndroid Build Coastguard Worker if ((input[0] & 0xe0) == 0xc0 && insize >= 2) {
68*59bfda1fSAndroid Build Coastguard Worker *wc = (((wchar_t) input[0] & 0x1f) << 6) |
69*59bfda1fSAndroid Build Coastguard Worker ((wchar_t) input[1] & 0x3f);
70*59bfda1fSAndroid Build Coastguard Worker return input + 2;
71*59bfda1fSAndroid Build Coastguard Worker }
72*59bfda1fSAndroid Build Coastguard Worker if ((input[0] & 0xf0) == 0xe0 && insize >= 3) {
73*59bfda1fSAndroid Build Coastguard Worker *wc = (((wchar_t) input[0] & 0x0f) << 12) |
74*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[1] & 0x3f) << 6) |
75*59bfda1fSAndroid Build Coastguard Worker ((wchar_t) input[2] & 0x3f);
76*59bfda1fSAndroid Build Coastguard Worker return input + 3;
77*59bfda1fSAndroid Build Coastguard Worker }
78*59bfda1fSAndroid Build Coastguard Worker if ((input[0] & 0xf8) == 0xf0 && insize >= 4) {
79*59bfda1fSAndroid Build Coastguard Worker *wc = (((wchar_t) input[0] & 0x07) << 18) |
80*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[1] & 0x3f) << 12) |
81*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[2] & 0x3f) << 6) |
82*59bfda1fSAndroid Build Coastguard Worker ((wchar_t) input[3] & 0x3f);
83*59bfda1fSAndroid Build Coastguard Worker return input + 4;
84*59bfda1fSAndroid Build Coastguard Worker }
85*59bfda1fSAndroid Build Coastguard Worker if ((input[0] & 0xfc) == 0xf8 && insize >= 5) {
86*59bfda1fSAndroid Build Coastguard Worker *wc = (((wchar_t) input[0] & 0x03) << 24) |
87*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[1] & 0x3f) << 18) |
88*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[2] & 0x3f) << 12) |
89*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[3] & 0x3f) << 6) |
90*59bfda1fSAndroid Build Coastguard Worker ((wchar_t) input[4] & 0x3f);
91*59bfda1fSAndroid Build Coastguard Worker return input + 5;
92*59bfda1fSAndroid Build Coastguard Worker }
93*59bfda1fSAndroid Build Coastguard Worker if ((input[0] & 0xfe) == 0xfc && insize >= 6) {
94*59bfda1fSAndroid Build Coastguard Worker *wc = (((wchar_t) input[0] & 0x01) << 30) |
95*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[1] & 0x3f) << 24) |
96*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[2] & 0x3f) << 18) |
97*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[3] & 0x3f) << 12) |
98*59bfda1fSAndroid Build Coastguard Worker (((wchar_t) input[4] & 0x3f) << 6) |
99*59bfda1fSAndroid Build Coastguard Worker ((wchar_t) input[5] & 0x3f);
100*59bfda1fSAndroid Build Coastguard Worker return input + 6;
101*59bfda1fSAndroid Build Coastguard Worker }
102*59bfda1fSAndroid Build Coastguard Worker return NULL;
103*59bfda1fSAndroid Build Coastguard Worker }
104*59bfda1fSAndroid Build Coastguard Worker
wchar_to_utf16(uint16_t * output,wchar_t wc,size_t outsize)105*59bfda1fSAndroid Build Coastguard Worker static uint16_t *wchar_to_utf16(uint16_t *output, wchar_t wc, size_t outsize)
106*59bfda1fSAndroid Build Coastguard Worker {
107*59bfda1fSAndroid Build Coastguard Worker if (wc <= 0xffff) {
108*59bfda1fSAndroid Build Coastguard Worker if (outsize == 0)
109*59bfda1fSAndroid Build Coastguard Worker return NULL;
110*59bfda1fSAndroid Build Coastguard Worker output[0] = cpu_to_le16(wc);
111*59bfda1fSAndroid Build Coastguard Worker return output + 1;
112*59bfda1fSAndroid Build Coastguard Worker }
113*59bfda1fSAndroid Build Coastguard Worker if (outsize < 2)
114*59bfda1fSAndroid Build Coastguard Worker return NULL;
115*59bfda1fSAndroid Build Coastguard Worker wc -= 0x10000;
116*59bfda1fSAndroid Build Coastguard Worker output[0] = cpu_to_le16(0xd800 | ((wc >> 10) & 0x3ff));
117*59bfda1fSAndroid Build Coastguard Worker output[1] = cpu_to_le16(0xdc00 | (wc & 0x3ff));
118*59bfda1fSAndroid Build Coastguard Worker return output + 2;
119*59bfda1fSAndroid Build Coastguard Worker }
120*59bfda1fSAndroid Build Coastguard Worker
utf8_to_utf16(char * output,const char * input,size_t outsize,size_t insize)121*59bfda1fSAndroid Build Coastguard Worker int utf8_to_utf16(char *output, const char *input, size_t outsize,
122*59bfda1fSAndroid Build Coastguard Worker size_t insize)
123*59bfda1fSAndroid Build Coastguard Worker {
124*59bfda1fSAndroid Build Coastguard Worker const char *inp = input;
125*59bfda1fSAndroid Build Coastguard Worker uint16_t *outp;
126*59bfda1fSAndroid Build Coastguard Worker wchar_t wc;
127*59bfda1fSAndroid Build Coastguard Worker uint16_t *volume_name = calloc(sizeof(uint16_t), MAX_VOLUME_NAME);
128*59bfda1fSAndroid Build Coastguard Worker
129*59bfda1fSAndroid Build Coastguard Worker if (!volume_name)
130*59bfda1fSAndroid Build Coastguard Worker return -ENOMEM;
131*59bfda1fSAndroid Build Coastguard Worker
132*59bfda1fSAndroid Build Coastguard Worker outp = volume_name;
133*59bfda1fSAndroid Build Coastguard Worker
134*59bfda1fSAndroid Build Coastguard Worker while ((size_t)(inp - input) < insize && *inp) {
135*59bfda1fSAndroid Build Coastguard Worker inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
136*59bfda1fSAndroid Build Coastguard Worker if (inp == NULL) {
137*59bfda1fSAndroid Build Coastguard Worker DBG(0, "illegal UTF-8 sequence\n");
138*59bfda1fSAndroid Build Coastguard Worker free(volume_name);
139*59bfda1fSAndroid Build Coastguard Worker return -EILSEQ;
140*59bfda1fSAndroid Build Coastguard Worker }
141*59bfda1fSAndroid Build Coastguard Worker outp = wchar_to_utf16(outp, wc, outsize - (outp - volume_name));
142*59bfda1fSAndroid Build Coastguard Worker if (outp == NULL) {
143*59bfda1fSAndroid Build Coastguard Worker DBG(0, "name is too long\n");
144*59bfda1fSAndroid Build Coastguard Worker free(volume_name);
145*59bfda1fSAndroid Build Coastguard Worker return -ENAMETOOLONG;
146*59bfda1fSAndroid Build Coastguard Worker }
147*59bfda1fSAndroid Build Coastguard Worker }
148*59bfda1fSAndroid Build Coastguard Worker *outp = cpu_to_le16(0);
149*59bfda1fSAndroid Build Coastguard Worker memcpy(output, volume_name, sizeof(uint16_t) * MAX_VOLUME_NAME);
150*59bfda1fSAndroid Build Coastguard Worker free(volume_name);
151*59bfda1fSAndroid Build Coastguard Worker return 0;
152*59bfda1fSAndroid Build Coastguard Worker }
153*59bfda1fSAndroid Build Coastguard Worker
utf16_to_wchar(uint16_t * input,wchar_t * wc,size_t insize)154*59bfda1fSAndroid Build Coastguard Worker static uint16_t *utf16_to_wchar(uint16_t *input, wchar_t *wc, size_t insize)
155*59bfda1fSAndroid Build Coastguard Worker {
156*59bfda1fSAndroid Build Coastguard Worker if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) {
157*59bfda1fSAndroid Build Coastguard Worker if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00)
158*59bfda1fSAndroid Build Coastguard Worker return NULL;
159*59bfda1fSAndroid Build Coastguard Worker *wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
160*59bfda1fSAndroid Build Coastguard Worker *wc |= (le16_to_cpu(input[1]) & 0x3ff);
161*59bfda1fSAndroid Build Coastguard Worker *wc += 0x10000;
162*59bfda1fSAndroid Build Coastguard Worker return input + 2;
163*59bfda1fSAndroid Build Coastguard Worker } else {
164*59bfda1fSAndroid Build Coastguard Worker *wc = le16_to_cpu(*input);
165*59bfda1fSAndroid Build Coastguard Worker return input + 1;
166*59bfda1fSAndroid Build Coastguard Worker }
167*59bfda1fSAndroid Build Coastguard Worker }
168*59bfda1fSAndroid Build Coastguard Worker
wchar_to_utf8(char * output,wchar_t wc,size_t outsize)169*59bfda1fSAndroid Build Coastguard Worker static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize)
170*59bfda1fSAndroid Build Coastguard Worker {
171*59bfda1fSAndroid Build Coastguard Worker if (wc <= 0x7f) {
172*59bfda1fSAndroid Build Coastguard Worker if (outsize < 1)
173*59bfda1fSAndroid Build Coastguard Worker return NULL;
174*59bfda1fSAndroid Build Coastguard Worker *output++ = (char) wc;
175*59bfda1fSAndroid Build Coastguard Worker } else if (wc <= 0x7ff) {
176*59bfda1fSAndroid Build Coastguard Worker if (outsize < 2)
177*59bfda1fSAndroid Build Coastguard Worker return NULL;
178*59bfda1fSAndroid Build Coastguard Worker *output++ = 0xc0 | (wc >> 6);
179*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | (wc & 0x3f);
180*59bfda1fSAndroid Build Coastguard Worker } else if (wc <= 0xffff) {
181*59bfda1fSAndroid Build Coastguard Worker if (outsize < 3)
182*59bfda1fSAndroid Build Coastguard Worker return NULL;
183*59bfda1fSAndroid Build Coastguard Worker *output++ = 0xe0 | (wc >> 12);
184*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 6) & 0x3f);
185*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | (wc & 0x3f);
186*59bfda1fSAndroid Build Coastguard Worker } else if (wc <= 0x1fffff) {
187*59bfda1fSAndroid Build Coastguard Worker if (outsize < 4)
188*59bfda1fSAndroid Build Coastguard Worker return NULL;
189*59bfda1fSAndroid Build Coastguard Worker *output++ = 0xf0 | (wc >> 18);
190*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 12) & 0x3f);
191*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 6) & 0x3f);
192*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | (wc & 0x3f);
193*59bfda1fSAndroid Build Coastguard Worker } else if (wc <= 0x3ffffff) {
194*59bfda1fSAndroid Build Coastguard Worker if (outsize < 5)
195*59bfda1fSAndroid Build Coastguard Worker return NULL;
196*59bfda1fSAndroid Build Coastguard Worker *output++ = 0xf8 | (wc >> 24);
197*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 18) & 0x3f);
198*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 12) & 0x3f);
199*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 6) & 0x3f);
200*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | (wc & 0x3f);
201*59bfda1fSAndroid Build Coastguard Worker } else if (wc <= 0x7fffffff) {
202*59bfda1fSAndroid Build Coastguard Worker if (outsize < 6)
203*59bfda1fSAndroid Build Coastguard Worker return NULL;
204*59bfda1fSAndroid Build Coastguard Worker *output++ = 0xfc | (wc >> 30);
205*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 24) & 0x3f);
206*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 18) & 0x3f);
207*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 12) & 0x3f);
208*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | ((wc >> 6) & 0x3f);
209*59bfda1fSAndroid Build Coastguard Worker *output++ = 0x80 | (wc & 0x3f);
210*59bfda1fSAndroid Build Coastguard Worker } else
211*59bfda1fSAndroid Build Coastguard Worker return NULL;
212*59bfda1fSAndroid Build Coastguard Worker
213*59bfda1fSAndroid Build Coastguard Worker return output;
214*59bfda1fSAndroid Build Coastguard Worker }
215*59bfda1fSAndroid Build Coastguard Worker
utf16_to_utf8(char * output,const char * input,size_t outsize,size_t insize)216*59bfda1fSAndroid Build Coastguard Worker int utf16_to_utf8(char *output, const char *input, size_t outsize,
217*59bfda1fSAndroid Build Coastguard Worker size_t insize)
218*59bfda1fSAndroid Build Coastguard Worker {
219*59bfda1fSAndroid Build Coastguard Worker char *outp = output;
220*59bfda1fSAndroid Build Coastguard Worker wchar_t wc;
221*59bfda1fSAndroid Build Coastguard Worker uint16_t *inp;
222*59bfda1fSAndroid Build Coastguard Worker uint16_t *volume_name = calloc(sizeof(uint16_t), MAX_VOLUME_NAME);
223*59bfda1fSAndroid Build Coastguard Worker
224*59bfda1fSAndroid Build Coastguard Worker if (!volume_name)
225*59bfda1fSAndroid Build Coastguard Worker return -ENOMEM;
226*59bfda1fSAndroid Build Coastguard Worker
227*59bfda1fSAndroid Build Coastguard Worker memcpy(volume_name, input, sizeof(uint16_t) * MAX_VOLUME_NAME);
228*59bfda1fSAndroid Build Coastguard Worker inp = volume_name;
229*59bfda1fSAndroid Build Coastguard Worker
230*59bfda1fSAndroid Build Coastguard Worker while ((size_t)(inp - volume_name) < insize && le16_to_cpu(*inp)) {
231*59bfda1fSAndroid Build Coastguard Worker inp = utf16_to_wchar(inp, &wc, insize - (inp - volume_name));
232*59bfda1fSAndroid Build Coastguard Worker if (inp == NULL) {
233*59bfda1fSAndroid Build Coastguard Worker DBG(0, "illegal UTF-16 sequence\n");
234*59bfda1fSAndroid Build Coastguard Worker free(volume_name);
235*59bfda1fSAndroid Build Coastguard Worker return -EILSEQ;
236*59bfda1fSAndroid Build Coastguard Worker }
237*59bfda1fSAndroid Build Coastguard Worker outp = wchar_to_utf8(outp, wc, outsize - (outp - output));
238*59bfda1fSAndroid Build Coastguard Worker if (outp == NULL) {
239*59bfda1fSAndroid Build Coastguard Worker DBG(0, "name is too long\n");
240*59bfda1fSAndroid Build Coastguard Worker free(volume_name);
241*59bfda1fSAndroid Build Coastguard Worker return -ENAMETOOLONG;
242*59bfda1fSAndroid Build Coastguard Worker }
243*59bfda1fSAndroid Build Coastguard Worker }
244*59bfda1fSAndroid Build Coastguard Worker *outp = '\0';
245*59bfda1fSAndroid Build Coastguard Worker free(volume_name);
246*59bfda1fSAndroid Build Coastguard Worker return 0;
247*59bfda1fSAndroid Build Coastguard Worker }
248*59bfda1fSAndroid Build Coastguard Worker
log_base_2(uint32_t num)249*59bfda1fSAndroid Build Coastguard Worker int log_base_2(uint32_t num)
250*59bfda1fSAndroid Build Coastguard Worker {
251*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
252*59bfda1fSAndroid Build Coastguard Worker if (num <= 0 || (num & (num - 1)) != 0)
253*59bfda1fSAndroid Build Coastguard Worker return -1;
254*59bfda1fSAndroid Build Coastguard Worker
255*59bfda1fSAndroid Build Coastguard Worker while (num >>= 1)
256*59bfda1fSAndroid Build Coastguard Worker ret++;
257*59bfda1fSAndroid Build Coastguard Worker return ret;
258*59bfda1fSAndroid Build Coastguard Worker }
259*59bfda1fSAndroid Build Coastguard Worker
260*59bfda1fSAndroid Build Coastguard Worker /*
261*59bfda1fSAndroid Build Coastguard Worker * f2fs bit operations
262*59bfda1fSAndroid Build Coastguard Worker */
263*59bfda1fSAndroid Build Coastguard Worker static const int bits_in_byte[256] = {
264*59bfda1fSAndroid Build Coastguard Worker 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
265*59bfda1fSAndroid Build Coastguard Worker 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
266*59bfda1fSAndroid Build Coastguard Worker 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
267*59bfda1fSAndroid Build Coastguard Worker 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
268*59bfda1fSAndroid Build Coastguard Worker 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
269*59bfda1fSAndroid Build Coastguard Worker 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
270*59bfda1fSAndroid Build Coastguard Worker 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
271*59bfda1fSAndroid Build Coastguard Worker 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
272*59bfda1fSAndroid Build Coastguard Worker 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
273*59bfda1fSAndroid Build Coastguard Worker 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
274*59bfda1fSAndroid Build Coastguard Worker 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
275*59bfda1fSAndroid Build Coastguard Worker 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
276*59bfda1fSAndroid Build Coastguard Worker 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
277*59bfda1fSAndroid Build Coastguard Worker 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
278*59bfda1fSAndroid Build Coastguard Worker 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
279*59bfda1fSAndroid Build Coastguard Worker 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
280*59bfda1fSAndroid Build Coastguard Worker };
281*59bfda1fSAndroid Build Coastguard Worker
get_bits_in_byte(unsigned char n)282*59bfda1fSAndroid Build Coastguard Worker int get_bits_in_byte(unsigned char n)
283*59bfda1fSAndroid Build Coastguard Worker {
284*59bfda1fSAndroid Build Coastguard Worker return bits_in_byte[n];
285*59bfda1fSAndroid Build Coastguard Worker }
286*59bfda1fSAndroid Build Coastguard Worker
test_and_set_bit_le(u32 nr,u8 * addr)287*59bfda1fSAndroid Build Coastguard Worker int test_and_set_bit_le(u32 nr, u8 *addr)
288*59bfda1fSAndroid Build Coastguard Worker {
289*59bfda1fSAndroid Build Coastguard Worker int mask, retval;
290*59bfda1fSAndroid Build Coastguard Worker
291*59bfda1fSAndroid Build Coastguard Worker addr += nr >> 3;
292*59bfda1fSAndroid Build Coastguard Worker mask = 1 << ((nr & 0x07));
293*59bfda1fSAndroid Build Coastguard Worker retval = mask & *addr;
294*59bfda1fSAndroid Build Coastguard Worker *addr |= mask;
295*59bfda1fSAndroid Build Coastguard Worker return retval;
296*59bfda1fSAndroid Build Coastguard Worker }
297*59bfda1fSAndroid Build Coastguard Worker
test_and_clear_bit_le(u32 nr,u8 * addr)298*59bfda1fSAndroid Build Coastguard Worker int test_and_clear_bit_le(u32 nr, u8 *addr)
299*59bfda1fSAndroid Build Coastguard Worker {
300*59bfda1fSAndroid Build Coastguard Worker int mask, retval;
301*59bfda1fSAndroid Build Coastguard Worker
302*59bfda1fSAndroid Build Coastguard Worker addr += nr >> 3;
303*59bfda1fSAndroid Build Coastguard Worker mask = 1 << ((nr & 0x07));
304*59bfda1fSAndroid Build Coastguard Worker retval = mask & *addr;
305*59bfda1fSAndroid Build Coastguard Worker *addr &= ~mask;
306*59bfda1fSAndroid Build Coastguard Worker return retval;
307*59bfda1fSAndroid Build Coastguard Worker }
308*59bfda1fSAndroid Build Coastguard Worker
test_bit_le(u32 nr,const u8 * addr)309*59bfda1fSAndroid Build Coastguard Worker int test_bit_le(u32 nr, const u8 *addr)
310*59bfda1fSAndroid Build Coastguard Worker {
311*59bfda1fSAndroid Build Coastguard Worker return ((1 << (nr & 7)) & (addr[nr >> 3]));
312*59bfda1fSAndroid Build Coastguard Worker }
313*59bfda1fSAndroid Build Coastguard Worker
f2fs_test_bit(unsigned int nr,const char * p)314*59bfda1fSAndroid Build Coastguard Worker int f2fs_test_bit(unsigned int nr, const char *p)
315*59bfda1fSAndroid Build Coastguard Worker {
316*59bfda1fSAndroid Build Coastguard Worker int mask;
317*59bfda1fSAndroid Build Coastguard Worker char *addr = (char *)p;
318*59bfda1fSAndroid Build Coastguard Worker
319*59bfda1fSAndroid Build Coastguard Worker addr += (nr >> 3);
320*59bfda1fSAndroid Build Coastguard Worker mask = 1 << (7 - (nr & 0x07));
321*59bfda1fSAndroid Build Coastguard Worker return (mask & *addr) != 0;
322*59bfda1fSAndroid Build Coastguard Worker }
323*59bfda1fSAndroid Build Coastguard Worker
f2fs_set_bit(unsigned int nr,char * addr)324*59bfda1fSAndroid Build Coastguard Worker int f2fs_set_bit(unsigned int nr, char *addr)
325*59bfda1fSAndroid Build Coastguard Worker {
326*59bfda1fSAndroid Build Coastguard Worker int mask;
327*59bfda1fSAndroid Build Coastguard Worker int ret;
328*59bfda1fSAndroid Build Coastguard Worker
329*59bfda1fSAndroid Build Coastguard Worker addr += (nr >> 3);
330*59bfda1fSAndroid Build Coastguard Worker mask = 1 << (7 - (nr & 0x07));
331*59bfda1fSAndroid Build Coastguard Worker ret = mask & *addr;
332*59bfda1fSAndroid Build Coastguard Worker *addr |= mask;
333*59bfda1fSAndroid Build Coastguard Worker return ret;
334*59bfda1fSAndroid Build Coastguard Worker }
335*59bfda1fSAndroid Build Coastguard Worker
f2fs_clear_bit(unsigned int nr,char * addr)336*59bfda1fSAndroid Build Coastguard Worker int f2fs_clear_bit(unsigned int nr, char *addr)
337*59bfda1fSAndroid Build Coastguard Worker {
338*59bfda1fSAndroid Build Coastguard Worker int mask;
339*59bfda1fSAndroid Build Coastguard Worker int ret;
340*59bfda1fSAndroid Build Coastguard Worker
341*59bfda1fSAndroid Build Coastguard Worker addr += (nr >> 3);
342*59bfda1fSAndroid Build Coastguard Worker mask = 1 << (7 - (nr & 0x07));
343*59bfda1fSAndroid Build Coastguard Worker ret = mask & *addr;
344*59bfda1fSAndroid Build Coastguard Worker *addr &= ~mask;
345*59bfda1fSAndroid Build Coastguard Worker return ret;
346*59bfda1fSAndroid Build Coastguard Worker }
347*59bfda1fSAndroid Build Coastguard Worker
__ffs(u8 word)348*59bfda1fSAndroid Build Coastguard Worker static inline u64 __ffs(u8 word)
349*59bfda1fSAndroid Build Coastguard Worker {
350*59bfda1fSAndroid Build Coastguard Worker int num = 0;
351*59bfda1fSAndroid Build Coastguard Worker
352*59bfda1fSAndroid Build Coastguard Worker if ((word & 0xf) == 0) {
353*59bfda1fSAndroid Build Coastguard Worker num += 4;
354*59bfda1fSAndroid Build Coastguard Worker word >>= 4;
355*59bfda1fSAndroid Build Coastguard Worker }
356*59bfda1fSAndroid Build Coastguard Worker if ((word & 0x3) == 0) {
357*59bfda1fSAndroid Build Coastguard Worker num += 2;
358*59bfda1fSAndroid Build Coastguard Worker word >>= 2;
359*59bfda1fSAndroid Build Coastguard Worker }
360*59bfda1fSAndroid Build Coastguard Worker if ((word & 0x1) == 0)
361*59bfda1fSAndroid Build Coastguard Worker num += 1;
362*59bfda1fSAndroid Build Coastguard Worker return num;
363*59bfda1fSAndroid Build Coastguard Worker }
364*59bfda1fSAndroid Build Coastguard Worker
365*59bfda1fSAndroid Build Coastguard Worker /* Copied from linux/lib/find_bit.c */
366*59bfda1fSAndroid Build Coastguard Worker #define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1)))
367*59bfda1fSAndroid Build Coastguard Worker
_find_next_bit_le(const u8 * addr,u64 nbits,u64 start,char invert)368*59bfda1fSAndroid Build Coastguard Worker static u64 _find_next_bit_le(const u8 *addr, u64 nbits, u64 start, char invert)
369*59bfda1fSAndroid Build Coastguard Worker {
370*59bfda1fSAndroid Build Coastguard Worker u8 tmp;
371*59bfda1fSAndroid Build Coastguard Worker
372*59bfda1fSAndroid Build Coastguard Worker if (!nbits || start >= nbits)
373*59bfda1fSAndroid Build Coastguard Worker return nbits;
374*59bfda1fSAndroid Build Coastguard Worker
375*59bfda1fSAndroid Build Coastguard Worker tmp = addr[start / BITS_PER_BYTE] ^ invert;
376*59bfda1fSAndroid Build Coastguard Worker
377*59bfda1fSAndroid Build Coastguard Worker /* Handle 1st word. */
378*59bfda1fSAndroid Build Coastguard Worker tmp &= BITMAP_FIRST_BYTE_MASK(start);
379*59bfda1fSAndroid Build Coastguard Worker start = round_down(start, BITS_PER_BYTE);
380*59bfda1fSAndroid Build Coastguard Worker
381*59bfda1fSAndroid Build Coastguard Worker while (!tmp) {
382*59bfda1fSAndroid Build Coastguard Worker start += BITS_PER_BYTE;
383*59bfda1fSAndroid Build Coastguard Worker if (start >= nbits)
384*59bfda1fSAndroid Build Coastguard Worker return nbits;
385*59bfda1fSAndroid Build Coastguard Worker
386*59bfda1fSAndroid Build Coastguard Worker tmp = addr[start / BITS_PER_BYTE] ^ invert;
387*59bfda1fSAndroid Build Coastguard Worker }
388*59bfda1fSAndroid Build Coastguard Worker
389*59bfda1fSAndroid Build Coastguard Worker return min(start + __ffs(tmp), nbits);
390*59bfda1fSAndroid Build Coastguard Worker }
391*59bfda1fSAndroid Build Coastguard Worker
find_next_bit_le(const u8 * addr,u64 size,u64 offset)392*59bfda1fSAndroid Build Coastguard Worker u64 find_next_bit_le(const u8 *addr, u64 size, u64 offset)
393*59bfda1fSAndroid Build Coastguard Worker {
394*59bfda1fSAndroid Build Coastguard Worker return _find_next_bit_le(addr, size, offset, 0);
395*59bfda1fSAndroid Build Coastguard Worker }
396*59bfda1fSAndroid Build Coastguard Worker
397*59bfda1fSAndroid Build Coastguard Worker
find_next_zero_bit_le(const u8 * addr,u64 size,u64 offset)398*59bfda1fSAndroid Build Coastguard Worker u64 find_next_zero_bit_le(const u8 *addr, u64 size, u64 offset)
399*59bfda1fSAndroid Build Coastguard Worker {
400*59bfda1fSAndroid Build Coastguard Worker return _find_next_bit_le(addr, size, offset, 0xff);
401*59bfda1fSAndroid Build Coastguard Worker }
402*59bfda1fSAndroid Build Coastguard Worker
403*59bfda1fSAndroid Build Coastguard Worker /*
404*59bfda1fSAndroid Build Coastguard Worker * Hashing code adapted from ext3
405*59bfda1fSAndroid Build Coastguard Worker */
406*59bfda1fSAndroid Build Coastguard Worker #define DELTA 0x9E3779B9
407*59bfda1fSAndroid Build Coastguard Worker
TEA_transform(unsigned int buf[4],unsigned int const in[])408*59bfda1fSAndroid Build Coastguard Worker static void TEA_transform(unsigned int buf[4], unsigned int const in[])
409*59bfda1fSAndroid Build Coastguard Worker {
410*59bfda1fSAndroid Build Coastguard Worker __u32 sum = 0;
411*59bfda1fSAndroid Build Coastguard Worker __u32 b0 = buf[0], b1 = buf[1];
412*59bfda1fSAndroid Build Coastguard Worker __u32 a = in[0], b = in[1], c = in[2], d = in[3];
413*59bfda1fSAndroid Build Coastguard Worker int n = 16;
414*59bfda1fSAndroid Build Coastguard Worker
415*59bfda1fSAndroid Build Coastguard Worker do {
416*59bfda1fSAndroid Build Coastguard Worker sum += DELTA;
417*59bfda1fSAndroid Build Coastguard Worker b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
418*59bfda1fSAndroid Build Coastguard Worker b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
419*59bfda1fSAndroid Build Coastguard Worker } while (--n);
420*59bfda1fSAndroid Build Coastguard Worker
421*59bfda1fSAndroid Build Coastguard Worker buf[0] += b0;
422*59bfda1fSAndroid Build Coastguard Worker buf[1] += b1;
423*59bfda1fSAndroid Build Coastguard Worker
424*59bfda1fSAndroid Build Coastguard Worker }
425*59bfda1fSAndroid Build Coastguard Worker
str2hashbuf(const unsigned char * msg,int len,unsigned int * buf,int num)426*59bfda1fSAndroid Build Coastguard Worker static void str2hashbuf(const unsigned char *msg, int len,
427*59bfda1fSAndroid Build Coastguard Worker unsigned int *buf, int num)
428*59bfda1fSAndroid Build Coastguard Worker {
429*59bfda1fSAndroid Build Coastguard Worker unsigned pad, val;
430*59bfda1fSAndroid Build Coastguard Worker int i;
431*59bfda1fSAndroid Build Coastguard Worker
432*59bfda1fSAndroid Build Coastguard Worker pad = (__u32)len | ((__u32)len << 8);
433*59bfda1fSAndroid Build Coastguard Worker pad |= pad << 16;
434*59bfda1fSAndroid Build Coastguard Worker
435*59bfda1fSAndroid Build Coastguard Worker val = pad;
436*59bfda1fSAndroid Build Coastguard Worker if (len > num * 4)
437*59bfda1fSAndroid Build Coastguard Worker len = num * 4;
438*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < len; i++) {
439*59bfda1fSAndroid Build Coastguard Worker if ((i % 4) == 0)
440*59bfda1fSAndroid Build Coastguard Worker val = pad;
441*59bfda1fSAndroid Build Coastguard Worker val = msg[i] + (val << 8);
442*59bfda1fSAndroid Build Coastguard Worker if ((i % 4) == 3) {
443*59bfda1fSAndroid Build Coastguard Worker *buf++ = val;
444*59bfda1fSAndroid Build Coastguard Worker val = pad;
445*59bfda1fSAndroid Build Coastguard Worker num--;
446*59bfda1fSAndroid Build Coastguard Worker }
447*59bfda1fSAndroid Build Coastguard Worker }
448*59bfda1fSAndroid Build Coastguard Worker if (--num >= 0)
449*59bfda1fSAndroid Build Coastguard Worker *buf++ = val;
450*59bfda1fSAndroid Build Coastguard Worker while (--num >= 0)
451*59bfda1fSAndroid Build Coastguard Worker *buf++ = pad;
452*59bfda1fSAndroid Build Coastguard Worker
453*59bfda1fSAndroid Build Coastguard Worker }
454*59bfda1fSAndroid Build Coastguard Worker
455*59bfda1fSAndroid Build Coastguard Worker /**
456*59bfda1fSAndroid Build Coastguard Worker * Return hash value of directory entry
457*59bfda1fSAndroid Build Coastguard Worker * @param name dentry name
458*59bfda1fSAndroid Build Coastguard Worker * @param len name lenth
459*59bfda1fSAndroid Build Coastguard Worker * @return return on success hash value, errno on failure
460*59bfda1fSAndroid Build Coastguard Worker */
__f2fs_dentry_hash(const unsigned char * name,int len)461*59bfda1fSAndroid Build Coastguard Worker static f2fs_hash_t __f2fs_dentry_hash(const unsigned char *name, int len)/* Need update */
462*59bfda1fSAndroid Build Coastguard Worker {
463*59bfda1fSAndroid Build Coastguard Worker __u32 hash;
464*59bfda1fSAndroid Build Coastguard Worker f2fs_hash_t f2fs_hash;
465*59bfda1fSAndroid Build Coastguard Worker const unsigned char *p;
466*59bfda1fSAndroid Build Coastguard Worker __u32 in[8], buf[4];
467*59bfda1fSAndroid Build Coastguard Worker
468*59bfda1fSAndroid Build Coastguard Worker /* special hash codes for special dentries */
469*59bfda1fSAndroid Build Coastguard Worker if ((len <= 2) && (name[0] == '.') &&
470*59bfda1fSAndroid Build Coastguard Worker (name[1] == '.' || name[1] == '\0'))
471*59bfda1fSAndroid Build Coastguard Worker return 0;
472*59bfda1fSAndroid Build Coastguard Worker
473*59bfda1fSAndroid Build Coastguard Worker /* Initialize the default seed for the hash checksum functions */
474*59bfda1fSAndroid Build Coastguard Worker buf[0] = 0x67452301;
475*59bfda1fSAndroid Build Coastguard Worker buf[1] = 0xefcdab89;
476*59bfda1fSAndroid Build Coastguard Worker buf[2] = 0x98badcfe;
477*59bfda1fSAndroid Build Coastguard Worker buf[3] = 0x10325476;
478*59bfda1fSAndroid Build Coastguard Worker
479*59bfda1fSAndroid Build Coastguard Worker p = name;
480*59bfda1fSAndroid Build Coastguard Worker while (1) {
481*59bfda1fSAndroid Build Coastguard Worker str2hashbuf(p, len, in, 4);
482*59bfda1fSAndroid Build Coastguard Worker TEA_transform(buf, in);
483*59bfda1fSAndroid Build Coastguard Worker p += 16;
484*59bfda1fSAndroid Build Coastguard Worker if (len <= 16)
485*59bfda1fSAndroid Build Coastguard Worker break;
486*59bfda1fSAndroid Build Coastguard Worker len -= 16;
487*59bfda1fSAndroid Build Coastguard Worker }
488*59bfda1fSAndroid Build Coastguard Worker hash = buf[0];
489*59bfda1fSAndroid Build Coastguard Worker
490*59bfda1fSAndroid Build Coastguard Worker f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
491*59bfda1fSAndroid Build Coastguard Worker return f2fs_hash;
492*59bfda1fSAndroid Build Coastguard Worker }
493*59bfda1fSAndroid Build Coastguard Worker
f2fs_dentry_hash(int encoding,int casefolded,const unsigned char * name,int len)494*59bfda1fSAndroid Build Coastguard Worker f2fs_hash_t f2fs_dentry_hash(int encoding, int casefolded,
495*59bfda1fSAndroid Build Coastguard Worker const unsigned char *name, int len)
496*59bfda1fSAndroid Build Coastguard Worker {
497*59bfda1fSAndroid Build Coastguard Worker const struct f2fs_nls_table *table = f2fs_load_nls_table(encoding);
498*59bfda1fSAndroid Build Coastguard Worker int r, dlen;
499*59bfda1fSAndroid Build Coastguard Worker unsigned char *buff;
500*59bfda1fSAndroid Build Coastguard Worker
501*59bfda1fSAndroid Build Coastguard Worker if (len && casefolded) {
502*59bfda1fSAndroid Build Coastguard Worker buff = malloc(sizeof(char) * PATH_MAX);
503*59bfda1fSAndroid Build Coastguard Worker ASSERT(buff);
504*59bfda1fSAndroid Build Coastguard Worker
505*59bfda1fSAndroid Build Coastguard Worker dlen = table->ops->casefold(table, name, len, buff, PATH_MAX);
506*59bfda1fSAndroid Build Coastguard Worker if (dlen < 0) {
507*59bfda1fSAndroid Build Coastguard Worker free(buff);
508*59bfda1fSAndroid Build Coastguard Worker goto opaque_seq;
509*59bfda1fSAndroid Build Coastguard Worker }
510*59bfda1fSAndroid Build Coastguard Worker r = __f2fs_dentry_hash(buff, dlen);
511*59bfda1fSAndroid Build Coastguard Worker
512*59bfda1fSAndroid Build Coastguard Worker free(buff);
513*59bfda1fSAndroid Build Coastguard Worker return r;
514*59bfda1fSAndroid Build Coastguard Worker }
515*59bfda1fSAndroid Build Coastguard Worker opaque_seq:
516*59bfda1fSAndroid Build Coastguard Worker return __f2fs_dentry_hash(name, len);
517*59bfda1fSAndroid Build Coastguard Worker }
518*59bfda1fSAndroid Build Coastguard Worker
addrs_per_page(struct f2fs_inode * i,bool is_inode)519*59bfda1fSAndroid Build Coastguard Worker unsigned int addrs_per_page(struct f2fs_inode *i, bool is_inode)
520*59bfda1fSAndroid Build Coastguard Worker {
521*59bfda1fSAndroid Build Coastguard Worker unsigned int addrs = is_inode ? CUR_ADDRS_PER_INODE(i) -
522*59bfda1fSAndroid Build Coastguard Worker get_inline_xattr_addrs(i) : DEF_ADDRS_PER_BLOCK;
523*59bfda1fSAndroid Build Coastguard Worker
524*59bfda1fSAndroid Build Coastguard Worker if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
525*59bfda1fSAndroid Build Coastguard Worker !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
526*59bfda1fSAndroid Build Coastguard Worker return addrs;
527*59bfda1fSAndroid Build Coastguard Worker return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
528*59bfda1fSAndroid Build Coastguard Worker }
529*59bfda1fSAndroid Build Coastguard Worker
f2fs_max_file_offset(struct f2fs_inode * i)530*59bfda1fSAndroid Build Coastguard Worker unsigned int f2fs_max_file_offset(struct f2fs_inode *i)
531*59bfda1fSAndroid Build Coastguard Worker {
532*59bfda1fSAndroid Build Coastguard Worker if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
533*59bfda1fSAndroid Build Coastguard Worker !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
534*59bfda1fSAndroid Build Coastguard Worker return le64_to_cpu(i->i_size);
535*59bfda1fSAndroid Build Coastguard Worker return ALIGN_UP(le64_to_cpu(i->i_size), 1 << i->i_log_cluster_size);
536*59bfda1fSAndroid Build Coastguard Worker }
537*59bfda1fSAndroid Build Coastguard Worker
538*59bfda1fSAndroid Build Coastguard Worker /*
539*59bfda1fSAndroid Build Coastguard Worker * CRC32
540*59bfda1fSAndroid Build Coastguard Worker */
541*59bfda1fSAndroid Build Coastguard Worker #define CRCPOLY_LE 0xedb88320
542*59bfda1fSAndroid Build Coastguard Worker
f2fs_cal_crc32(uint32_t crc,void * buf,int len)543*59bfda1fSAndroid Build Coastguard Worker uint32_t f2fs_cal_crc32(uint32_t crc, void *buf, int len)
544*59bfda1fSAndroid Build Coastguard Worker {
545*59bfda1fSAndroid Build Coastguard Worker int i;
546*59bfda1fSAndroid Build Coastguard Worker unsigned char *p = (unsigned char *)buf;
547*59bfda1fSAndroid Build Coastguard Worker while (len--) {
548*59bfda1fSAndroid Build Coastguard Worker crc ^= *p++;
549*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
550*59bfda1fSAndroid Build Coastguard Worker crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
551*59bfda1fSAndroid Build Coastguard Worker }
552*59bfda1fSAndroid Build Coastguard Worker return crc;
553*59bfda1fSAndroid Build Coastguard Worker }
554*59bfda1fSAndroid Build Coastguard Worker
f2fs_crc_valid(uint32_t blk_crc,void * buf,int len)555*59bfda1fSAndroid Build Coastguard Worker int f2fs_crc_valid(uint32_t blk_crc, void *buf, int len)
556*59bfda1fSAndroid Build Coastguard Worker {
557*59bfda1fSAndroid Build Coastguard Worker uint32_t cal_crc = 0;
558*59bfda1fSAndroid Build Coastguard Worker
559*59bfda1fSAndroid Build Coastguard Worker cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
560*59bfda1fSAndroid Build Coastguard Worker
561*59bfda1fSAndroid Build Coastguard Worker if (cal_crc != blk_crc) {
562*59bfda1fSAndroid Build Coastguard Worker DBG(0,"CRC validation failed: cal_crc = %u, "
563*59bfda1fSAndroid Build Coastguard Worker "blk_crc = %u buff_size = 0x%x\n",
564*59bfda1fSAndroid Build Coastguard Worker cal_crc, blk_crc, len);
565*59bfda1fSAndroid Build Coastguard Worker return -1;
566*59bfda1fSAndroid Build Coastguard Worker }
567*59bfda1fSAndroid Build Coastguard Worker return 0;
568*59bfda1fSAndroid Build Coastguard Worker }
569*59bfda1fSAndroid Build Coastguard Worker
f2fs_inode_chksum(struct f2fs_node * node)570*59bfda1fSAndroid Build Coastguard Worker __u32 f2fs_inode_chksum(struct f2fs_node *node)
571*59bfda1fSAndroid Build Coastguard Worker {
572*59bfda1fSAndroid Build Coastguard Worker struct f2fs_inode *ri = &node->i;
573*59bfda1fSAndroid Build Coastguard Worker __le32 ino = F2FS_NODE_FOOTER(node)->ino;
574*59bfda1fSAndroid Build Coastguard Worker __le32 gen = ri->i_generation;
575*59bfda1fSAndroid Build Coastguard Worker __u32 chksum, chksum_seed;
576*59bfda1fSAndroid Build Coastguard Worker __u32 dummy_cs = 0;
577*59bfda1fSAndroid Build Coastguard Worker unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
578*59bfda1fSAndroid Build Coastguard Worker unsigned int cs_size = sizeof(dummy_cs);
579*59bfda1fSAndroid Build Coastguard Worker
580*59bfda1fSAndroid Build Coastguard Worker chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino,
581*59bfda1fSAndroid Build Coastguard Worker sizeof(ino));
582*59bfda1fSAndroid Build Coastguard Worker chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen));
583*59bfda1fSAndroid Build Coastguard Worker
584*59bfda1fSAndroid Build Coastguard Worker chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset);
585*59bfda1fSAndroid Build Coastguard Worker chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size);
586*59bfda1fSAndroid Build Coastguard Worker offset += cs_size;
587*59bfda1fSAndroid Build Coastguard Worker chksum = f2fs_cal_crc32(chksum, (__u8 *)ri + offset,
588*59bfda1fSAndroid Build Coastguard Worker F2FS_BLKSIZE - offset);
589*59bfda1fSAndroid Build Coastguard Worker return chksum;
590*59bfda1fSAndroid Build Coastguard Worker }
591*59bfda1fSAndroid Build Coastguard Worker
f2fs_checkpoint_chksum(struct f2fs_checkpoint * cp)592*59bfda1fSAndroid Build Coastguard Worker __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *cp)
593*59bfda1fSAndroid Build Coastguard Worker {
594*59bfda1fSAndroid Build Coastguard Worker unsigned int chksum_ofs = le32_to_cpu(cp->checksum_offset);
595*59bfda1fSAndroid Build Coastguard Worker __u32 chksum;
596*59bfda1fSAndroid Build Coastguard Worker
597*59bfda1fSAndroid Build Coastguard Worker chksum = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, chksum_ofs);
598*59bfda1fSAndroid Build Coastguard Worker if (chksum_ofs < CP_CHKSUM_OFFSET) {
599*59bfda1fSAndroid Build Coastguard Worker chksum_ofs += sizeof(chksum);
600*59bfda1fSAndroid Build Coastguard Worker chksum = f2fs_cal_crc32(chksum, (__u8 *)cp + chksum_ofs,
601*59bfda1fSAndroid Build Coastguard Worker F2FS_BLKSIZE - chksum_ofs);
602*59bfda1fSAndroid Build Coastguard Worker }
603*59bfda1fSAndroid Build Coastguard Worker return chksum;
604*59bfda1fSAndroid Build Coastguard Worker }
605*59bfda1fSAndroid Build Coastguard Worker
write_inode(struct f2fs_node * inode,u64 blkaddr,enum rw_hint whint)606*59bfda1fSAndroid Build Coastguard Worker int write_inode(struct f2fs_node *inode, u64 blkaddr, enum rw_hint whint)
607*59bfda1fSAndroid Build Coastguard Worker {
608*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_INODE_CHKSUM)
609*59bfda1fSAndroid Build Coastguard Worker inode->i.i_inode_checksum =
610*59bfda1fSAndroid Build Coastguard Worker cpu_to_le32(f2fs_inode_chksum(inode));
611*59bfda1fSAndroid Build Coastguard Worker return dev_write_block(inode, blkaddr, whint);
612*59bfda1fSAndroid Build Coastguard Worker }
613*59bfda1fSAndroid Build Coastguard Worker
614*59bfda1fSAndroid Build Coastguard Worker /*
615*59bfda1fSAndroid Build Coastguard Worker * try to identify the root device
616*59bfda1fSAndroid Build Coastguard Worker */
get_rootdev()617*59bfda1fSAndroid Build Coastguard Worker char *get_rootdev()
618*59bfda1fSAndroid Build Coastguard Worker {
619*59bfda1fSAndroid Build Coastguard Worker #if defined(_WIN32) || defined(WITH_ANDROID)
620*59bfda1fSAndroid Build Coastguard Worker return NULL;
621*59bfda1fSAndroid Build Coastguard Worker #else
622*59bfda1fSAndroid Build Coastguard Worker struct stat sb;
623*59bfda1fSAndroid Build Coastguard Worker int fd, ret;
624*59bfda1fSAndroid Build Coastguard Worker char buf[PATH_MAX + 1];
625*59bfda1fSAndroid Build Coastguard Worker char *uevent, *ptr;
626*59bfda1fSAndroid Build Coastguard Worker char *rootdev;
627*59bfda1fSAndroid Build Coastguard Worker
628*59bfda1fSAndroid Build Coastguard Worker if (stat("/", &sb) == -1)
629*59bfda1fSAndroid Build Coastguard Worker return NULL;
630*59bfda1fSAndroid Build Coastguard Worker
631*59bfda1fSAndroid Build Coastguard Worker snprintf(buf, PATH_MAX, "/sys/dev/block/%u:%u/uevent",
632*59bfda1fSAndroid Build Coastguard Worker major(sb.st_dev), minor(sb.st_dev));
633*59bfda1fSAndroid Build Coastguard Worker
634*59bfda1fSAndroid Build Coastguard Worker fd = open(buf, O_RDONLY);
635*59bfda1fSAndroid Build Coastguard Worker
636*59bfda1fSAndroid Build Coastguard Worker if (fd < 0)
637*59bfda1fSAndroid Build Coastguard Worker return NULL;
638*59bfda1fSAndroid Build Coastguard Worker
639*59bfda1fSAndroid Build Coastguard Worker ret = lseek(fd, (off_t)0, SEEK_END);
640*59bfda1fSAndroid Build Coastguard Worker (void)lseek(fd, (off_t)0, SEEK_SET);
641*59bfda1fSAndroid Build Coastguard Worker
642*59bfda1fSAndroid Build Coastguard Worker if (ret == -1) {
643*59bfda1fSAndroid Build Coastguard Worker close(fd);
644*59bfda1fSAndroid Build Coastguard Worker return NULL;
645*59bfda1fSAndroid Build Coastguard Worker }
646*59bfda1fSAndroid Build Coastguard Worker
647*59bfda1fSAndroid Build Coastguard Worker uevent = malloc(ret + 1);
648*59bfda1fSAndroid Build Coastguard Worker ASSERT(uevent);
649*59bfda1fSAndroid Build Coastguard Worker
650*59bfda1fSAndroid Build Coastguard Worker uevent[ret] = '\0';
651*59bfda1fSAndroid Build Coastguard Worker
652*59bfda1fSAndroid Build Coastguard Worker ret = read(fd, uevent, ret);
653*59bfda1fSAndroid Build Coastguard Worker close(fd);
654*59bfda1fSAndroid Build Coastguard Worker
655*59bfda1fSAndroid Build Coastguard Worker ptr = strstr(uevent, "DEVNAME");
656*59bfda1fSAndroid Build Coastguard Worker if (!ptr)
657*59bfda1fSAndroid Build Coastguard Worker goto out_free;
658*59bfda1fSAndroid Build Coastguard Worker
659*59bfda1fSAndroid Build Coastguard Worker ret = sscanf(ptr, "DEVNAME=%s\n", buf);
660*59bfda1fSAndroid Build Coastguard Worker if (strlen(buf) == 0)
661*59bfda1fSAndroid Build Coastguard Worker goto out_free;
662*59bfda1fSAndroid Build Coastguard Worker
663*59bfda1fSAndroid Build Coastguard Worker ret = strlen(buf) + 5;
664*59bfda1fSAndroid Build Coastguard Worker rootdev = malloc(ret + 1);
665*59bfda1fSAndroid Build Coastguard Worker if (!rootdev)
666*59bfda1fSAndroid Build Coastguard Worker goto out_free;
667*59bfda1fSAndroid Build Coastguard Worker rootdev[ret] = '\0';
668*59bfda1fSAndroid Build Coastguard Worker
669*59bfda1fSAndroid Build Coastguard Worker snprintf(rootdev, ret + 1, "/dev/%s", buf);
670*59bfda1fSAndroid Build Coastguard Worker free(uevent);
671*59bfda1fSAndroid Build Coastguard Worker return rootdev;
672*59bfda1fSAndroid Build Coastguard Worker
673*59bfda1fSAndroid Build Coastguard Worker out_free:
674*59bfda1fSAndroid Build Coastguard Worker free(uevent);
675*59bfda1fSAndroid Build Coastguard Worker return NULL;
676*59bfda1fSAndroid Build Coastguard Worker #endif
677*59bfda1fSAndroid Build Coastguard Worker }
678*59bfda1fSAndroid Build Coastguard Worker
679*59bfda1fSAndroid Build Coastguard Worker /*
680*59bfda1fSAndroid Build Coastguard Worker * device information
681*59bfda1fSAndroid Build Coastguard Worker */
f2fs_init_configuration(void)682*59bfda1fSAndroid Build Coastguard Worker void f2fs_init_configuration(void)
683*59bfda1fSAndroid Build Coastguard Worker {
684*59bfda1fSAndroid Build Coastguard Worker int i;
685*59bfda1fSAndroid Build Coastguard Worker
686*59bfda1fSAndroid Build Coastguard Worker memset(&c, 0, sizeof(struct f2fs_configuration));
687*59bfda1fSAndroid Build Coastguard Worker c.ndevs = 1;
688*59bfda1fSAndroid Build Coastguard Worker c.blksize = 1 << DEFAULT_BLKSIZE_BITS;
689*59bfda1fSAndroid Build Coastguard Worker c.blksize_bits = DEFAULT_BLKSIZE_BITS;
690*59bfda1fSAndroid Build Coastguard Worker c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
691*59bfda1fSAndroid Build Coastguard Worker c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
692*59bfda1fSAndroid Build Coastguard Worker c.wanted_total_sectors = -1;
693*59bfda1fSAndroid Build Coastguard Worker c.wanted_sector_size = -1;
694*59bfda1fSAndroid Build Coastguard Worker #ifndef WITH_ANDROID
695*59bfda1fSAndroid Build Coastguard Worker c.preserve_limits = 1;
696*59bfda1fSAndroid Build Coastguard Worker c.no_kernel_check = 1;
697*59bfda1fSAndroid Build Coastguard Worker #else
698*59bfda1fSAndroid Build Coastguard Worker c.no_kernel_check = 0;
699*59bfda1fSAndroid Build Coastguard Worker #endif
700*59bfda1fSAndroid Build Coastguard Worker
701*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < MAX_DEVICES; i++) {
702*59bfda1fSAndroid Build Coastguard Worker c.devices[i].fd = -1;
703*59bfda1fSAndroid Build Coastguard Worker c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
704*59bfda1fSAndroid Build Coastguard Worker c.devices[i].end_blkaddr = -1;
705*59bfda1fSAndroid Build Coastguard Worker c.devices[i].zoned_model = F2FS_ZONED_NONE;
706*59bfda1fSAndroid Build Coastguard Worker }
707*59bfda1fSAndroid Build Coastguard Worker
708*59bfda1fSAndroid Build Coastguard Worker /* calculated by overprovision ratio */
709*59bfda1fSAndroid Build Coastguard Worker c.segs_per_sec = 1;
710*59bfda1fSAndroid Build Coastguard Worker c.secs_per_zone = 1;
711*59bfda1fSAndroid Build Coastguard Worker c.segs_per_zone = 1;
712*59bfda1fSAndroid Build Coastguard Worker c.vol_label = "";
713*59bfda1fSAndroid Build Coastguard Worker c.trim = 1;
714*59bfda1fSAndroid Build Coastguard Worker c.kd = -1;
715*59bfda1fSAndroid Build Coastguard Worker c.fixed_time = -1;
716*59bfda1fSAndroid Build Coastguard Worker c.s_encoding = 0;
717*59bfda1fSAndroid Build Coastguard Worker c.s_encoding_flags = 0;
718*59bfda1fSAndroid Build Coastguard Worker
719*59bfda1fSAndroid Build Coastguard Worker /* default root owner */
720*59bfda1fSAndroid Build Coastguard Worker c.root_uid = getuid();
721*59bfda1fSAndroid Build Coastguard Worker c.root_gid = getgid();
722*59bfda1fSAndroid Build Coastguard Worker }
723*59bfda1fSAndroid Build Coastguard Worker
f2fs_dev_is_writable(void)724*59bfda1fSAndroid Build Coastguard Worker int f2fs_dev_is_writable(void)
725*59bfda1fSAndroid Build Coastguard Worker {
726*59bfda1fSAndroid Build Coastguard Worker return !c.ro || c.force;
727*59bfda1fSAndroid Build Coastguard Worker }
728*59bfda1fSAndroid Build Coastguard Worker
729*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SETMNTENT
is_mounted(const char * mpt,const char * device)730*59bfda1fSAndroid Build Coastguard Worker static int is_mounted(const char *mpt, const char *device)
731*59bfda1fSAndroid Build Coastguard Worker {
732*59bfda1fSAndroid Build Coastguard Worker FILE *file = NULL;
733*59bfda1fSAndroid Build Coastguard Worker struct mntent *mnt = NULL;
734*59bfda1fSAndroid Build Coastguard Worker
735*59bfda1fSAndroid Build Coastguard Worker file = setmntent(mpt, "r");
736*59bfda1fSAndroid Build Coastguard Worker if (file == NULL)
737*59bfda1fSAndroid Build Coastguard Worker return 0;
738*59bfda1fSAndroid Build Coastguard Worker
739*59bfda1fSAndroid Build Coastguard Worker while ((mnt = getmntent(file)) != NULL) {
740*59bfda1fSAndroid Build Coastguard Worker if (!strcmp(device, mnt->mnt_fsname)) {
741*59bfda1fSAndroid Build Coastguard Worker #ifdef MNTOPT_RO
742*59bfda1fSAndroid Build Coastguard Worker if (hasmntopt(mnt, MNTOPT_RO))
743*59bfda1fSAndroid Build Coastguard Worker c.ro = 1;
744*59bfda1fSAndroid Build Coastguard Worker #endif
745*59bfda1fSAndroid Build Coastguard Worker break;
746*59bfda1fSAndroid Build Coastguard Worker }
747*59bfda1fSAndroid Build Coastguard Worker }
748*59bfda1fSAndroid Build Coastguard Worker endmntent(file);
749*59bfda1fSAndroid Build Coastguard Worker return mnt ? 1 : 0;
750*59bfda1fSAndroid Build Coastguard Worker }
751*59bfda1fSAndroid Build Coastguard Worker #endif
752*59bfda1fSAndroid Build Coastguard Worker
f2fs_dev_is_umounted(char * path)753*59bfda1fSAndroid Build Coastguard Worker int f2fs_dev_is_umounted(char *path)
754*59bfda1fSAndroid Build Coastguard Worker {
755*59bfda1fSAndroid Build Coastguard Worker #ifdef _WIN32
756*59bfda1fSAndroid Build Coastguard Worker return 0;
757*59bfda1fSAndroid Build Coastguard Worker #else
758*59bfda1fSAndroid Build Coastguard Worker struct stat st_buf;
759*59bfda1fSAndroid Build Coastguard Worker int is_rootdev = 0;
760*59bfda1fSAndroid Build Coastguard Worker int ret = 0;
761*59bfda1fSAndroid Build Coastguard Worker char *rootdev_name = get_rootdev();
762*59bfda1fSAndroid Build Coastguard Worker
763*59bfda1fSAndroid Build Coastguard Worker if (rootdev_name) {
764*59bfda1fSAndroid Build Coastguard Worker if (!strcmp(path, rootdev_name))
765*59bfda1fSAndroid Build Coastguard Worker is_rootdev = 1;
766*59bfda1fSAndroid Build Coastguard Worker free(rootdev_name);
767*59bfda1fSAndroid Build Coastguard Worker }
768*59bfda1fSAndroid Build Coastguard Worker
769*59bfda1fSAndroid Build Coastguard Worker /*
770*59bfda1fSAndroid Build Coastguard Worker * try with /proc/mounts fist to detect RDONLY.
771*59bfda1fSAndroid Build Coastguard Worker * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
772*59bfda1fSAndroid Build Coastguard Worker */
773*59bfda1fSAndroid Build Coastguard Worker #ifdef __linux__
774*59bfda1fSAndroid Build Coastguard Worker ret = is_mounted("/proc/mounts", path);
775*59bfda1fSAndroid Build Coastguard Worker if (ret) {
776*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: Mounted device!\n");
777*59bfda1fSAndroid Build Coastguard Worker return -1;
778*59bfda1fSAndroid Build Coastguard Worker }
779*59bfda1fSAndroid Build Coastguard Worker #endif
780*59bfda1fSAndroid Build Coastguard Worker #if defined(MOUNTED) || defined(_PATH_MOUNTED)
781*59bfda1fSAndroid Build Coastguard Worker #ifndef MOUNTED
782*59bfda1fSAndroid Build Coastguard Worker #define MOUNTED _PATH_MOUNTED
783*59bfda1fSAndroid Build Coastguard Worker #endif
784*59bfda1fSAndroid Build Coastguard Worker ret = is_mounted(MOUNTED, path);
785*59bfda1fSAndroid Build Coastguard Worker if (ret) {
786*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: Mounted device!\n");
787*59bfda1fSAndroid Build Coastguard Worker return -1;
788*59bfda1fSAndroid Build Coastguard Worker }
789*59bfda1fSAndroid Build Coastguard Worker #endif
790*59bfda1fSAndroid Build Coastguard Worker /*
791*59bfda1fSAndroid Build Coastguard Worker * If we are supposed to operate on the root device, then
792*59bfda1fSAndroid Build Coastguard Worker * also check the mounts for '/dev/root', which sometimes
793*59bfda1fSAndroid Build Coastguard Worker * functions as an alias for the root device.
794*59bfda1fSAndroid Build Coastguard Worker */
795*59bfda1fSAndroid Build Coastguard Worker if (is_rootdev) {
796*59bfda1fSAndroid Build Coastguard Worker #ifdef __linux__
797*59bfda1fSAndroid Build Coastguard Worker ret = is_mounted("/proc/mounts", "/dev/root");
798*59bfda1fSAndroid Build Coastguard Worker if (ret) {
799*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: Mounted device!\n");
800*59bfda1fSAndroid Build Coastguard Worker return -1;
801*59bfda1fSAndroid Build Coastguard Worker }
802*59bfda1fSAndroid Build Coastguard Worker #endif
803*59bfda1fSAndroid Build Coastguard Worker }
804*59bfda1fSAndroid Build Coastguard Worker
805*59bfda1fSAndroid Build Coastguard Worker /*
806*59bfda1fSAndroid Build Coastguard Worker * If f2fs is umounted with -l, the process can still use
807*59bfda1fSAndroid Build Coastguard Worker * the file system. In this case, we should not format.
808*59bfda1fSAndroid Build Coastguard Worker */
809*59bfda1fSAndroid Build Coastguard Worker if (stat(path, &st_buf)) {
810*59bfda1fSAndroid Build Coastguard Worker /* sparse file will be created after this. */
811*59bfda1fSAndroid Build Coastguard Worker if (c.sparse_mode)
812*59bfda1fSAndroid Build Coastguard Worker return 0;
813*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: stat failed errno:%d\n", errno);
814*59bfda1fSAndroid Build Coastguard Worker return -1;
815*59bfda1fSAndroid Build Coastguard Worker }
816*59bfda1fSAndroid Build Coastguard Worker
817*59bfda1fSAndroid Build Coastguard Worker if (S_ISBLK(st_buf.st_mode)) {
818*59bfda1fSAndroid Build Coastguard Worker int fd = open(path, O_RDONLY | O_EXCL);
819*59bfda1fSAndroid Build Coastguard Worker
820*59bfda1fSAndroid Build Coastguard Worker if (fd >= 0) {
821*59bfda1fSAndroid Build Coastguard Worker close(fd);
822*59bfda1fSAndroid Build Coastguard Worker } else if (errno == EBUSY) {
823*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: In use by the system!\n");
824*59bfda1fSAndroid Build Coastguard Worker return -EBUSY;
825*59bfda1fSAndroid Build Coastguard Worker }
826*59bfda1fSAndroid Build Coastguard Worker } else if (S_ISREG(st_buf.st_mode)) {
827*59bfda1fSAndroid Build Coastguard Worker /* check whether regular is backfile of loop device */
828*59bfda1fSAndroid Build Coastguard Worker #if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H)
829*59bfda1fSAndroid Build Coastguard Worker struct mntent *mnt;
830*59bfda1fSAndroid Build Coastguard Worker struct stat st_loop;
831*59bfda1fSAndroid Build Coastguard Worker FILE *f;
832*59bfda1fSAndroid Build Coastguard Worker
833*59bfda1fSAndroid Build Coastguard Worker f = setmntent("/proc/mounts", "r");
834*59bfda1fSAndroid Build Coastguard Worker
835*59bfda1fSAndroid Build Coastguard Worker while ((mnt = getmntent(f)) != NULL) {
836*59bfda1fSAndroid Build Coastguard Worker struct loop_info64 loopinfo = {0, };
837*59bfda1fSAndroid Build Coastguard Worker int loop_fd, err;
838*59bfda1fSAndroid Build Coastguard Worker
839*59bfda1fSAndroid Build Coastguard Worker if (mnt->mnt_fsname[0] != '/')
840*59bfda1fSAndroid Build Coastguard Worker continue;
841*59bfda1fSAndroid Build Coastguard Worker if (stat(mnt->mnt_fsname, &st_loop) != 0)
842*59bfda1fSAndroid Build Coastguard Worker continue;
843*59bfda1fSAndroid Build Coastguard Worker if (!S_ISBLK(st_loop.st_mode))
844*59bfda1fSAndroid Build Coastguard Worker continue;
845*59bfda1fSAndroid Build Coastguard Worker if (major(st_loop.st_rdev) != LOOP_MAJOR)
846*59bfda1fSAndroid Build Coastguard Worker continue;
847*59bfda1fSAndroid Build Coastguard Worker
848*59bfda1fSAndroid Build Coastguard Worker loop_fd = open(mnt->mnt_fsname, O_RDONLY);
849*59bfda1fSAndroid Build Coastguard Worker if (loop_fd < 0) {
850*59bfda1fSAndroid Build Coastguard Worker /* non-root users have no permission */
851*59bfda1fSAndroid Build Coastguard Worker if (errno == EPERM || errno == EACCES) {
852*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: open %s failed errno:%d - be careful to overwrite a mounted loopback file.\n",
853*59bfda1fSAndroid Build Coastguard Worker mnt->mnt_fsname, errno);
854*59bfda1fSAndroid Build Coastguard Worker return 0;
855*59bfda1fSAndroid Build Coastguard Worker }
856*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: open %s failed errno:%d\n",
857*59bfda1fSAndroid Build Coastguard Worker mnt->mnt_fsname, errno);
858*59bfda1fSAndroid Build Coastguard Worker return -errno;
859*59bfda1fSAndroid Build Coastguard Worker }
860*59bfda1fSAndroid Build Coastguard Worker
861*59bfda1fSAndroid Build Coastguard Worker err = ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo);
862*59bfda1fSAndroid Build Coastguard Worker close(loop_fd);
863*59bfda1fSAndroid Build Coastguard Worker if (err < 0) {
864*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: ioctl LOOP_GET_STATUS64 failed errno:%d!\n",
865*59bfda1fSAndroid Build Coastguard Worker errno);
866*59bfda1fSAndroid Build Coastguard Worker return -errno;
867*59bfda1fSAndroid Build Coastguard Worker }
868*59bfda1fSAndroid Build Coastguard Worker
869*59bfda1fSAndroid Build Coastguard Worker if (st_buf.st_dev == loopinfo.lo_device &&
870*59bfda1fSAndroid Build Coastguard Worker st_buf.st_ino == loopinfo.lo_inode) {
871*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: In use by loop device!\n");
872*59bfda1fSAndroid Build Coastguard Worker return -EBUSY;
873*59bfda1fSAndroid Build Coastguard Worker }
874*59bfda1fSAndroid Build Coastguard Worker }
875*59bfda1fSAndroid Build Coastguard Worker #endif
876*59bfda1fSAndroid Build Coastguard Worker }
877*59bfda1fSAndroid Build Coastguard Worker return ret;
878*59bfda1fSAndroid Build Coastguard Worker #endif
879*59bfda1fSAndroid Build Coastguard Worker }
880*59bfda1fSAndroid Build Coastguard Worker
f2fs_devs_are_umounted(void)881*59bfda1fSAndroid Build Coastguard Worker int f2fs_devs_are_umounted(void)
882*59bfda1fSAndroid Build Coastguard Worker {
883*59bfda1fSAndroid Build Coastguard Worker int ret, i;
884*59bfda1fSAndroid Build Coastguard Worker
885*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < c.ndevs; i++) {
886*59bfda1fSAndroid Build Coastguard Worker ret = f2fs_dev_is_umounted((char *)c.devices[i].path);
887*59bfda1fSAndroid Build Coastguard Worker if (ret)
888*59bfda1fSAndroid Build Coastguard Worker return ret;
889*59bfda1fSAndroid Build Coastguard Worker }
890*59bfda1fSAndroid Build Coastguard Worker return 0;
891*59bfda1fSAndroid Build Coastguard Worker }
892*59bfda1fSAndroid Build Coastguard Worker
get_kernel_version(__u8 * version)893*59bfda1fSAndroid Build Coastguard Worker void get_kernel_version(__u8 *version)
894*59bfda1fSAndroid Build Coastguard Worker {
895*59bfda1fSAndroid Build Coastguard Worker int i;
896*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < VERSION_NAME_LEN; i++) {
897*59bfda1fSAndroid Build Coastguard Worker if (version[i] == '\n')
898*59bfda1fSAndroid Build Coastguard Worker break;
899*59bfda1fSAndroid Build Coastguard Worker }
900*59bfda1fSAndroid Build Coastguard Worker memset(version + i, 0, VERSION_LEN + 1 - i);
901*59bfda1fSAndroid Build Coastguard Worker }
902*59bfda1fSAndroid Build Coastguard Worker
get_kernel_uname_version(__u8 * version)903*59bfda1fSAndroid Build Coastguard Worker void get_kernel_uname_version(__u8 *version)
904*59bfda1fSAndroid Build Coastguard Worker {
905*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_UTSNAME_H
906*59bfda1fSAndroid Build Coastguard Worker struct utsname buf;
907*59bfda1fSAndroid Build Coastguard Worker
908*59bfda1fSAndroid Build Coastguard Worker memset(version, 0, VERSION_LEN);
909*59bfda1fSAndroid Build Coastguard Worker if (uname(&buf))
910*59bfda1fSAndroid Build Coastguard Worker return;
911*59bfda1fSAndroid Build Coastguard Worker
912*59bfda1fSAndroid Build Coastguard Worker #if defined(WITH_KERNEL_VERSION)
913*59bfda1fSAndroid Build Coastguard Worker snprintf((char *)version,
914*59bfda1fSAndroid Build Coastguard Worker VERSION_NAME_LEN, "%s %s", buf.release, buf.version);
915*59bfda1fSAndroid Build Coastguard Worker #else
916*59bfda1fSAndroid Build Coastguard Worker snprintf((char *)version,
917*59bfda1fSAndroid Build Coastguard Worker VERSION_NAME_LEN, "%s", buf.release);
918*59bfda1fSAndroid Build Coastguard Worker #endif
919*59bfda1fSAndroid Build Coastguard Worker #else
920*59bfda1fSAndroid Build Coastguard Worker memset(version, 0, VERSION_LEN);
921*59bfda1fSAndroid Build Coastguard Worker #endif
922*59bfda1fSAndroid Build Coastguard Worker }
923*59bfda1fSAndroid Build Coastguard Worker
924*59bfda1fSAndroid Build Coastguard Worker #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
925*59bfda1fSAndroid Build Coastguard Worker #define BLKGETSIZE _IO(0x12,96)
926*59bfda1fSAndroid Build Coastguard Worker #endif
927*59bfda1fSAndroid Build Coastguard Worker
928*59bfda1fSAndroid Build Coastguard Worker #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
929*59bfda1fSAndroid Build Coastguard Worker #define BLKGETSIZE64 _IOR(0x12,114, size_t)
930*59bfda1fSAndroid Build Coastguard Worker #endif
931*59bfda1fSAndroid Build Coastguard Worker
932*59bfda1fSAndroid Build Coastguard Worker #if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
933*59bfda1fSAndroid Build Coastguard Worker #define BLKSSZGET _IO(0x12,104)
934*59bfda1fSAndroid Build Coastguard Worker #endif
935*59bfda1fSAndroid Build Coastguard Worker
936*59bfda1fSAndroid Build Coastguard Worker #if defined(__APPLE__)
937*59bfda1fSAndroid Build Coastguard Worker #include <sys/disk.h>
938*59bfda1fSAndroid Build Coastguard Worker #define BLKGETSIZE DKIOCGETBLOCKCOUNT
939*59bfda1fSAndroid Build Coastguard Worker #define BLKSSZGET DKIOCGETBLOCKCOUNT
940*59bfda1fSAndroid Build Coastguard Worker #endif /* APPLE_DARWIN */
941*59bfda1fSAndroid Build Coastguard Worker
942*59bfda1fSAndroid Build Coastguard Worker #ifndef _WIN32
open_check_fs(char * path,int flag)943*59bfda1fSAndroid Build Coastguard Worker static int open_check_fs(char *path, int flag)
944*59bfda1fSAndroid Build Coastguard Worker {
945*59bfda1fSAndroid Build Coastguard Worker if (c.func != DUMP && (c.func != FSCK || c.fix_on || c.auto_fix))
946*59bfda1fSAndroid Build Coastguard Worker return -1;
947*59bfda1fSAndroid Build Coastguard Worker
948*59bfda1fSAndroid Build Coastguard Worker /* allow to open ro */
949*59bfda1fSAndroid Build Coastguard Worker return open(path, O_RDONLY | flag);
950*59bfda1fSAndroid Build Coastguard Worker }
951*59bfda1fSAndroid Build Coastguard Worker
952*59bfda1fSAndroid Build Coastguard Worker #ifdef __linux__
is_power_of_2(unsigned long n)953*59bfda1fSAndroid Build Coastguard Worker static int is_power_of_2(unsigned long n)
954*59bfda1fSAndroid Build Coastguard Worker {
955*59bfda1fSAndroid Build Coastguard Worker return (n != 0 && ((n & (n - 1)) == 0));
956*59bfda1fSAndroid Build Coastguard Worker }
957*59bfda1fSAndroid Build Coastguard Worker #endif
958*59bfda1fSAndroid Build Coastguard Worker
get_device_info(int i)959*59bfda1fSAndroid Build Coastguard Worker int get_device_info(int i)
960*59bfda1fSAndroid Build Coastguard Worker {
961*59bfda1fSAndroid Build Coastguard Worker int32_t fd = 0;
962*59bfda1fSAndroid Build Coastguard Worker uint32_t sector_size;
963*59bfda1fSAndroid Build Coastguard Worker #ifndef BLKGETSIZE64
964*59bfda1fSAndroid Build Coastguard Worker uint32_t total_sectors;
965*59bfda1fSAndroid Build Coastguard Worker #endif
966*59bfda1fSAndroid Build Coastguard Worker struct stat *stat_buf;
967*59bfda1fSAndroid Build Coastguard Worker #ifdef HDIO_GETGIO
968*59bfda1fSAndroid Build Coastguard Worker struct hd_geometry geom;
969*59bfda1fSAndroid Build Coastguard Worker #endif
970*59bfda1fSAndroid Build Coastguard Worker #if !defined(WITH_ANDROID) && defined(__linux__)
971*59bfda1fSAndroid Build Coastguard Worker sg_io_hdr_t io_hdr;
972*59bfda1fSAndroid Build Coastguard Worker unsigned char reply_buffer[96] = {0};
973*59bfda1fSAndroid Build Coastguard Worker unsigned char model_inq[6] = {MODELINQUIRY};
974*59bfda1fSAndroid Build Coastguard Worker #endif
975*59bfda1fSAndroid Build Coastguard Worker struct device_info *dev = c.devices + i;
976*59bfda1fSAndroid Build Coastguard Worker int flags = O_RDWR;
977*59bfda1fSAndroid Build Coastguard Worker
978*59bfda1fSAndroid Build Coastguard Worker if (c.sparse_mode) {
979*59bfda1fSAndroid Build Coastguard Worker fd = open(dev->path, O_RDWR | O_CREAT | O_BINARY, 0644);
980*59bfda1fSAndroid Build Coastguard Worker if (fd < 0) {
981*59bfda1fSAndroid Build Coastguard Worker fd = open_check_fs(dev->path, O_BINARY);
982*59bfda1fSAndroid Build Coastguard Worker if (fd < 0) {
983*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to open a sparse file!\n");
984*59bfda1fSAndroid Build Coastguard Worker return -1;
985*59bfda1fSAndroid Build Coastguard Worker }
986*59bfda1fSAndroid Build Coastguard Worker }
987*59bfda1fSAndroid Build Coastguard Worker }
988*59bfda1fSAndroid Build Coastguard Worker
989*59bfda1fSAndroid Build Coastguard Worker stat_buf = calloc(1, sizeof(struct stat));
990*59bfda1fSAndroid Build Coastguard Worker ASSERT(stat_buf);
991*59bfda1fSAndroid Build Coastguard Worker
992*59bfda1fSAndroid Build Coastguard Worker if (stat(dev->path, stat_buf) < 0) {
993*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to get the device stat!\n");
994*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
995*59bfda1fSAndroid Build Coastguard Worker return -1;
996*59bfda1fSAndroid Build Coastguard Worker }
997*59bfda1fSAndroid Build Coastguard Worker
998*59bfda1fSAndroid Build Coastguard Worker #ifdef __linux__
999*59bfda1fSAndroid Build Coastguard Worker if (S_ISBLK(stat_buf->st_mode)) {
1000*59bfda1fSAndroid Build Coastguard Worker if (f2fs_get_zoned_model(i) < 0) {
1001*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1002*59bfda1fSAndroid Build Coastguard Worker return -1;
1003*59bfda1fSAndroid Build Coastguard Worker }
1004*59bfda1fSAndroid Build Coastguard Worker }
1005*59bfda1fSAndroid Build Coastguard Worker #endif
1006*59bfda1fSAndroid Build Coastguard Worker
1007*59bfda1fSAndroid Build Coastguard Worker if (!c.sparse_mode) {
1008*59bfda1fSAndroid Build Coastguard Worker if (dev->zoned_model == F2FS_ZONED_HM)
1009*59bfda1fSAndroid Build Coastguard Worker flags |= O_DSYNC;
1010*59bfda1fSAndroid Build Coastguard Worker
1011*59bfda1fSAndroid Build Coastguard Worker if (S_ISBLK(stat_buf->st_mode) &&
1012*59bfda1fSAndroid Build Coastguard Worker !c.force && c.func != DUMP && !c.dry_run) {
1013*59bfda1fSAndroid Build Coastguard Worker flags |= O_EXCL;
1014*59bfda1fSAndroid Build Coastguard Worker fd = open(dev->path, flags);
1015*59bfda1fSAndroid Build Coastguard Worker if (fd < 0)
1016*59bfda1fSAndroid Build Coastguard Worker fd = open_check_fs(dev->path, O_EXCL);
1017*59bfda1fSAndroid Build Coastguard Worker } else {
1018*59bfda1fSAndroid Build Coastguard Worker fd = open(dev->path, flags);
1019*59bfda1fSAndroid Build Coastguard Worker if (fd < 0)
1020*59bfda1fSAndroid Build Coastguard Worker fd = open_check_fs(dev->path, 0);
1021*59bfda1fSAndroid Build Coastguard Worker }
1022*59bfda1fSAndroid Build Coastguard Worker }
1023*59bfda1fSAndroid Build Coastguard Worker if (fd < 0) {
1024*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to open the device!\n");
1025*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1026*59bfda1fSAndroid Build Coastguard Worker return -1;
1027*59bfda1fSAndroid Build Coastguard Worker }
1028*59bfda1fSAndroid Build Coastguard Worker
1029*59bfda1fSAndroid Build Coastguard Worker dev->fd = fd;
1030*59bfda1fSAndroid Build Coastguard Worker
1031*59bfda1fSAndroid Build Coastguard Worker if (c.sparse_mode && i == 0) {
1032*59bfda1fSAndroid Build Coastguard Worker if (f2fs_init_sparse_file()) {
1033*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1034*59bfda1fSAndroid Build Coastguard Worker return -1;
1035*59bfda1fSAndroid Build Coastguard Worker }
1036*59bfda1fSAndroid Build Coastguard Worker }
1037*59bfda1fSAndroid Build Coastguard Worker
1038*59bfda1fSAndroid Build Coastguard Worker if (c.kd == -1) {
1039*59bfda1fSAndroid Build Coastguard Worker #if !defined(WITH_ANDROID) && defined(__linux__)
1040*59bfda1fSAndroid Build Coastguard Worker c.kd = open("/proc/version", O_RDONLY);
1041*59bfda1fSAndroid Build Coastguard Worker #endif
1042*59bfda1fSAndroid Build Coastguard Worker if (c.kd < 0) {
1043*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: not exist /proc/version!\n");
1044*59bfda1fSAndroid Build Coastguard Worker c.kd = -2;
1045*59bfda1fSAndroid Build Coastguard Worker }
1046*59bfda1fSAndroid Build Coastguard Worker }
1047*59bfda1fSAndroid Build Coastguard Worker
1048*59bfda1fSAndroid Build Coastguard Worker if (c.sparse_mode) {
1049*59bfda1fSAndroid Build Coastguard Worker dev->total_sectors = c.device_size / dev->sector_size;
1050*59bfda1fSAndroid Build Coastguard Worker } else if (S_ISREG(stat_buf->st_mode)) {
1051*59bfda1fSAndroid Build Coastguard Worker dev->total_sectors = stat_buf->st_size / dev->sector_size;
1052*59bfda1fSAndroid Build Coastguard Worker } else if (S_ISBLK(stat_buf->st_mode)) {
1053*59bfda1fSAndroid Build Coastguard Worker #ifdef BLKSSZGET
1054*59bfda1fSAndroid Build Coastguard Worker if (ioctl(fd, BLKSSZGET, §or_size) < 0)
1055*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Using the default sector size\n");
1056*59bfda1fSAndroid Build Coastguard Worker else if (dev->sector_size < sector_size)
1057*59bfda1fSAndroid Build Coastguard Worker dev->sector_size = sector_size;
1058*59bfda1fSAndroid Build Coastguard Worker #endif
1059*59bfda1fSAndroid Build Coastguard Worker #ifdef BLKGETSIZE64
1060*59bfda1fSAndroid Build Coastguard Worker if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
1061*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Cannot get the device size\n");
1062*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1063*59bfda1fSAndroid Build Coastguard Worker return -1;
1064*59bfda1fSAndroid Build Coastguard Worker }
1065*59bfda1fSAndroid Build Coastguard Worker #else
1066*59bfda1fSAndroid Build Coastguard Worker if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
1067*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Cannot get the device size\n");
1068*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1069*59bfda1fSAndroid Build Coastguard Worker return -1;
1070*59bfda1fSAndroid Build Coastguard Worker }
1071*59bfda1fSAndroid Build Coastguard Worker dev->total_sectors = total_sectors;
1072*59bfda1fSAndroid Build Coastguard Worker #endif
1073*59bfda1fSAndroid Build Coastguard Worker dev->total_sectors /= dev->sector_size;
1074*59bfda1fSAndroid Build Coastguard Worker
1075*59bfda1fSAndroid Build Coastguard Worker if (i == 0) {
1076*59bfda1fSAndroid Build Coastguard Worker #ifdef HDIO_GETGIO
1077*59bfda1fSAndroid Build Coastguard Worker if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
1078*59bfda1fSAndroid Build Coastguard Worker c.start_sector = 0;
1079*59bfda1fSAndroid Build Coastguard Worker else
1080*59bfda1fSAndroid Build Coastguard Worker c.start_sector = geom.start;
1081*59bfda1fSAndroid Build Coastguard Worker #else
1082*59bfda1fSAndroid Build Coastguard Worker c.start_sector = 0;
1083*59bfda1fSAndroid Build Coastguard Worker #endif
1084*59bfda1fSAndroid Build Coastguard Worker }
1085*59bfda1fSAndroid Build Coastguard Worker
1086*59bfda1fSAndroid Build Coastguard Worker #if !defined(WITH_ANDROID) && defined(__linux__)
1087*59bfda1fSAndroid Build Coastguard Worker /* Send INQUIRY command */
1088*59bfda1fSAndroid Build Coastguard Worker memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
1089*59bfda1fSAndroid Build Coastguard Worker io_hdr.interface_id = 'S';
1090*59bfda1fSAndroid Build Coastguard Worker io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
1091*59bfda1fSAndroid Build Coastguard Worker io_hdr.dxfer_len = sizeof(reply_buffer);
1092*59bfda1fSAndroid Build Coastguard Worker io_hdr.dxferp = reply_buffer;
1093*59bfda1fSAndroid Build Coastguard Worker io_hdr.cmd_len = sizeof(model_inq);
1094*59bfda1fSAndroid Build Coastguard Worker io_hdr.cmdp = model_inq;
1095*59bfda1fSAndroid Build Coastguard Worker io_hdr.timeout = 1000;
1096*59bfda1fSAndroid Build Coastguard Worker
1097*59bfda1fSAndroid Build Coastguard Worker if (!ioctl(fd, SG_IO, &io_hdr)) {
1098*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: [%s] Disk Model: %.16s\n",
1099*59bfda1fSAndroid Build Coastguard Worker dev->path, reply_buffer+16);
1100*59bfda1fSAndroid Build Coastguard Worker }
1101*59bfda1fSAndroid Build Coastguard Worker #endif
1102*59bfda1fSAndroid Build Coastguard Worker } else {
1103*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Volume type is not supported!!!\n");
1104*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1105*59bfda1fSAndroid Build Coastguard Worker return -1;
1106*59bfda1fSAndroid Build Coastguard Worker }
1107*59bfda1fSAndroid Build Coastguard Worker
1108*59bfda1fSAndroid Build Coastguard Worker if (!c.sector_size) {
1109*59bfda1fSAndroid Build Coastguard Worker c.sector_size = dev->sector_size;
1110*59bfda1fSAndroid Build Coastguard Worker c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1111*59bfda1fSAndroid Build Coastguard Worker } else if (c.sector_size != c.devices[i].sector_size) {
1112*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Different sector sizes!!!\n");
1113*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1114*59bfda1fSAndroid Build Coastguard Worker return -1;
1115*59bfda1fSAndroid Build Coastguard Worker }
1116*59bfda1fSAndroid Build Coastguard Worker
1117*59bfda1fSAndroid Build Coastguard Worker #ifdef __linux__
1118*59bfda1fSAndroid Build Coastguard Worker if (dev->zoned_model != F2FS_ZONED_NONE) {
1119*59bfda1fSAndroid Build Coastguard Worker
1120*59bfda1fSAndroid Build Coastguard Worker /* Get the number of blocks per zones */
1121*59bfda1fSAndroid Build Coastguard Worker if (f2fs_get_zone_blocks(i)) {
1122*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to get number of blocks per zone\n");
1123*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1124*59bfda1fSAndroid Build Coastguard Worker return -1;
1125*59bfda1fSAndroid Build Coastguard Worker }
1126*59bfda1fSAndroid Build Coastguard Worker
1127*59bfda1fSAndroid Build Coastguard Worker if (!is_power_of_2(dev->zone_size))
1128*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: zoned: zone size %" PRIu64 "u (not a power of 2)\n",
1129*59bfda1fSAndroid Build Coastguard Worker dev->zone_size);
1130*59bfda1fSAndroid Build Coastguard Worker
1131*59bfda1fSAndroid Build Coastguard Worker /*
1132*59bfda1fSAndroid Build Coastguard Worker * Check zone configuration: for the first disk of a
1133*59bfda1fSAndroid Build Coastguard Worker * multi-device volume, conventional zones are needed.
1134*59bfda1fSAndroid Build Coastguard Worker */
1135*59bfda1fSAndroid Build Coastguard Worker if (f2fs_check_zones(i)) {
1136*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to check zone configuration\n");
1137*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1138*59bfda1fSAndroid Build Coastguard Worker return -1;
1139*59bfda1fSAndroid Build Coastguard Worker }
1140*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: Host-%s zoned block device:\n",
1141*59bfda1fSAndroid Build Coastguard Worker (dev->zoned_model == F2FS_ZONED_HA) ?
1142*59bfda1fSAndroid Build Coastguard Worker "aware" : "managed");
1143*59bfda1fSAndroid Build Coastguard Worker MSG(0, " %u zones, %" PRIu64 "u zone size(bytes), %u randomly writeable zones\n",
1144*59bfda1fSAndroid Build Coastguard Worker dev->nr_zones, dev->zone_size,
1145*59bfda1fSAndroid Build Coastguard Worker dev->nr_rnd_zones);
1146*59bfda1fSAndroid Build Coastguard Worker MSG(0, " %zu blocks per zone\n",
1147*59bfda1fSAndroid Build Coastguard Worker dev->zone_blocks);
1148*59bfda1fSAndroid Build Coastguard Worker
1149*59bfda1fSAndroid Build Coastguard Worker if (c.conf_reserved_sections) {
1150*59bfda1fSAndroid Build Coastguard Worker if (c.conf_reserved_sections < MIN_RSVD_SECS) {
1151*59bfda1fSAndroid Build Coastguard Worker MSG(0, " Too small sections are reserved(%u secs)\n",
1152*59bfda1fSAndroid Build Coastguard Worker c.conf_reserved_sections);
1153*59bfda1fSAndroid Build Coastguard Worker c.conf_reserved_sections = MIN_RSVD_SECS;
1154*59bfda1fSAndroid Build Coastguard Worker MSG(0, " It is operated as a minimum reserved sections(%u secs)\n",
1155*59bfda1fSAndroid Build Coastguard Worker c.conf_reserved_sections);
1156*59bfda1fSAndroid Build Coastguard Worker } else {
1157*59bfda1fSAndroid Build Coastguard Worker MSG(0, " %u sections are reserved\n",
1158*59bfda1fSAndroid Build Coastguard Worker c.conf_reserved_sections);
1159*59bfda1fSAndroid Build Coastguard Worker }
1160*59bfda1fSAndroid Build Coastguard Worker if (!c.overprovision) {
1161*59bfda1fSAndroid Build Coastguard Worker c.overprovision = CONFIG_RSVD_DEFAULT_OP_RATIO;
1162*59bfda1fSAndroid Build Coastguard Worker MSG(0, " Overprovision ratio is set to default(%.1lf%%)\n",
1163*59bfda1fSAndroid Build Coastguard Worker c.overprovision);
1164*59bfda1fSAndroid Build Coastguard Worker }
1165*59bfda1fSAndroid Build Coastguard Worker }
1166*59bfda1fSAndroid Build Coastguard Worker }
1167*59bfda1fSAndroid Build Coastguard Worker #endif
1168*59bfda1fSAndroid Build Coastguard Worker
1169*59bfda1fSAndroid Build Coastguard Worker /* adjust wanted_total_sectors */
1170*59bfda1fSAndroid Build Coastguard Worker if (c.wanted_total_sectors != -1) {
1171*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n",
1172*59bfda1fSAndroid Build Coastguard Worker c.wanted_total_sectors, c.wanted_sector_size);
1173*59bfda1fSAndroid Build Coastguard Worker if (c.wanted_sector_size == -1) {
1174*59bfda1fSAndroid Build Coastguard Worker c.wanted_sector_size = dev->sector_size;
1175*59bfda1fSAndroid Build Coastguard Worker } else if (dev->sector_size != c.wanted_sector_size) {
1176*59bfda1fSAndroid Build Coastguard Worker c.wanted_total_sectors *= c.wanted_sector_size;
1177*59bfda1fSAndroid Build Coastguard Worker c.wanted_total_sectors /= dev->sector_size;
1178*59bfda1fSAndroid Build Coastguard Worker }
1179*59bfda1fSAndroid Build Coastguard Worker }
1180*59bfda1fSAndroid Build Coastguard Worker
1181*59bfda1fSAndroid Build Coastguard Worker c.total_sectors += dev->total_sectors;
1182*59bfda1fSAndroid Build Coastguard Worker free(stat_buf);
1183*59bfda1fSAndroid Build Coastguard Worker return 0;
1184*59bfda1fSAndroid Build Coastguard Worker }
1185*59bfda1fSAndroid Build Coastguard Worker
1186*59bfda1fSAndroid Build Coastguard Worker #else
1187*59bfda1fSAndroid Build Coastguard Worker
1188*59bfda1fSAndroid Build Coastguard Worker #include "windows.h"
1189*59bfda1fSAndroid Build Coastguard Worker #include "winioctl.h"
1190*59bfda1fSAndroid Build Coastguard Worker
1191*59bfda1fSAndroid Build Coastguard Worker #if (_WIN32_WINNT >= 0x0500)
1192*59bfda1fSAndroid Build Coastguard Worker #define HAVE_GET_FILE_SIZE_EX 1
1193*59bfda1fSAndroid Build Coastguard Worker #endif
1194*59bfda1fSAndroid Build Coastguard Worker
win_get_device_size(const char * file,uint64_t * device_size)1195*59bfda1fSAndroid Build Coastguard Worker static int win_get_device_size(const char *file, uint64_t *device_size)
1196*59bfda1fSAndroid Build Coastguard Worker {
1197*59bfda1fSAndroid Build Coastguard Worker HANDLE dev;
1198*59bfda1fSAndroid Build Coastguard Worker PARTITION_INFORMATION pi;
1199*59bfda1fSAndroid Build Coastguard Worker DISK_GEOMETRY gi;
1200*59bfda1fSAndroid Build Coastguard Worker DWORD retbytes;
1201*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_GET_FILE_SIZE_EX
1202*59bfda1fSAndroid Build Coastguard Worker LARGE_INTEGER filesize;
1203*59bfda1fSAndroid Build Coastguard Worker #else
1204*59bfda1fSAndroid Build Coastguard Worker DWORD filesize;
1205*59bfda1fSAndroid Build Coastguard Worker #endif /* HAVE_GET_FILE_SIZE_EX */
1206*59bfda1fSAndroid Build Coastguard Worker
1207*59bfda1fSAndroid Build Coastguard Worker dev = CreateFile(file, GENERIC_READ,
1208*59bfda1fSAndroid Build Coastguard Worker FILE_SHARE_READ | FILE_SHARE_WRITE ,
1209*59bfda1fSAndroid Build Coastguard Worker NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1210*59bfda1fSAndroid Build Coastguard Worker
1211*59bfda1fSAndroid Build Coastguard Worker if (dev == INVALID_HANDLE_VALUE)
1212*59bfda1fSAndroid Build Coastguard Worker return EBADF;
1213*59bfda1fSAndroid Build Coastguard Worker if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
1214*59bfda1fSAndroid Build Coastguard Worker &pi, sizeof(PARTITION_INFORMATION),
1215*59bfda1fSAndroid Build Coastguard Worker &pi, sizeof(PARTITION_INFORMATION),
1216*59bfda1fSAndroid Build Coastguard Worker &retbytes, NULL)) {
1217*59bfda1fSAndroid Build Coastguard Worker
1218*59bfda1fSAndroid Build Coastguard Worker *device_size = pi.PartitionLength.QuadPart;
1219*59bfda1fSAndroid Build Coastguard Worker
1220*59bfda1fSAndroid Build Coastguard Worker } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1221*59bfda1fSAndroid Build Coastguard Worker &gi, sizeof(DISK_GEOMETRY),
1222*59bfda1fSAndroid Build Coastguard Worker &gi, sizeof(DISK_GEOMETRY),
1223*59bfda1fSAndroid Build Coastguard Worker &retbytes, NULL)) {
1224*59bfda1fSAndroid Build Coastguard Worker
1225*59bfda1fSAndroid Build Coastguard Worker *device_size = gi.BytesPerSector *
1226*59bfda1fSAndroid Build Coastguard Worker gi.SectorsPerTrack *
1227*59bfda1fSAndroid Build Coastguard Worker gi.TracksPerCylinder *
1228*59bfda1fSAndroid Build Coastguard Worker gi.Cylinders.QuadPart;
1229*59bfda1fSAndroid Build Coastguard Worker
1230*59bfda1fSAndroid Build Coastguard Worker #ifdef HAVE_GET_FILE_SIZE_EX
1231*59bfda1fSAndroid Build Coastguard Worker } else if (GetFileSizeEx(dev, &filesize)) {
1232*59bfda1fSAndroid Build Coastguard Worker *device_size = filesize.QuadPart;
1233*59bfda1fSAndroid Build Coastguard Worker }
1234*59bfda1fSAndroid Build Coastguard Worker #else
1235*59bfda1fSAndroid Build Coastguard Worker } else {
1236*59bfda1fSAndroid Build Coastguard Worker filesize = GetFileSize(dev, NULL);
1237*59bfda1fSAndroid Build Coastguard Worker if (INVALID_FILE_SIZE != filesize)
1238*59bfda1fSAndroid Build Coastguard Worker return -1;
1239*59bfda1fSAndroid Build Coastguard Worker *device_size = filesize;
1240*59bfda1fSAndroid Build Coastguard Worker }
1241*59bfda1fSAndroid Build Coastguard Worker #endif /* HAVE_GET_FILE_SIZE_EX */
1242*59bfda1fSAndroid Build Coastguard Worker
1243*59bfda1fSAndroid Build Coastguard Worker CloseHandle(dev);
1244*59bfda1fSAndroid Build Coastguard Worker return 0;
1245*59bfda1fSAndroid Build Coastguard Worker }
1246*59bfda1fSAndroid Build Coastguard Worker
get_device_info(int i)1247*59bfda1fSAndroid Build Coastguard Worker int get_device_info(int i)
1248*59bfda1fSAndroid Build Coastguard Worker {
1249*59bfda1fSAndroid Build Coastguard Worker struct device_info *dev = c.devices + i;
1250*59bfda1fSAndroid Build Coastguard Worker uint64_t device_size = 0;
1251*59bfda1fSAndroid Build Coastguard Worker int32_t fd = 0;
1252*59bfda1fSAndroid Build Coastguard Worker
1253*59bfda1fSAndroid Build Coastguard Worker /* Block device target is not supported on Windows. */
1254*59bfda1fSAndroid Build Coastguard Worker if (!c.sparse_mode) {
1255*59bfda1fSAndroid Build Coastguard Worker if (win_get_device_size(dev->path, &device_size)) {
1256*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to get device size!\n");
1257*59bfda1fSAndroid Build Coastguard Worker return -1;
1258*59bfda1fSAndroid Build Coastguard Worker }
1259*59bfda1fSAndroid Build Coastguard Worker } else {
1260*59bfda1fSAndroid Build Coastguard Worker device_size = c.device_size;
1261*59bfda1fSAndroid Build Coastguard Worker }
1262*59bfda1fSAndroid Build Coastguard Worker if (c.sparse_mode) {
1263*59bfda1fSAndroid Build Coastguard Worker fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1264*59bfda1fSAndroid Build Coastguard Worker } else {
1265*59bfda1fSAndroid Build Coastguard Worker fd = open((char *)dev->path, O_RDWR | O_BINARY);
1266*59bfda1fSAndroid Build Coastguard Worker }
1267*59bfda1fSAndroid Build Coastguard Worker if (fd < 0) {
1268*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: Failed to open the device!\n");
1269*59bfda1fSAndroid Build Coastguard Worker return -1;
1270*59bfda1fSAndroid Build Coastguard Worker }
1271*59bfda1fSAndroid Build Coastguard Worker dev->fd = fd;
1272*59bfda1fSAndroid Build Coastguard Worker dev->total_sectors = device_size / dev->sector_size;
1273*59bfda1fSAndroid Build Coastguard Worker c.start_sector = 0;
1274*59bfda1fSAndroid Build Coastguard Worker c.sector_size = dev->sector_size;
1275*59bfda1fSAndroid Build Coastguard Worker c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1276*59bfda1fSAndroid Build Coastguard Worker c.total_sectors += dev->total_sectors;
1277*59bfda1fSAndroid Build Coastguard Worker
1278*59bfda1fSAndroid Build Coastguard Worker if (c.sparse_mode && i==0 && f2fs_init_sparse_file())
1279*59bfda1fSAndroid Build Coastguard Worker return -1;
1280*59bfda1fSAndroid Build Coastguard Worker return 0;
1281*59bfda1fSAndroid Build Coastguard Worker }
1282*59bfda1fSAndroid Build Coastguard Worker #endif
1283*59bfda1fSAndroid Build Coastguard Worker
f2fs_get_device_info(void)1284*59bfda1fSAndroid Build Coastguard Worker int f2fs_get_device_info(void)
1285*59bfda1fSAndroid Build Coastguard Worker {
1286*59bfda1fSAndroid Build Coastguard Worker int i;
1287*59bfda1fSAndroid Build Coastguard Worker
1288*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < c.ndevs; i++)
1289*59bfda1fSAndroid Build Coastguard Worker if (get_device_info(i))
1290*59bfda1fSAndroid Build Coastguard Worker return -1;
1291*59bfda1fSAndroid Build Coastguard Worker return 0;
1292*59bfda1fSAndroid Build Coastguard Worker }
1293*59bfda1fSAndroid Build Coastguard Worker
f2fs_get_f2fs_info(void)1294*59bfda1fSAndroid Build Coastguard Worker int f2fs_get_f2fs_info(void)
1295*59bfda1fSAndroid Build Coastguard Worker {
1296*59bfda1fSAndroid Build Coastguard Worker int i;
1297*59bfda1fSAndroid Build Coastguard Worker
1298*59bfda1fSAndroid Build Coastguard Worker if (c.wanted_total_sectors < c.total_sectors) {
1299*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
1300*59bfda1fSAndroid Build Coastguard Worker c.total_sectors, c.sector_size);
1301*59bfda1fSAndroid Build Coastguard Worker c.total_sectors = c.wanted_total_sectors;
1302*59bfda1fSAndroid Build Coastguard Worker c.devices[0].total_sectors = c.total_sectors;
1303*59bfda1fSAndroid Build Coastguard Worker }
1304*59bfda1fSAndroid Build Coastguard Worker if (c.total_sectors * c.sector_size >
1305*59bfda1fSAndroid Build Coastguard Worker (uint64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
1306*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
1307*59bfda1fSAndroid Build Coastguard Worker return -1;
1308*59bfda1fSAndroid Build Coastguard Worker }
1309*59bfda1fSAndroid Build Coastguard Worker
1310*59bfda1fSAndroid Build Coastguard Worker /*
1311*59bfda1fSAndroid Build Coastguard Worker * Check device types and determine the final volume operation mode:
1312*59bfda1fSAndroid Build Coastguard Worker * - If all devices are regular block devices, default operation.
1313*59bfda1fSAndroid Build Coastguard Worker * - If at least one HM device is found, operate in HM mode (BLKZONED
1314*59bfda1fSAndroid Build Coastguard Worker * feature will be enabled by mkfs).
1315*59bfda1fSAndroid Build Coastguard Worker * - If an HA device is found, let mkfs decide based on the -m option
1316*59bfda1fSAndroid Build Coastguard Worker * setting by the user.
1317*59bfda1fSAndroid Build Coastguard Worker */
1318*59bfda1fSAndroid Build Coastguard Worker c.zoned_model = F2FS_ZONED_NONE;
1319*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < c.ndevs; i++) {
1320*59bfda1fSAndroid Build Coastguard Worker switch (c.devices[i].zoned_model) {
1321*59bfda1fSAndroid Build Coastguard Worker case F2FS_ZONED_NONE:
1322*59bfda1fSAndroid Build Coastguard Worker continue;
1323*59bfda1fSAndroid Build Coastguard Worker case F2FS_ZONED_HM:
1324*59bfda1fSAndroid Build Coastguard Worker c.zoned_model = F2FS_ZONED_HM;
1325*59bfda1fSAndroid Build Coastguard Worker break;
1326*59bfda1fSAndroid Build Coastguard Worker case F2FS_ZONED_HA:
1327*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model != F2FS_ZONED_HM)
1328*59bfda1fSAndroid Build Coastguard Worker c.zoned_model = F2FS_ZONED_HA;
1329*59bfda1fSAndroid Build Coastguard Worker break;
1330*59bfda1fSAndroid Build Coastguard Worker }
1331*59bfda1fSAndroid Build Coastguard Worker }
1332*59bfda1fSAndroid Build Coastguard Worker
1333*59bfda1fSAndroid Build Coastguard Worker if (c.zoned_model != F2FS_ZONED_NONE) {
1334*59bfda1fSAndroid Build Coastguard Worker
1335*59bfda1fSAndroid Build Coastguard Worker /*
1336*59bfda1fSAndroid Build Coastguard Worker * For zoned model, the zones sizes of all zoned devices must
1337*59bfda1fSAndroid Build Coastguard Worker * be equal.
1338*59bfda1fSAndroid Build Coastguard Worker */
1339*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < c.ndevs; i++) {
1340*59bfda1fSAndroid Build Coastguard Worker if (c.devices[i].zoned_model == F2FS_ZONED_NONE)
1341*59bfda1fSAndroid Build Coastguard Worker continue;
1342*59bfda1fSAndroid Build Coastguard Worker if (c.zone_blocks &&
1343*59bfda1fSAndroid Build Coastguard Worker c.zone_blocks != c.devices[i].zone_blocks) {
1344*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\tError: zones of different size are "
1345*59bfda1fSAndroid Build Coastguard Worker "not supported\n");
1346*59bfda1fSAndroid Build Coastguard Worker return -1;
1347*59bfda1fSAndroid Build Coastguard Worker }
1348*59bfda1fSAndroid Build Coastguard Worker c.zone_blocks = c.devices[i].zone_blocks;
1349*59bfda1fSAndroid Build Coastguard Worker }
1350*59bfda1fSAndroid Build Coastguard Worker
1351*59bfda1fSAndroid Build Coastguard Worker /*
1352*59bfda1fSAndroid Build Coastguard Worker * Align sections to the device zone size and align F2FS zones
1353*59bfda1fSAndroid Build Coastguard Worker * to the device zones. For F2FS_ZONED_HA model without the
1354*59bfda1fSAndroid Build Coastguard Worker * BLKZONED feature set at format time, this is only an
1355*59bfda1fSAndroid Build Coastguard Worker * optimization as sequential writes will not be enforced.
1356*59bfda1fSAndroid Build Coastguard Worker */
1357*59bfda1fSAndroid Build Coastguard Worker c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
1358*59bfda1fSAndroid Build Coastguard Worker c.secs_per_zone = 1;
1359*59bfda1fSAndroid Build Coastguard Worker } else {
1360*59bfda1fSAndroid Build Coastguard Worker if(c.zoned_mode != 0) {
1361*59bfda1fSAndroid Build Coastguard Worker MSG(0, "\n Error: %s may not be a zoned block device \n",
1362*59bfda1fSAndroid Build Coastguard Worker c.devices[0].path);
1363*59bfda1fSAndroid Build Coastguard Worker return -1;
1364*59bfda1fSAndroid Build Coastguard Worker }
1365*59bfda1fSAndroid Build Coastguard Worker }
1366*59bfda1fSAndroid Build Coastguard Worker
1367*59bfda1fSAndroid Build Coastguard Worker c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
1368*59bfda1fSAndroid Build Coastguard Worker
1369*59bfda1fSAndroid Build Coastguard Worker if (c.func != MKFS)
1370*59bfda1fSAndroid Build Coastguard Worker return 0;
1371*59bfda1fSAndroid Build Coastguard Worker
1372*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
1373*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
1374*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: sector size = %u\n", c.sector_size);
1375*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
1376*59bfda1fSAndroid Build Coastguard Worker c.total_sectors, (c.total_sectors *
1377*59bfda1fSAndroid Build Coastguard Worker (c.sector_size >> 9)) >> 11);
1378*59bfda1fSAndroid Build Coastguard Worker return 0;
1379*59bfda1fSAndroid Build Coastguard Worker }
1380*59bfda1fSAndroid Build Coastguard Worker
calc_extra_isize(void)1381*59bfda1fSAndroid Build Coastguard Worker unsigned int calc_extra_isize(void)
1382*59bfda1fSAndroid Build Coastguard Worker {
1383*59bfda1fSAndroid Build Coastguard Worker unsigned int size = offsetof(struct f2fs_inode, i_projid);
1384*59bfda1fSAndroid Build Coastguard Worker
1385*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)
1386*59bfda1fSAndroid Build Coastguard Worker size = offsetof(struct f2fs_inode, i_projid);
1387*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_PRJQUOTA)
1388*59bfda1fSAndroid Build Coastguard Worker size = offsetof(struct f2fs_inode, i_inode_checksum);
1389*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_INODE_CHKSUM)
1390*59bfda1fSAndroid Build Coastguard Worker size = offsetof(struct f2fs_inode, i_crtime);
1391*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_INODE_CRTIME)
1392*59bfda1fSAndroid Build Coastguard Worker size = offsetof(struct f2fs_inode, i_compr_blocks);
1393*59bfda1fSAndroid Build Coastguard Worker if (c.feature & F2FS_FEATURE_COMPRESSION)
1394*59bfda1fSAndroid Build Coastguard Worker size = offsetof(struct f2fs_inode, i_extra_end);
1395*59bfda1fSAndroid Build Coastguard Worker
1396*59bfda1fSAndroid Build Coastguard Worker return size - F2FS_EXTRA_ISIZE_OFFSET;
1397*59bfda1fSAndroid Build Coastguard Worker }
1398*59bfda1fSAndroid Build Coastguard Worker
1399*59bfda1fSAndroid Build Coastguard Worker #define ARRAY_SIZE(array) \
1400*59bfda1fSAndroid Build Coastguard Worker (sizeof(array) / sizeof(array[0]))
1401*59bfda1fSAndroid Build Coastguard Worker
1402*59bfda1fSAndroid Build Coastguard Worker static const struct {
1403*59bfda1fSAndroid Build Coastguard Worker char *name;
1404*59bfda1fSAndroid Build Coastguard Worker __u16 encoding_magic;
1405*59bfda1fSAndroid Build Coastguard Worker __u16 default_flags;
1406*59bfda1fSAndroid Build Coastguard Worker
1407*59bfda1fSAndroid Build Coastguard Worker } f2fs_encoding_map[] = {
1408*59bfda1fSAndroid Build Coastguard Worker {
1409*59bfda1fSAndroid Build Coastguard Worker .encoding_magic = F2FS_ENC_UTF8_12_1,
1410*59bfda1fSAndroid Build Coastguard Worker .name = "utf8",
1411*59bfda1fSAndroid Build Coastguard Worker .default_flags = 0,
1412*59bfda1fSAndroid Build Coastguard Worker },
1413*59bfda1fSAndroid Build Coastguard Worker };
1414*59bfda1fSAndroid Build Coastguard Worker
1415*59bfda1fSAndroid Build Coastguard Worker static const struct enc_flags {
1416*59bfda1fSAndroid Build Coastguard Worker __u16 flag;
1417*59bfda1fSAndroid Build Coastguard Worker char *param;
1418*59bfda1fSAndroid Build Coastguard Worker } encoding_flags[] = {
1419*59bfda1fSAndroid Build Coastguard Worker { F2FS_ENC_STRICT_MODE_FL, "strict" },
1420*59bfda1fSAndroid Build Coastguard Worker };
1421*59bfda1fSAndroid Build Coastguard Worker
1422*59bfda1fSAndroid Build Coastguard Worker /* Return a positive number < 0xff indicating the encoding magic number
1423*59bfda1fSAndroid Build Coastguard Worker * or a negative value indicating error. */
f2fs_str2encoding(const char * string)1424*59bfda1fSAndroid Build Coastguard Worker int f2fs_str2encoding(const char *string)
1425*59bfda1fSAndroid Build Coastguard Worker {
1426*59bfda1fSAndroid Build Coastguard Worker int i;
1427*59bfda1fSAndroid Build Coastguard Worker
1428*59bfda1fSAndroid Build Coastguard Worker for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1429*59bfda1fSAndroid Build Coastguard Worker if (!strcmp(string, f2fs_encoding_map[i].name))
1430*59bfda1fSAndroid Build Coastguard Worker return f2fs_encoding_map[i].encoding_magic;
1431*59bfda1fSAndroid Build Coastguard Worker
1432*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
1433*59bfda1fSAndroid Build Coastguard Worker }
1434*59bfda1fSAndroid Build Coastguard Worker
f2fs_encoding2str(const int encoding)1435*59bfda1fSAndroid Build Coastguard Worker char *f2fs_encoding2str(const int encoding)
1436*59bfda1fSAndroid Build Coastguard Worker {
1437*59bfda1fSAndroid Build Coastguard Worker int i;
1438*59bfda1fSAndroid Build Coastguard Worker
1439*59bfda1fSAndroid Build Coastguard Worker for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1440*59bfda1fSAndroid Build Coastguard Worker if (f2fs_encoding_map[i].encoding_magic == encoding)
1441*59bfda1fSAndroid Build Coastguard Worker return f2fs_encoding_map[i].name;
1442*59bfda1fSAndroid Build Coastguard Worker
1443*59bfda1fSAndroid Build Coastguard Worker return NULL;
1444*59bfda1fSAndroid Build Coastguard Worker }
1445*59bfda1fSAndroid Build Coastguard Worker
f2fs_get_encoding_flags(int encoding)1446*59bfda1fSAndroid Build Coastguard Worker int f2fs_get_encoding_flags(int encoding)
1447*59bfda1fSAndroid Build Coastguard Worker {
1448*59bfda1fSAndroid Build Coastguard Worker int i;
1449*59bfda1fSAndroid Build Coastguard Worker
1450*59bfda1fSAndroid Build Coastguard Worker for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1451*59bfda1fSAndroid Build Coastguard Worker if (f2fs_encoding_map[i].encoding_magic == encoding)
1452*59bfda1fSAndroid Build Coastguard Worker return f2fs_encoding_map[encoding].default_flags;
1453*59bfda1fSAndroid Build Coastguard Worker
1454*59bfda1fSAndroid Build Coastguard Worker return 0;
1455*59bfda1fSAndroid Build Coastguard Worker }
1456*59bfda1fSAndroid Build Coastguard Worker
f2fs_str2encoding_flags(char ** param,__u16 * flags)1457*59bfda1fSAndroid Build Coastguard Worker int f2fs_str2encoding_flags(char **param, __u16 *flags)
1458*59bfda1fSAndroid Build Coastguard Worker {
1459*59bfda1fSAndroid Build Coastguard Worker char *f = strtok(*param, ",");
1460*59bfda1fSAndroid Build Coastguard Worker const struct enc_flags *fl;
1461*59bfda1fSAndroid Build Coastguard Worker int i, neg = 0;
1462*59bfda1fSAndroid Build Coastguard Worker
1463*59bfda1fSAndroid Build Coastguard Worker while (f) {
1464*59bfda1fSAndroid Build Coastguard Worker neg = 0;
1465*59bfda1fSAndroid Build Coastguard Worker if (!strncmp("no", f, 2)) {
1466*59bfda1fSAndroid Build Coastguard Worker neg = 1;
1467*59bfda1fSAndroid Build Coastguard Worker f += 2;
1468*59bfda1fSAndroid Build Coastguard Worker }
1469*59bfda1fSAndroid Build Coastguard Worker
1470*59bfda1fSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) {
1471*59bfda1fSAndroid Build Coastguard Worker fl = &encoding_flags[i];
1472*59bfda1fSAndroid Build Coastguard Worker if (!strcmp(fl->param, f)) {
1473*59bfda1fSAndroid Build Coastguard Worker if (neg) {
1474*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Sub %s\n", fl->param);
1475*59bfda1fSAndroid Build Coastguard Worker *flags &= ~fl->flag;
1476*59bfda1fSAndroid Build Coastguard Worker } else {
1477*59bfda1fSAndroid Build Coastguard Worker MSG(0, "Add %s\n", fl->param);
1478*59bfda1fSAndroid Build Coastguard Worker *flags |= fl->flag;
1479*59bfda1fSAndroid Build Coastguard Worker }
1480*59bfda1fSAndroid Build Coastguard Worker
1481*59bfda1fSAndroid Build Coastguard Worker goto next_flag;
1482*59bfda1fSAndroid Build Coastguard Worker }
1483*59bfda1fSAndroid Build Coastguard Worker }
1484*59bfda1fSAndroid Build Coastguard Worker *param = f;
1485*59bfda1fSAndroid Build Coastguard Worker return -EINVAL;
1486*59bfda1fSAndroid Build Coastguard Worker next_flag:
1487*59bfda1fSAndroid Build Coastguard Worker f = strtok(NULL, ":");
1488*59bfda1fSAndroid Build Coastguard Worker }
1489*59bfda1fSAndroid Build Coastguard Worker return 0;
1490*59bfda1fSAndroid Build Coastguard Worker }
1491