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 #define _LARGEFILE64_SOURCE 10 11 #include <f2fs_fs.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <errno.h> 16 #include <unistd.h> 17 #include <fcntl.h> 18 #ifdef HAVE_MNTENT_H 19 #include <mntent.h> 20 #endif 21 #include <time.h> 22 #include <sys/stat.h> 23 #ifndef ANDROID_WINDOWS_HOST 24 #include <sys/mount.h> 25 #include <sys/ioctl.h> 26 #endif 27 #ifdef HAVE_SYS_SYSMACROS_H 28 #include <sys/sysmacros.h> 29 #endif 30 #ifdef HAVE_SYS_UTSNAME_H 31 #include <sys/utsname.h> 32 #endif 33 #ifndef WITH_ANDROID 34 #ifdef HAVE_SCSI_SG_H 35 #include <scsi/sg.h> 36 #endif 37 #endif 38 #ifdef HAVE_LINUX_HDREG_H 39 #include <linux/hdreg.h> 40 #endif 41 #ifdef HAVE_LINUX_LIMITS_H 42 #include <linux/limits.h> 43 #endif 44 45 #ifndef WITH_ANDROID 46 /* SCSI command for standard inquiry*/ 47 #define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00 48 #endif 49 50 #ifndef ANDROID_WINDOWS_HOST /* 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 */ 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 105 static u_int16_t *wchar_to_utf16(u_int16_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 121 int utf8_to_utf16(u_int16_t *output, const char *input, size_t outsize, 122 size_t insize) 123 { 124 const char *inp = input; 125 u_int16_t *outp = output; 126 wchar_t wc; 127 128 while ((size_t)(inp - input) < insize && *inp) { 129 inp = utf8_to_wchar(inp, &wc, insize - (inp - input)); 130 if (inp == NULL) { 131 DBG(0, "illegal UTF-8 sequence\n"); 132 return -EILSEQ; 133 } 134 outp = wchar_to_utf16(outp, wc, outsize - (outp - output)); 135 if (outp == NULL) { 136 DBG(0, "name is too long\n"); 137 return -ENAMETOOLONG; 138 } 139 } 140 *outp = cpu_to_le16(0); 141 return 0; 142 } 143 144 static const u_int16_t *utf16_to_wchar(const u_int16_t *input, wchar_t *wc, 145 size_t insize) 146 { 147 if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) { 148 if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00) 149 return NULL; 150 *wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10); 151 *wc |= (le16_to_cpu(input[1]) & 0x3ff); 152 *wc += 0x10000; 153 return input + 2; 154 } else { 155 *wc = le16_to_cpu(*input); 156 return input + 1; 157 } 158 } 159 160 static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize) 161 { 162 if (wc <= 0x7f) { 163 if (outsize < 1) 164 return NULL; 165 *output++ = (char) wc; 166 } else if (wc <= 0x7ff) { 167 if (outsize < 2) 168 return NULL; 169 *output++ = 0xc0 | (wc >> 6); 170 *output++ = 0x80 | (wc & 0x3f); 171 } else if (wc <= 0xffff) { 172 if (outsize < 3) 173 return NULL; 174 *output++ = 0xe0 | (wc >> 12); 175 *output++ = 0x80 | ((wc >> 6) & 0x3f); 176 *output++ = 0x80 | (wc & 0x3f); 177 } else if (wc <= 0x1fffff) { 178 if (outsize < 4) 179 return NULL; 180 *output++ = 0xf0 | (wc >> 18); 181 *output++ = 0x80 | ((wc >> 12) & 0x3f); 182 *output++ = 0x80 | ((wc >> 6) & 0x3f); 183 *output++ = 0x80 | (wc & 0x3f); 184 } else if (wc <= 0x3ffffff) { 185 if (outsize < 5) 186 return NULL; 187 *output++ = 0xf8 | (wc >> 24); 188 *output++ = 0x80 | ((wc >> 18) & 0x3f); 189 *output++ = 0x80 | ((wc >> 12) & 0x3f); 190 *output++ = 0x80 | ((wc >> 6) & 0x3f); 191 *output++ = 0x80 | (wc & 0x3f); 192 } else if (wc <= 0x7fffffff) { 193 if (outsize < 6) 194 return NULL; 195 *output++ = 0xfc | (wc >> 30); 196 *output++ = 0x80 | ((wc >> 24) & 0x3f); 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 202 return NULL; 203 204 return output; 205 } 206 207 int utf16_to_utf8(char *output, const u_int16_t *input, size_t outsize, 208 size_t insize) 209 { 210 const u_int16_t *inp = input; 211 char *outp = output; 212 wchar_t wc; 213 214 while ((size_t)(inp - input) < insize && le16_to_cpu(*inp)) { 215 inp = utf16_to_wchar(inp, &wc, insize - (inp - input)); 216 if (inp == NULL) { 217 DBG(0, "illegal UTF-16 sequence\n"); 218 return -EILSEQ; 219 } 220 outp = wchar_to_utf8(outp, wc, outsize - (outp - output)); 221 if (outp == NULL) { 222 DBG(0, "name is too long\n"); 223 return -ENAMETOOLONG; 224 } 225 } 226 *outp = '\0'; 227 return 0; 228 } 229 230 int log_base_2(u_int32_t num) 231 { 232 int ret = 0; 233 if (num <= 0 || (num & (num - 1)) != 0) 234 return -1; 235 236 while (num >>= 1) 237 ret++; 238 return ret; 239 } 240 241 /* 242 * f2fs bit operations 243 */ 244 static const int bits_in_byte[256] = { 245 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 246 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 247 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 248 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 249 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 250 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 251 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 252 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 253 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 254 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 255 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 256 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 257 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 258 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 259 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 260 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 261 }; 262 263 int get_bits_in_byte(unsigned char n) 264 { 265 return bits_in_byte[n]; 266 } 267 268 int test_and_set_bit_le(u32 nr, u8 *addr) 269 { 270 int mask, retval; 271 272 addr += nr >> 3; 273 mask = 1 << ((nr & 0x07)); 274 retval = mask & *addr; 275 *addr |= mask; 276 return retval; 277 } 278 279 int test_and_clear_bit_le(u32 nr, u8 *addr) 280 { 281 int mask, retval; 282 283 addr += nr >> 3; 284 mask = 1 << ((nr & 0x07)); 285 retval = mask & *addr; 286 *addr &= ~mask; 287 return retval; 288 } 289 290 int test_bit_le(u32 nr, const u8 *addr) 291 { 292 return ((1 << (nr & 7)) & (addr[nr >> 3])); 293 } 294 295 int f2fs_test_bit(unsigned int nr, const char *p) 296 { 297 int mask; 298 char *addr = (char *)p; 299 300 addr += (nr >> 3); 301 mask = 1 << (7 - (nr & 0x07)); 302 return (mask & *addr) != 0; 303 } 304 305 int f2fs_set_bit(unsigned int nr, char *addr) 306 { 307 int mask; 308 int ret; 309 310 addr += (nr >> 3); 311 mask = 1 << (7 - (nr & 0x07)); 312 ret = mask & *addr; 313 *addr |= mask; 314 return ret; 315 } 316 317 int f2fs_clear_bit(unsigned int nr, char *addr) 318 { 319 int mask; 320 int ret; 321 322 addr += (nr >> 3); 323 mask = 1 << (7 - (nr & 0x07)); 324 ret = mask & *addr; 325 *addr &= ~mask; 326 return ret; 327 } 328 329 static inline u64 __ffs(u8 word) 330 { 331 int num = 0; 332 333 if ((word & 0xf) == 0) { 334 num += 4; 335 word >>= 4; 336 } 337 if ((word & 0x3) == 0) { 338 num += 2; 339 word >>= 2; 340 } 341 if ((word & 0x1) == 0) 342 num += 1; 343 return num; 344 } 345 346 /* Copied from linux/lib/find_bit.c */ 347 #define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1))) 348 349 static u64 _find_next_bit_le(const u8 *addr, u64 nbits, u64 start, char invert) 350 { 351 u8 tmp; 352 353 if (!nbits || start >= nbits) 354 return nbits; 355 356 tmp = addr[start / BITS_PER_BYTE] ^ invert; 357 358 /* Handle 1st word. */ 359 tmp &= BITMAP_FIRST_BYTE_MASK(start); 360 start = round_down(start, BITS_PER_BYTE); 361 362 while (!tmp) { 363 start += BITS_PER_BYTE; 364 if (start >= nbits) 365 return nbits; 366 367 tmp = addr[start / BITS_PER_BYTE] ^ invert; 368 } 369 370 return min(start + __ffs(tmp), nbits); 371 } 372 373 u64 find_next_bit_le(const u8 *addr, u64 size, u64 offset) 374 { 375 return _find_next_bit_le(addr, size, offset, 0); 376 } 377 378 379 u64 find_next_zero_bit_le(const u8 *addr, u64 size, u64 offset) 380 { 381 return _find_next_bit_le(addr, size, offset, 0xff); 382 } 383 384 /* 385 * Hashing code adapted from ext3 386 */ 387 #define DELTA 0x9E3779B9 388 389 static void TEA_transform(unsigned int buf[4], unsigned int const in[]) 390 { 391 __u32 sum = 0; 392 __u32 b0 = buf[0], b1 = buf[1]; 393 __u32 a = in[0], b = in[1], c = in[2], d = in[3]; 394 int n = 16; 395 396 do { 397 sum += DELTA; 398 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); 399 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); 400 } while (--n); 401 402 buf[0] += b0; 403 buf[1] += b1; 404 405 } 406 407 static void str2hashbuf(const unsigned char *msg, int len, 408 unsigned int *buf, int num) 409 { 410 unsigned pad, val; 411 int i; 412 413 pad = (__u32)len | ((__u32)len << 8); 414 pad |= pad << 16; 415 416 val = pad; 417 if (len > num * 4) 418 len = num * 4; 419 for (i = 0; i < len; i++) { 420 if ((i % 4) == 0) 421 val = pad; 422 val = msg[i] + (val << 8); 423 if ((i % 4) == 3) { 424 *buf++ = val; 425 val = pad; 426 num--; 427 } 428 } 429 if (--num >= 0) 430 *buf++ = val; 431 while (--num >= 0) 432 *buf++ = pad; 433 434 } 435 436 /** 437 * Return hash value of directory entry 438 * @param name dentry name 439 * @param len name lenth 440 * @return return on success hash value, errno on failure 441 */ 442 f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len) 443 { 444 __u32 hash; 445 f2fs_hash_t f2fs_hash; 446 const unsigned char *p; 447 __u32 in[8], buf[4]; 448 449 /* special hash codes for special dentries */ 450 if ((len <= 2) && (name[0] == '.') && 451 (name[1] == '.' || name[1] == '\0')) 452 return 0; 453 454 /* Initialize the default seed for the hash checksum functions */ 455 buf[0] = 0x67452301; 456 buf[1] = 0xefcdab89; 457 buf[2] = 0x98badcfe; 458 buf[3] = 0x10325476; 459 460 p = name; 461 while (1) { 462 str2hashbuf(p, len, in, 4); 463 TEA_transform(buf, in); 464 p += 16; 465 if (len <= 16) 466 break; 467 len -= 16; 468 } 469 hash = buf[0]; 470 471 f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT); 472 return f2fs_hash; 473 } 474 475 unsigned int addrs_per_inode(struct f2fs_inode *i) 476 { 477 return CUR_ADDRS_PER_INODE(i) - get_inline_xattr_addrs(i); 478 } 479 480 /* 481 * CRC32 482 */ 483 #define CRCPOLY_LE 0xedb88320 484 485 u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len) 486 { 487 int i; 488 unsigned char *p = (unsigned char *)buf; 489 while (len--) { 490 crc ^= *p++; 491 for (i = 0; i < 8; i++) 492 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); 493 } 494 return crc; 495 } 496 497 int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len) 498 { 499 u_int32_t cal_crc = 0; 500 501 cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len); 502 503 if (cal_crc != blk_crc) { 504 DBG(0,"CRC validation failed: cal_crc = %u, " 505 "blk_crc = %u buff_size = 0x%x\n", 506 cal_crc, blk_crc, len); 507 return -1; 508 } 509 return 0; 510 } 511 512 __u32 f2fs_inode_chksum(struct f2fs_node *node) 513 { 514 struct f2fs_inode *ri = &node->i; 515 __le32 ino = node->footer.ino; 516 __le32 gen = ri->i_generation; 517 __u32 chksum, chksum_seed; 518 __u32 dummy_cs = 0; 519 unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum); 520 unsigned int cs_size = sizeof(dummy_cs); 521 522 chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino, 523 sizeof(ino)); 524 chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen)); 525 526 chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset); 527 chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size); 528 offset += cs_size; 529 chksum = f2fs_cal_crc32(chksum, (__u8 *)ri + offset, 530 F2FS_BLKSIZE - offset); 531 return chksum; 532 } 533 534 /* 535 * try to identify the root device 536 */ 537 const char *get_rootdev() 538 { 539 #if defined(ANDROID_WINDOWS_HOST) || defined(WITH_ANDROID) 540 return NULL; 541 #else 542 struct stat sb; 543 int fd, ret; 544 char buf[32]; 545 char *uevent, *ptr; 546 547 static char rootdev[PATH_MAX + 1]; 548 549 if (stat("/", &sb) == -1) 550 return NULL; 551 552 snprintf(buf, 32, "/sys/dev/block/%u:%u/uevent", 553 major(sb.st_dev), minor(sb.st_dev)); 554 555 fd = open(buf, O_RDONLY); 556 557 if (fd < 0) 558 return NULL; 559 560 ret = lseek(fd, (off_t)0, SEEK_END); 561 (void)lseek(fd, (off_t)0, SEEK_SET); 562 563 if (ret == -1) { 564 close(fd); 565 return NULL; 566 } 567 568 uevent = malloc(ret + 1); 569 uevent[ret] = '\0'; 570 571 ret = read(fd, uevent, ret); 572 close(fd); 573 574 ptr = strstr(uevent, "DEVNAME"); 575 if (!ptr) 576 return NULL; 577 578 ret = sscanf(ptr, "DEVNAME=%s\n", buf); 579 snprintf(rootdev, PATH_MAX + 1, "/dev/%s", buf); 580 581 return rootdev; 582 #endif 583 } 584 585 /* 586 * device information 587 */ 588 void f2fs_init_configuration(void) 589 { 590 int i; 591 592 c.ndevs = 1; 593 c.total_sectors = 0; 594 c.sector_size = 0; 595 c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK; 596 c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT; 597 c.rootdev_name = get_rootdev(); 598 c.wanted_total_sectors = -1; 599 c.wanted_sector_size = -1; 600 c.zoned_mode = 0; 601 c.zoned_model = 0; 602 c.zone_blocks = 0; 603 #ifdef WITH_ANDROID 604 c.preserve_limits = 0; 605 #else 606 c.preserve_limits = 1; 607 #endif 608 609 for (i = 0; i < MAX_DEVICES; i++) { 610 memset(&c.devices[i], 0, sizeof(struct device_info)); 611 c.devices[i].fd = -1; 612 c.devices[i].sector_size = DEFAULT_SECTOR_SIZE; 613 c.devices[i].end_blkaddr = -1; 614 c.devices[i].zoned_model = F2FS_ZONED_NONE; 615 } 616 617 /* calculated by overprovision ratio */ 618 c.reserved_segments = 0; 619 c.overprovision = 0; 620 c.segs_per_sec = 1; 621 c.secs_per_zone = 1; 622 c.segs_per_zone = 1; 623 c.heap = 0; 624 c.vol_label = ""; 625 c.trim = 1; 626 c.trimmed = 0; 627 c.ro = 0; 628 c.kd = -1; 629 c.dry_run = 0; 630 c.fixed_time = -1; 631 } 632 633 #ifdef HAVE_SETMNTENT 634 static int is_mounted(const char *mpt, const char *device) 635 { 636 FILE *file = NULL; 637 struct mntent *mnt = NULL; 638 639 file = setmntent(mpt, "r"); 640 if (file == NULL) 641 return 0; 642 643 while ((mnt = getmntent(file)) != NULL) { 644 if (!strcmp(device, mnt->mnt_fsname)) { 645 #ifdef MNTOPT_RO 646 if (hasmntopt(mnt, MNTOPT_RO)) 647 c.ro = 1; 648 #endif 649 break; 650 } 651 } 652 endmntent(file); 653 return mnt ? 1 : 0; 654 } 655 #endif 656 657 int f2fs_dev_is_umounted(char *path) 658 { 659 #ifdef ANDROID_WINDOWS_HOST 660 return 0; 661 #else 662 struct stat *st_buf; 663 int is_rootdev = 0; 664 int ret = 0; 665 666 if (c.rootdev_name && !strcmp(path, c.rootdev_name)) 667 is_rootdev = 1; 668 669 /* 670 * try with /proc/mounts fist to detect RDONLY. 671 * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab. 672 */ 673 #ifdef __linux__ 674 ret = is_mounted("/proc/mounts", path); 675 if (ret) { 676 MSG(0, "Info: Mounted device!\n"); 677 return -1; 678 } 679 #endif 680 #if defined(MOUNTED) || defined(_PATH_MOUNTED) 681 #ifndef MOUNTED 682 #define MOUNTED _PATH_MOUNTED 683 #endif 684 ret = is_mounted(MOUNTED, path); 685 if (ret) { 686 MSG(0, "Info: Mounted device!\n"); 687 return -1; 688 } 689 #endif 690 /* 691 * If we are supposed to operate on the root device, then 692 * also check the mounts for '/dev/root', which sometimes 693 * functions as an alias for the root device. 694 */ 695 if (is_rootdev) { 696 #ifdef __linux__ 697 ret = is_mounted("/proc/mounts", "/dev/root"); 698 if (ret) { 699 MSG(0, "Info: Mounted device!\n"); 700 return -1; 701 } 702 #endif 703 } 704 705 /* 706 * If f2fs is umounted with -l, the process can still use 707 * the file system. In this case, we should not format. 708 */ 709 st_buf = malloc(sizeof(struct stat)); 710 if (stat(path, st_buf) == 0 && S_ISBLK(st_buf->st_mode)) { 711 int fd = open(path, O_RDONLY | O_EXCL); 712 713 if (fd >= 0) { 714 close(fd); 715 } else if (errno == EBUSY) { 716 MSG(0, "\tError: In use by the system!\n"); 717 free(st_buf); 718 return -1; 719 } 720 } 721 free(st_buf); 722 return ret; 723 #endif 724 } 725 726 int f2fs_devs_are_umounted(void) 727 { 728 int i; 729 730 for (i = 0; i < c.ndevs; i++) 731 if (f2fs_dev_is_umounted((char *)c.devices[i].path)) 732 return -1; 733 return 0; 734 } 735 736 void get_kernel_version(__u8 *version) 737 { 738 int i; 739 for (i = 0; i < VERSION_LEN; i++) { 740 if (version[i] == '\n') 741 break; 742 } 743 memset(version + i, 0, VERSION_LEN + 1 - i); 744 } 745 746 void get_kernel_uname_version(__u8 *version) 747 { 748 #ifdef HAVE_SYS_UTSNAME_H 749 struct utsname buf; 750 751 memset(version, 0, VERSION_LEN); 752 if (uname(&buf)) 753 return; 754 755 snprintf((char *)version, 756 VERSION_LEN, "%s %s", buf.release, buf.version); 757 #else 758 memset(version, 0, VERSION_LEN); 759 #endif 760 } 761 762 #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) 763 #define BLKGETSIZE _IO(0x12,96) 764 #endif 765 766 #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) 767 #define BLKGETSIZE64 _IOR(0x12,114, size_t) 768 #endif 769 770 #if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET) 771 #define BLKSSZGET _IO(0x12,104) 772 #endif 773 774 #if defined(__APPLE__) 775 #include <sys/disk.h> 776 #define BLKGETSIZE DKIOCGETBLOCKCOUNT 777 #define BLKSSZGET DKIOCGETBLOCKCOUNT 778 #endif /* APPLE_DARWIN */ 779 780 #ifndef ANDROID_WINDOWS_HOST 781 int get_device_info(int i) 782 { 783 int32_t fd = 0; 784 uint32_t sector_size; 785 #ifndef BLKGETSIZE64 786 uint32_t total_sectors; 787 #endif 788 struct stat *stat_buf; 789 #ifdef HDIO_GETGIO 790 struct hd_geometry geom; 791 #endif 792 #if !defined(WITH_ANDROID) && defined(__linux__) 793 sg_io_hdr_t io_hdr; 794 unsigned char reply_buffer[96] = {0}; 795 unsigned char model_inq[6] = {MODELINQUIRY}; 796 #endif 797 struct device_info *dev = c.devices + i; 798 799 if (c.sparse_mode) { 800 fd = open((char *)dev->path, O_RDWR | O_CREAT | O_BINARY, 0644); 801 } else { 802 fd = open((char *)dev->path, O_RDWR); 803 } 804 if (fd < 0) { 805 MSG(0, "\tError: Failed to open the device!\n"); 806 return -1; 807 } 808 809 dev->fd = fd; 810 811 if (c.sparse_mode) { 812 if (f2fs_init_sparse_file()) 813 return -1; 814 } 815 816 if (c.kd == -1) { 817 #if !defined(WITH_ANDROID) && defined(__linux__) 818 c.kd = open("/proc/version", O_RDONLY); 819 #endif 820 if (c.kd < 0) { 821 MSG(0, "\tInfo: No support kernel version!\n"); 822 c.kd = -2; 823 } 824 } 825 826 stat_buf = malloc(sizeof(struct stat)); 827 if (fstat(fd, stat_buf) < 0 ) { 828 MSG(0, "\tError: Failed to get the device stat!\n"); 829 free(stat_buf); 830 return -1; 831 } 832 833 if (c.sparse_mode) { 834 dev->total_sectors = c.device_size / dev->sector_size; 835 } else if (S_ISREG(stat_buf->st_mode)) { 836 dev->total_sectors = stat_buf->st_size / dev->sector_size; 837 } else if (S_ISBLK(stat_buf->st_mode)) { 838 #ifdef BLKSSZGET 839 if (ioctl(fd, BLKSSZGET, §or_size) < 0) 840 MSG(0, "\tError: Using the default sector size\n"); 841 else if (dev->sector_size < sector_size) 842 dev->sector_size = sector_size; 843 #endif 844 #ifdef BLKGETSIZE64 845 if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) { 846 MSG(0, "\tError: Cannot get the device size\n"); 847 free(stat_buf); 848 return -1; 849 } 850 #else 851 if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) { 852 MSG(0, "\tError: Cannot get the device size\n"); 853 free(stat_buf); 854 return -1; 855 } 856 dev->total_sectors = total_sectors; 857 #endif 858 dev->total_sectors /= dev->sector_size; 859 860 if (i == 0) { 861 #ifdef HDIO_GETGIO 862 if (ioctl(fd, HDIO_GETGEO, &geom) < 0) 863 c.start_sector = 0; 864 else 865 c.start_sector = geom.start; 866 #else 867 c.start_sector = 0; 868 #endif 869 } 870 871 #if !defined(WITH_ANDROID) && defined(__linux__) 872 /* Send INQUIRY command */ 873 memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); 874 io_hdr.interface_id = 'S'; 875 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; 876 io_hdr.dxfer_len = sizeof(reply_buffer); 877 io_hdr.dxferp = reply_buffer; 878 io_hdr.cmd_len = sizeof(model_inq); 879 io_hdr.cmdp = model_inq; 880 io_hdr.timeout = 1000; 881 882 if (!ioctl(fd, SG_IO, &io_hdr)) { 883 int i = 16; 884 885 MSG(0, "Info: [%s] Disk Model: ", 886 dev->path); 887 while (reply_buffer[i] != '`' && i < 80) 888 printf("%c", reply_buffer[i++]); 889 printf("\n"); 890 } 891 #endif 892 } else { 893 MSG(0, "\tError: Volume type is not supported!!!\n"); 894 free(stat_buf); 895 return -1; 896 } 897 898 if (!c.sector_size) { 899 c.sector_size = dev->sector_size; 900 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size; 901 } else if (c.sector_size != c.devices[i].sector_size) { 902 MSG(0, "\tError: Different sector sizes!!!\n"); 903 free(stat_buf); 904 return -1; 905 } 906 907 #if !defined(WITH_ANDROID) && defined(__linux__) 908 if (S_ISBLK(stat_buf->st_mode)) 909 f2fs_get_zoned_model(i); 910 911 if (dev->zoned_model != F2FS_ZONED_NONE) { 912 if (dev->zoned_model == F2FS_ZONED_HM) 913 c.zoned_model = F2FS_ZONED_HM; 914 915 if (f2fs_get_zone_blocks(i)) { 916 MSG(0, "\tError: Failed to get number of blocks per zone\n"); 917 free(stat_buf); 918 return -1; 919 } 920 921 if (f2fs_check_zones(i)) { 922 MSG(0, "\tError: Failed to check zone configuration\n"); 923 free(stat_buf); 924 return -1; 925 } 926 MSG(0, "Info: Host-%s zoned block device:\n", 927 (dev->zoned_model == F2FS_ZONED_HA) ? 928 "aware" : "managed"); 929 MSG(0, " %u zones, %u randomly writeable zones\n", 930 dev->nr_zones, dev->nr_rnd_zones); 931 MSG(0, " %lu blocks per zone\n", 932 dev->zone_blocks); 933 } 934 #endif 935 /* adjust wanted_total_sectors */ 936 if (c.wanted_total_sectors != -1) { 937 MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n", 938 c.wanted_total_sectors, c.wanted_sector_size); 939 if (c.wanted_sector_size == -1) { 940 c.wanted_sector_size = dev->sector_size; 941 } else if (dev->sector_size != c.wanted_sector_size) { 942 c.wanted_total_sectors *= c.wanted_sector_size; 943 c.wanted_total_sectors /= dev->sector_size; 944 } 945 } 946 947 c.total_sectors += dev->total_sectors; 948 free(stat_buf); 949 return 0; 950 } 951 952 #else 953 954 #include "windows.h" 955 #include "winioctl.h" 956 957 #if (_WIN32_WINNT >= 0x0500) 958 #define HAVE_GET_FILE_SIZE_EX 1 959 #endif 960 961 static int win_get_device_size(const char *file, uint64_t *device_size) 962 { 963 HANDLE dev; 964 PARTITION_INFORMATION pi; 965 DISK_GEOMETRY gi; 966 DWORD retbytes; 967 #ifdef HAVE_GET_FILE_SIZE_EX 968 LARGE_INTEGER filesize; 969 #else 970 DWORD filesize; 971 #endif /* HAVE_GET_FILE_SIZE_EX */ 972 973 dev = CreateFile(file, GENERIC_READ, 974 FILE_SHARE_READ | FILE_SHARE_WRITE , 975 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 976 977 if (dev == INVALID_HANDLE_VALUE) 978 return EBADF; 979 if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, 980 &pi, sizeof(PARTITION_INFORMATION), 981 &pi, sizeof(PARTITION_INFORMATION), 982 &retbytes, NULL)) { 983 984 *device_size = pi.PartitionLength.QuadPart; 985 986 } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, 987 &gi, sizeof(DISK_GEOMETRY), 988 &gi, sizeof(DISK_GEOMETRY), 989 &retbytes, NULL)) { 990 991 *device_size = gi.BytesPerSector * 992 gi.SectorsPerTrack * 993 gi.TracksPerCylinder * 994 gi.Cylinders.QuadPart; 995 996 #ifdef HAVE_GET_FILE_SIZE_EX 997 } else if (GetFileSizeEx(dev, &filesize)) { 998 *device_size = filesize.QuadPart; 999 } 1000 #else 1001 } else { 1002 filesize = GetFileSize(dev, NULL); 1003 if (INVALID_FILE_SIZE != filesize) 1004 return -1; 1005 *device_size = filesize; 1006 } 1007 #endif /* HAVE_GET_FILE_SIZE_EX */ 1008 1009 CloseHandle(dev); 1010 return 0; 1011 } 1012 1013 int get_device_info(int i) 1014 { 1015 struct device_info *dev = c.devices + i; 1016 uint64_t device_size = 0; 1017 int32_t fd = 0; 1018 1019 /* Block device target is not supported on Windows. */ 1020 if (!c.sparse_mode) { 1021 if (win_get_device_size(dev->path, &device_size)) { 1022 MSG(0, "\tError: Failed to get device size!\n"); 1023 return -1; 1024 } 1025 } else { 1026 device_size = c.device_size; 1027 } 1028 if (c.sparse_mode) { 1029 fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); 1030 } else { 1031 fd = open((char *)dev->path, O_RDWR | O_BINARY); 1032 } 1033 if (fd < 0) { 1034 MSG(0, "\tError: Failed to open the device!\n"); 1035 return -1; 1036 } 1037 dev->fd = fd; 1038 dev->total_sectors = device_size / dev->sector_size; 1039 c.start_sector = 0; 1040 c.sector_size = dev->sector_size; 1041 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size; 1042 c.total_sectors += dev->total_sectors; 1043 1044 return 0; 1045 } 1046 #endif 1047 1048 int f2fs_get_device_info(void) 1049 { 1050 int i; 1051 1052 for (i = 0; i < c.ndevs; i++) 1053 if (get_device_info(i)) 1054 return -1; 1055 1056 if (c.wanted_total_sectors < c.total_sectors) { 1057 MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n", 1058 c.total_sectors, c.sector_size); 1059 c.total_sectors = c.wanted_total_sectors; 1060 c.devices[0].total_sectors = c.total_sectors; 1061 } 1062 if (c.total_sectors * c.sector_size > 1063 (u_int64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) { 1064 MSG(0, "\tError: F2FS can support 16TB at most!!!\n"); 1065 return -1; 1066 } 1067 1068 for (i = 0; i < c.ndevs; i++) { 1069 if (c.devices[i].zoned_model != F2FS_ZONED_NONE) { 1070 if (c.zone_blocks && 1071 c.zone_blocks != c.devices[i].zone_blocks) { 1072 MSG(0, "\tError: not support different zone sizes!!!\n"); 1073 return -1; 1074 } 1075 c.zone_blocks = c.devices[i].zone_blocks; 1076 } 1077 } 1078 1079 /* 1080 * Align sections to the device zone size 1081 * and align F2FS zones to the device zones. 1082 */ 1083 if (c.zone_blocks) { 1084 c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT; 1085 c.secs_per_zone = 1; 1086 } else { 1087 c.zoned_mode = 0; 1088 } 1089 1090 c.segs_per_zone = c.segs_per_sec * c.secs_per_zone; 1091 1092 MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec); 1093 MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone); 1094 MSG(0, "Info: sector size = %u\n", c.sector_size); 1095 MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n", 1096 c.total_sectors, (c.total_sectors * 1097 (c.sector_size >> 9)) >> 11); 1098 return 0; 1099 } 1100