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