4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
7 * Dual licensed under the GPL or LGPL version 2 licenses.
9 #define _LARGEFILE64_SOURCE
10 #define _FILE_OFFSET_BITS 64
25 #ifdef HAVE_SYS_IOCTL_H
26 #include <sys/ioctl.h>
28 #ifdef HAVE_SYS_SYSMACROS_H
29 #include <sys/sysmacros.h>
31 #ifdef HAVE_SYS_UTSNAME_H
32 #include <sys/utsname.h>
37 #ifdef HAVE_LINUX_HDREG_H
38 #include <linux/hdreg.h>
40 #ifdef HAVE_LINUX_LIMITS_H
41 #include <linux/limits.h>
44 /* SCSI command for standard inquiry*/
45 #define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00
47 #ifndef _WIN32 /* O_BINARY is windows-specific flag */
50 /* On Windows, wchar_t is 8 bit sized and it causes compilation errors. */
55 * UTF conversion codes are Copied from exfat tools.
57 static const char *utf8_to_wchar(const char *input, wchar_t *wc,
60 if ((input[0] & 0x80) == 0 && insize >= 1) {
61 *wc = (wchar_t) input[0];
64 if ((input[0] & 0xe0) == 0xc0 && insize >= 2) {
65 *wc = (((wchar_t) input[0] & 0x1f) << 6) |
66 ((wchar_t) input[1] & 0x3f);
69 if ((input[0] & 0xf0) == 0xe0 && insize >= 3) {
70 *wc = (((wchar_t) input[0] & 0x0f) << 12) |
71 (((wchar_t) input[1] & 0x3f) << 6) |
72 ((wchar_t) input[2] & 0x3f);
75 if ((input[0] & 0xf8) == 0xf0 && insize >= 4) {
76 *wc = (((wchar_t) input[0] & 0x07) << 18) |
77 (((wchar_t) input[1] & 0x3f) << 12) |
78 (((wchar_t) input[2] & 0x3f) << 6) |
79 ((wchar_t) input[3] & 0x3f);
82 if ((input[0] & 0xfc) == 0xf8 && insize >= 5) {
83 *wc = (((wchar_t) input[0] & 0x03) << 24) |
84 (((wchar_t) input[1] & 0x3f) << 18) |
85 (((wchar_t) input[2] & 0x3f) << 12) |
86 (((wchar_t) input[3] & 0x3f) << 6) |
87 ((wchar_t) input[4] & 0x3f);
90 if ((input[0] & 0xfe) == 0xfc && insize >= 6) {
91 *wc = (((wchar_t) input[0] & 0x01) << 30) |
92 (((wchar_t) input[1] & 0x3f) << 24) |
93 (((wchar_t) input[2] & 0x3f) << 18) |
94 (((wchar_t) input[3] & 0x3f) << 12) |
95 (((wchar_t) input[4] & 0x3f) << 6) |
96 ((wchar_t) input[5] & 0x3f);
102 static uint16_t *wchar_to_utf16(uint16_t *output, wchar_t wc, size_t outsize)
107 output[0] = cpu_to_le16(wc);
113 output[0] = cpu_to_le16(0xd800 | ((wc >> 10) & 0x3ff));
114 output[1] = cpu_to_le16(0xdc00 | (wc & 0x3ff));
118 int utf8_to_utf16(char *output, const char *input, size_t outsize,
121 const char *inp = input;
124 uint16_t *volume_name = calloc(sizeof(uint16_t), MAX_VOLUME_NAME);
131 while ((size_t)(inp - input) < insize && *inp) {
132 inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
134 DBG(0, "illegal UTF-8 sequence\n");
138 outp = wchar_to_utf16(outp, wc, outsize - (outp - volume_name));
140 DBG(0, "name is too long\n");
142 return -ENAMETOOLONG;
145 *outp = cpu_to_le16(0);
146 memcpy(output, volume_name, sizeof(uint16_t) * MAX_VOLUME_NAME);
151 static uint16_t *utf16_to_wchar(uint16_t *input, wchar_t *wc, size_t insize)
153 if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) {
154 if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00)
156 *wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
157 *wc |= (le16_to_cpu(input[1]) & 0x3ff);
161 *wc = le16_to_cpu(*input);
166 static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize)
171 *output++ = (char) wc;
172 } else if (wc <= 0x7ff) {
175 *output++ = 0xc0 | (wc >> 6);
176 *output++ = 0x80 | (wc & 0x3f);
177 } else if (wc <= 0xffff) {
180 *output++ = 0xe0 | (wc >> 12);
181 *output++ = 0x80 | ((wc >> 6) & 0x3f);
182 *output++ = 0x80 | (wc & 0x3f);
183 } else if (wc <= 0x1fffff) {
186 *output++ = 0xf0 | (wc >> 18);
187 *output++ = 0x80 | ((wc >> 12) & 0x3f);
188 *output++ = 0x80 | ((wc >> 6) & 0x3f);
189 *output++ = 0x80 | (wc & 0x3f);
190 } else if (wc <= 0x3ffffff) {
193 *output++ = 0xf8 | (wc >> 24);
194 *output++ = 0x80 | ((wc >> 18) & 0x3f);
195 *output++ = 0x80 | ((wc >> 12) & 0x3f);
196 *output++ = 0x80 | ((wc >> 6) & 0x3f);
197 *output++ = 0x80 | (wc & 0x3f);
198 } else if (wc <= 0x7fffffff) {
201 *output++ = 0xfc | (wc >> 30);
202 *output++ = 0x80 | ((wc >> 24) & 0x3f);
203 *output++ = 0x80 | ((wc >> 18) & 0x3f);
204 *output++ = 0x80 | ((wc >> 12) & 0x3f);
205 *output++ = 0x80 | ((wc >> 6) & 0x3f);
206 *output++ = 0x80 | (wc & 0x3f);
213 int utf16_to_utf8(char *output, const char *input, size_t outsize,
219 uint16_t *volume_name = calloc(sizeof(uint16_t), MAX_VOLUME_NAME);
224 memcpy(volume_name, input, sizeof(uint16_t) * MAX_VOLUME_NAME);
227 while ((size_t)(inp - volume_name) < insize && le16_to_cpu(*inp)) {
228 inp = utf16_to_wchar(inp, &wc, insize - (inp - volume_name));
230 DBG(0, "illegal UTF-16 sequence\n");
234 outp = wchar_to_utf8(outp, wc, outsize - (outp - output));
236 DBG(0, "name is too long\n");
238 return -ENAMETOOLONG;
246 int log_base_2(uint32_t num)
249 if (num <= 0 || (num & (num - 1)) != 0)
258 * f2fs bit operations
260 static const int bits_in_byte[256] = {
261 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
262 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
263 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
264 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
265 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
266 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
267 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
268 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
269 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
270 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
271 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
272 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
273 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
274 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
275 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
276 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
279 int get_bits_in_byte(unsigned char n)
281 return bits_in_byte[n];
284 int test_and_set_bit_le(u32 nr, u8 *addr)
289 mask = 1 << ((nr & 0x07));
290 retval = mask & *addr;
295 int test_and_clear_bit_le(u32 nr, u8 *addr)
300 mask = 1 << ((nr & 0x07));
301 retval = mask & *addr;
306 int test_bit_le(u32 nr, const u8 *addr)
308 return ((1 << (nr & 7)) & (addr[nr >> 3]));
311 int f2fs_test_bit(unsigned int nr, const char *p)
314 char *addr = (char *)p;
317 mask = 1 << (7 - (nr & 0x07));
318 return (mask & *addr) != 0;
321 int f2fs_set_bit(unsigned int nr, char *addr)
327 mask = 1 << (7 - (nr & 0x07));
333 int f2fs_clear_bit(unsigned int nr, char *addr)
339 mask = 1 << (7 - (nr & 0x07));
345 static inline u64 __ffs(u8 word)
349 if ((word & 0xf) == 0) {
353 if ((word & 0x3) == 0) {
357 if ((word & 0x1) == 0)
362 /* Copied from linux/lib/find_bit.c */
363 #define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1)))
365 static u64 _find_next_bit_le(const u8 *addr, u64 nbits, u64 start, char invert)
369 if (!nbits || start >= nbits)
372 tmp = addr[start / BITS_PER_BYTE] ^ invert;
374 /* Handle 1st word. */
375 tmp &= BITMAP_FIRST_BYTE_MASK(start);
376 start = round_down(start, BITS_PER_BYTE);
379 start += BITS_PER_BYTE;
383 tmp = addr[start / BITS_PER_BYTE] ^ invert;
386 return min(start + __ffs(tmp), nbits);
389 u64 find_next_bit_le(const u8 *addr, u64 size, u64 offset)
391 return _find_next_bit_le(addr, size, offset, 0);
395 u64 find_next_zero_bit_le(const u8 *addr, u64 size, u64 offset)
397 return _find_next_bit_le(addr, size, offset, 0xff);
401 * Hashing code adapted from ext3
403 #define DELTA 0x9E3779B9
405 static void TEA_transform(unsigned int buf[4], unsigned int const in[])
408 __u32 b0 = buf[0], b1 = buf[1];
409 __u32 a = in[0], b = in[1], c = in[2], d = in[3];
414 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
415 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
423 static void str2hashbuf(const unsigned char *msg, int len,
424 unsigned int *buf, int num)
429 pad = (__u32)len | ((__u32)len << 8);
435 for (i = 0; i < len; i++) {
438 val = msg[i] + (val << 8);
453 * Return hash value of directory entry
454 * @param name dentry name
455 * @param len name lenth
456 * @return return on success hash value, errno on failure
458 static f2fs_hash_t __f2fs_dentry_hash(const unsigned char *name, int len)/* Need update */
461 f2fs_hash_t f2fs_hash;
462 const unsigned char *p;
465 /* special hash codes for special dentries */
466 if ((len <= 2) && (name[0] == '.') &&
467 (name[1] == '.' || name[1] == '\0'))
470 /* Initialize the default seed for the hash checksum functions */
478 str2hashbuf(p, len, in, 4);
479 TEA_transform(buf, in);
487 f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
491 f2fs_hash_t f2fs_dentry_hash(int encoding, int casefolded,
492 const unsigned char *name, int len)
494 const struct f2fs_nls_table *table = f2fs_load_nls_table(encoding);
498 if (len && casefolded) {
499 buff = malloc(sizeof(char) * PATH_MAX);
502 dlen = table->ops->casefold(table, name, len, buff, PATH_MAX);
507 r = __f2fs_dentry_hash(buff, dlen);
513 return __f2fs_dentry_hash(name, len);
516 unsigned int addrs_per_inode(struct f2fs_inode *i)
518 unsigned int addrs = CUR_ADDRS_PER_INODE(i) - get_inline_xattr_addrs(i);
520 if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
521 !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
523 return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
526 unsigned int addrs_per_block(struct f2fs_inode *i)
528 if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
529 !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
530 return DEF_ADDRS_PER_BLOCK;
531 return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1 << i->i_log_cluster_size);
534 unsigned int f2fs_max_file_offset(struct f2fs_inode *i)
536 if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
537 !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
538 return le64_to_cpu(i->i_size);
539 return ALIGN_UP(le64_to_cpu(i->i_size), 1 << i->i_log_cluster_size);
545 #define CRCPOLY_LE 0xedb88320
547 uint32_t f2fs_cal_crc32(uint32_t crc, void *buf, int len)
550 unsigned char *p = (unsigned char *)buf;
553 for (i = 0; i < 8; i++)
554 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
559 int f2fs_crc_valid(uint32_t blk_crc, void *buf, int len)
561 uint32_t cal_crc = 0;
563 cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
565 if (cal_crc != blk_crc) {
566 DBG(0,"CRC validation failed: cal_crc = %u, "
567 "blk_crc = %u buff_size = 0x%x\n",
568 cal_crc, blk_crc, len);
574 __u32 f2fs_inode_chksum(struct f2fs_node *node)
576 struct f2fs_inode *ri = &node->i;
577 __le32 ino = node->footer.ino;
578 __le32 gen = ri->i_generation;
579 __u32 chksum, chksum_seed;
581 unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
582 unsigned int cs_size = sizeof(dummy_cs);
584 chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino,
586 chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen));
588 chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset);
589 chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size);
591 chksum = f2fs_cal_crc32(chksum, (__u8 *)ri + offset,
592 F2FS_BLKSIZE - offset);
596 __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *cp)
598 unsigned int chksum_ofs = le32_to_cpu(cp->checksum_offset);
601 chksum = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, chksum_ofs);
602 if (chksum_ofs < CP_CHKSUM_OFFSET) {
603 chksum_ofs += sizeof(chksum);
604 chksum = f2fs_cal_crc32(chksum, (__u8 *)cp + chksum_ofs,
605 F2FS_BLKSIZE - chksum_ofs);
610 int write_inode(struct f2fs_node *inode, u64 blkaddr)
612 if (c.feature & F2FS_FEATURE_INODE_CHKSUM)
613 inode->i.i_inode_checksum =
614 cpu_to_le32(f2fs_inode_chksum(inode));
615 return dev_write_block(inode, blkaddr);
619 * try to identify the root device
623 #if defined(_WIN32) || defined(WITH_ANDROID)
628 char buf[PATH_MAX + 1];
632 if (stat("/", &sb) == -1)
635 snprintf(buf, PATH_MAX, "/sys/dev/block/%u:%u/uevent",
636 major(sb.st_dev), minor(sb.st_dev));
638 fd = open(buf, O_RDONLY);
643 ret = lseek(fd, (off_t)0, SEEK_END);
644 (void)lseek(fd, (off_t)0, SEEK_SET);
651 uevent = malloc(ret + 1);
656 ret = read(fd, uevent, ret);
659 ptr = strstr(uevent, "DEVNAME");
663 ret = sscanf(ptr, "DEVNAME=%s\n", buf);
664 if (strlen(buf) == 0)
667 ret = strlen(buf) + 5;
668 rootdev = malloc(ret + 1);
673 snprintf(rootdev, ret + 1, "/dev/%s", buf);
686 void f2fs_init_configuration(void)
690 memset(&c, 0, sizeof(struct f2fs_configuration));
692 c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
693 c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
694 c.wanted_total_sectors = -1;
695 c.wanted_sector_size = -1;
697 c.preserve_limits = 1;
698 c.no_kernel_check = 1;
700 c.no_kernel_check = 0;
703 for (i = 0; i < MAX_DEVICES; i++) {
704 c.devices[i].fd = -1;
705 c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
706 c.devices[i].end_blkaddr = -1;
707 c.devices[i].zoned_model = F2FS_ZONED_NONE;
710 /* calculated by overprovision ratio */
719 c.s_encoding_flags = 0;
721 /* default root owner */
722 c.root_uid = getuid();
723 c.root_gid = getgid();
726 int f2fs_dev_is_writable(void)
728 return !c.ro || c.force;
731 #ifdef HAVE_SETMNTENT
732 static int is_mounted(const char *mpt, const char *device)
735 struct mntent *mnt = NULL;
737 file = setmntent(mpt, "r");
741 while ((mnt = getmntent(file)) != NULL) {
742 if (!strcmp(device, mnt->mnt_fsname)) {
744 if (hasmntopt(mnt, MNTOPT_RO))
755 int f2fs_dev_is_umounted(char *path)
763 char *rootdev_name = get_rootdev();
766 if (!strcmp(path, rootdev_name))
772 * try with /proc/mounts fist to detect RDONLY.
773 * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
776 ret = is_mounted("/proc/mounts", path);
778 MSG(0, "Info: Mounted device!\n");
782 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
784 #define MOUNTED _PATH_MOUNTED
786 ret = is_mounted(MOUNTED, path);
788 MSG(0, "Info: Mounted device!\n");
793 * If we are supposed to operate on the root device, then
794 * also check the mounts for '/dev/root', which sometimes
795 * functions as an alias for the root device.
799 ret = is_mounted("/proc/mounts", "/dev/root");
801 MSG(0, "Info: Mounted device!\n");
808 * If f2fs is umounted with -l, the process can still use
809 * the file system. In this case, we should not format.
811 st_buf = malloc(sizeof(struct stat));
814 if (stat(path, st_buf) == 0 && S_ISBLK(st_buf->st_mode)) {
815 int fd = open(path, O_RDONLY | O_EXCL);
819 } else if (errno == EBUSY) {
820 MSG(0, "\tError: In use by the system!\n");
830 int f2fs_devs_are_umounted(void)
834 for (i = 0; i < c.ndevs; i++)
835 if (f2fs_dev_is_umounted((char *)c.devices[i].path))
840 void get_kernel_version(__u8 *version)
843 for (i = 0; i < VERSION_NAME_LEN; i++) {
844 if (version[i] == '\n')
847 memset(version + i, 0, VERSION_LEN + 1 - i);
850 void get_kernel_uname_version(__u8 *version)
852 #ifdef HAVE_SYS_UTSNAME_H
855 memset(version, 0, VERSION_LEN);
859 #if defined(WITH_KERNEL_VERSION)
860 snprintf((char *)version,
861 VERSION_NAME_LEN, "%s %s", buf.release, buf.version);
863 snprintf((char *)version,
864 VERSION_NAME_LEN, "%s", buf.release);
867 memset(version, 0, VERSION_LEN);
871 #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
872 #define BLKGETSIZE _IO(0x12,96)
875 #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
876 #define BLKGETSIZE64 _IOR(0x12,114, size_t)
879 #if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
880 #define BLKSSZGET _IO(0x12,104)
883 #if defined(__APPLE__)
884 #include <sys/disk.h>
885 #define BLKGETSIZE DKIOCGETBLOCKCOUNT
886 #define BLKSSZGET DKIOCGETBLOCKCOUNT
887 #endif /* APPLE_DARWIN */
890 static int open_check_fs(char *path, int flag)
892 if (c.func != DUMP && (c.func != FSCK || c.fix_on || c.auto_fix))
895 /* allow to open ro */
896 return open(path, O_RDONLY | flag);
900 static int is_power_of_2(unsigned long n)
902 return (n != 0 && ((n & (n - 1)) == 0));
906 int get_device_info(int i)
909 uint32_t sector_size;
911 uint32_t total_sectors;
913 struct stat *stat_buf;
915 struct hd_geometry geom;
917 #if !defined(WITH_ANDROID) && defined(__linux__)
919 unsigned char reply_buffer[96] = {0};
920 unsigned char model_inq[6] = {MODELINQUIRY};
922 struct device_info *dev = c.devices + i;
925 fd = open(dev->path, O_RDWR | O_CREAT | O_BINARY, 0644);
927 fd = open_check_fs(dev->path, O_BINARY);
929 MSG(0, "\tError: Failed to open a sparse file!\n");
935 stat_buf = malloc(sizeof(struct stat));
938 if (!c.sparse_mode) {
939 if (stat(dev->path, stat_buf) < 0 ) {
940 MSG(0, "\tError: Failed to get the device stat!\n");
945 if (S_ISBLK(stat_buf->st_mode) &&
946 !c.force && c.func != DUMP && !c.dry_run) {
947 fd = open(dev->path, O_RDWR | O_EXCL);
949 fd = open_check_fs(dev->path, O_EXCL);
951 fd = open(dev->path, O_RDWR);
953 fd = open_check_fs(dev->path, 0);
957 MSG(0, "\tError: Failed to open the device!\n");
965 if (f2fs_init_sparse_file()) {
972 #if !defined(WITH_ANDROID) && defined(__linux__)
973 c.kd = open("/proc/version", O_RDONLY);
976 MSG(0, "Info: not exist /proc/version!\n");
982 dev->total_sectors = c.device_size / dev->sector_size;
983 } else if (S_ISREG(stat_buf->st_mode)) {
984 dev->total_sectors = stat_buf->st_size / dev->sector_size;
985 } else if (S_ISBLK(stat_buf->st_mode)) {
987 if (ioctl(fd, BLKSSZGET, §or_size) < 0)
988 MSG(0, "\tError: Using the default sector size\n");
989 else if (dev->sector_size < sector_size)
990 dev->sector_size = sector_size;
993 if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
994 MSG(0, "\tError: Cannot get the device size\n");
999 if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
1000 MSG(0, "\tError: Cannot get the device size\n");
1004 dev->total_sectors = total_sectors;
1006 dev->total_sectors /= dev->sector_size;
1010 if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
1013 c.start_sector = geom.start;
1019 #if !defined(WITH_ANDROID) && defined(__linux__)
1020 /* Send INQUIRY command */
1021 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
1022 io_hdr.interface_id = 'S';
1023 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
1024 io_hdr.dxfer_len = sizeof(reply_buffer);
1025 io_hdr.dxferp = reply_buffer;
1026 io_hdr.cmd_len = sizeof(model_inq);
1027 io_hdr.cmdp = model_inq;
1028 io_hdr.timeout = 1000;
1030 if (!ioctl(fd, SG_IO, &io_hdr)) {
1031 MSG(0, "Info: [%s] Disk Model: %.16s\n",
1032 dev->path, reply_buffer+16);
1036 MSG(0, "\tError: Volume type is not supported!!!\n");
1041 if (!c.sector_size) {
1042 c.sector_size = dev->sector_size;
1043 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1044 } else if (c.sector_size != c.devices[i].sector_size) {
1045 MSG(0, "\tError: Different sector sizes!!!\n");
1051 if (S_ISBLK(stat_buf->st_mode)) {
1052 if (f2fs_get_zoned_model(i) < 0) {
1058 if (dev->zoned_model != F2FS_ZONED_NONE) {
1060 /* Get the number of blocks per zones */
1061 if (f2fs_get_zone_blocks(i)) {
1062 MSG(0, "\tError: Failed to get number of blocks per zone\n");
1067 if (!is_power_of_2(dev->zone_size))
1068 MSG(0, "Info: zoned: zone size %" PRIu64 "u (not a power of 2)\n",
1072 * Check zone configuration: for the first disk of a
1073 * multi-device volume, conventional zones are needed.
1075 if (f2fs_check_zones(i)) {
1076 MSG(0, "\tError: Failed to check zone configuration\n");
1080 MSG(0, "Info: Host-%s zoned block device:\n",
1081 (dev->zoned_model == F2FS_ZONED_HA) ?
1082 "aware" : "managed");
1083 MSG(0, " %u zones, %" PRIu64 "u zone size(bytes), %u randomly writeable zones\n",
1084 dev->nr_zones, dev->zone_size,
1086 MSG(0, " %zu blocks per zone\n",
1089 if (c.conf_reserved_sections) {
1090 if (c.conf_reserved_sections < MIN_RSVD_SECS) {
1091 MSG(0, " Too small sections are reserved(%u secs)\n",
1092 c.conf_reserved_sections);
1093 c.conf_reserved_sections = MIN_RSVD_SECS;
1094 MSG(0, " It is operated as a minimum reserved sections(%u secs)\n",
1095 c.conf_reserved_sections);
1097 MSG(0, " %u sections are reserved\n",
1098 c.conf_reserved_sections);
1100 if (!c.overprovision) {
1101 c.overprovision = CONFIG_RSVD_DEFAULT_OP_RATIO;
1102 MSG(0, " Overprovision ratio is set to default(%.1lf%%)\n",
1108 /* adjust wanted_total_sectors */
1109 if (c.wanted_total_sectors != -1) {
1110 MSG(0, "Info: wanted sectors = %"PRIu64" (in %"PRIu64" bytes)\n",
1111 c.wanted_total_sectors, c.wanted_sector_size);
1112 if (c.wanted_sector_size == -1) {
1113 c.wanted_sector_size = dev->sector_size;
1114 } else if (dev->sector_size != c.wanted_sector_size) {
1115 c.wanted_total_sectors *= c.wanted_sector_size;
1116 c.wanted_total_sectors /= dev->sector_size;
1120 c.total_sectors += dev->total_sectors;
1127 #include "windows.h"
1128 #include "winioctl.h"
1130 #if (_WIN32_WINNT >= 0x0500)
1131 #define HAVE_GET_FILE_SIZE_EX 1
1134 static int win_get_device_size(const char *file, uint64_t *device_size)
1137 PARTITION_INFORMATION pi;
1140 #ifdef HAVE_GET_FILE_SIZE_EX
1141 LARGE_INTEGER filesize;
1144 #endif /* HAVE_GET_FILE_SIZE_EX */
1146 dev = CreateFile(file, GENERIC_READ,
1147 FILE_SHARE_READ | FILE_SHARE_WRITE ,
1148 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1150 if (dev == INVALID_HANDLE_VALUE)
1152 if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
1153 &pi, sizeof(PARTITION_INFORMATION),
1154 &pi, sizeof(PARTITION_INFORMATION),
1157 *device_size = pi.PartitionLength.QuadPart;
1159 } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1160 &gi, sizeof(DISK_GEOMETRY),
1161 &gi, sizeof(DISK_GEOMETRY),
1164 *device_size = gi.BytesPerSector *
1165 gi.SectorsPerTrack *
1166 gi.TracksPerCylinder *
1167 gi.Cylinders.QuadPart;
1169 #ifdef HAVE_GET_FILE_SIZE_EX
1170 } else if (GetFileSizeEx(dev, &filesize)) {
1171 *device_size = filesize.QuadPart;
1175 filesize = GetFileSize(dev, NULL);
1176 if (INVALID_FILE_SIZE != filesize)
1178 *device_size = filesize;
1180 #endif /* HAVE_GET_FILE_SIZE_EX */
1186 int get_device_info(int i)
1188 struct device_info *dev = c.devices + i;
1189 uint64_t device_size = 0;
1192 /* Block device target is not supported on Windows. */
1193 if (!c.sparse_mode) {
1194 if (win_get_device_size(dev->path, &device_size)) {
1195 MSG(0, "\tError: Failed to get device size!\n");
1199 device_size = c.device_size;
1201 if (c.sparse_mode) {
1202 fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1204 fd = open((char *)dev->path, O_RDWR | O_BINARY);
1207 MSG(0, "\tError: Failed to open the device!\n");
1211 dev->total_sectors = device_size / dev->sector_size;
1213 c.sector_size = dev->sector_size;
1214 c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
1215 c.total_sectors += dev->total_sectors;
1217 if (c.sparse_mode && f2fs_init_sparse_file())
1223 int f2fs_get_device_info(void)
1227 for (i = 0; i < c.ndevs; i++)
1228 if (get_device_info(i))
1233 int f2fs_get_f2fs_info(void)
1237 if (c.wanted_total_sectors < c.total_sectors) {
1238 MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
1239 c.total_sectors, c.sector_size);
1240 c.total_sectors = c.wanted_total_sectors;
1241 c.devices[0].total_sectors = c.total_sectors;
1243 if (c.total_sectors * c.sector_size >
1244 (uint64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
1245 MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
1250 * Check device types and determine the final volume operation mode:
1251 * - If all devices are regular block devices, default operation.
1252 * - If at least one HM device is found, operate in HM mode (BLKZONED
1253 * feature will be enabled by mkfs).
1254 * - If an HA device is found, let mkfs decide based on the -m option
1255 * setting by the user.
1257 c.zoned_model = F2FS_ZONED_NONE;
1258 for (i = 0; i < c.ndevs; i++) {
1259 switch (c.devices[i].zoned_model) {
1260 case F2FS_ZONED_NONE:
1263 c.zoned_model = F2FS_ZONED_HM;
1266 if (c.zoned_model != F2FS_ZONED_HM)
1267 c.zoned_model = F2FS_ZONED_HA;
1272 if (c.zoned_model != F2FS_ZONED_NONE) {
1275 * For zoned model, the zones sizes of all zoned devices must
1278 for (i = 0; i < c.ndevs; i++) {
1279 if (c.devices[i].zoned_model == F2FS_ZONED_NONE)
1281 if (c.zone_blocks &&
1282 c.zone_blocks != c.devices[i].zone_blocks) {
1283 MSG(0, "\tError: zones of different size are "
1287 c.zone_blocks = c.devices[i].zone_blocks;
1291 * Align sections to the device zone size and align F2FS zones
1292 * to the device zones. For F2FS_ZONED_HA model without the
1293 * BLKZONED feature set at format time, this is only an
1294 * optimization as sequential writes will not be enforced.
1296 c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
1297 c.secs_per_zone = 1;
1299 if(c.zoned_mode != 0) {
1300 MSG(0, "\n Error: %s may not be a zoned block device \n",
1306 c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
1311 MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
1312 MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
1313 MSG(0, "Info: sector size = %u\n", c.sector_size);
1314 MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
1315 c.total_sectors, (c.total_sectors *
1316 (c.sector_size >> 9)) >> 11);
1320 unsigned int calc_extra_isize(void)
1322 unsigned int size = offsetof(struct f2fs_inode, i_projid);
1324 if (c.feature & F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)
1325 size = offsetof(struct f2fs_inode, i_projid);
1326 if (c.feature & F2FS_FEATURE_PRJQUOTA)
1327 size = offsetof(struct f2fs_inode, i_inode_checksum);
1328 if (c.feature & F2FS_FEATURE_INODE_CHKSUM)
1329 size = offsetof(struct f2fs_inode, i_crtime);
1330 if (c.feature & F2FS_FEATURE_INODE_CRTIME)
1331 size = offsetof(struct f2fs_inode, i_compr_blocks);
1332 if (c.feature & F2FS_FEATURE_COMPRESSION)
1333 size = offsetof(struct f2fs_inode, i_extra_end);
1335 return size - F2FS_EXTRA_ISIZE_OFFSET;
1338 #define ARRAY_SIZE(array) \
1339 (sizeof(array) / sizeof(array[0]))
1341 static const struct {
1343 __u16 encoding_magic;
1344 __u16 default_flags;
1346 } f2fs_encoding_map[] = {
1348 .encoding_magic = F2FS_ENC_UTF8_12_1,
1354 static const struct enc_flags {
1357 } encoding_flags[] = {
1358 { F2FS_ENC_STRICT_MODE_FL, "strict" },
1361 /* Return a positive number < 0xff indicating the encoding magic number
1362 * or a negative value indicating error. */
1363 int f2fs_str2encoding(const char *string)
1367 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1368 if (!strcmp(string, f2fs_encoding_map[i].name))
1369 return f2fs_encoding_map[i].encoding_magic;
1374 char *f2fs_encoding2str(const int encoding)
1378 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1379 if (f2fs_encoding_map[i].encoding_magic == encoding)
1380 return f2fs_encoding_map[i].name;
1385 int f2fs_get_encoding_flags(int encoding)
1389 for (i = 0 ; i < ARRAY_SIZE(f2fs_encoding_map); i++)
1390 if (f2fs_encoding_map[i].encoding_magic == encoding)
1391 return f2fs_encoding_map[encoding].default_flags;
1396 int f2fs_str2encoding_flags(char **param, __u16 *flags)
1398 char *f = strtok(*param, ",");
1399 const struct enc_flags *fl;
1404 if (!strncmp("no", f, 2)) {
1409 for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) {
1410 fl = &encoding_flags[i];
1411 if (!strcmp(fl->param, f)) {
1413 MSG(0, "Sub %s\n", fl->param);
1414 *flags &= ~fl->flag;
1416 MSG(0, "Add %s\n", fl->param);
1426 f = strtok(NULL, ":");