1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
/*
* Copyright (C) 2013 Alejandro Martinez Ruiz <alex@nowcomputing.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License
*/
#include <stddef.h>
#include <string.h>
#include "superblocks.h"
#define F2FS_MAGIC "\x10\x20\xF5\xF2"
#define F2FS_MAGIC_OFF 0
#define F2FS_UUID_SIZE 16
#define F2FS_LABEL_SIZE 512
#define F2FS_SB1_OFF 0x400
#define F2FS_SB1_KBOFF (F2FS_SB1_OFF >> 10)
#define F2FS_SB2_OFF 0x1400
#define F2FS_SB2_KBOFF (F2FS_SB2_OFF >> 10)
struct f2fs_super_block { /* According to version 1.1 */
/* 0x00 */ uint32_t magic; /* Magic Number */
/* 0x04 */ uint16_t major_ver; /* Major Version */
/* 0x06 */ uint16_t minor_ver; /* Minor Version */
/* 0x08 */ uint32_t log_sectorsize; /* log2 sector size in bytes */
/* 0x0C */ uint32_t log_sectors_per_block; /* log2 # of sectors per block */
/* 0x10 */ uint32_t log_blocksize; /* log2 block size in bytes */
/* 0x14 */ uint32_t log_blocks_per_seg; /* log2 # of blocks per segment */
/* 0x18 */ uint32_t segs_per_sec; /* # of segments per section */
/* 0x1C */ uint32_t secs_per_zone; /* # of sections per zone */
/* 0x20 */ uint32_t checksum_offset; /* checksum offset inside super block */
/* 0x24 */ uint64_t block_count; /* total # of user blocks */
/* 0x2C */ uint32_t section_count; /* total # of sections */
/* 0x30 */ uint32_t segment_count; /* total # of segments */
/* 0x34 */ uint32_t segment_count_ckpt; /* # of segments for checkpoint */
/* 0x38 */ uint32_t segment_count_sit; /* # of segments for SIT */
/* 0x3C */ uint32_t segment_count_nat; /* # of segments for NAT */
/* 0x40 */ uint32_t segment_count_ssa; /* # of segments for SSA */
/* 0x44 */ uint32_t segment_count_main; /* # of segments for main area */
/* 0x48 */ uint32_t segment0_blkaddr; /* start block address of segment 0 */
/* 0x4C */ uint32_t cp_blkaddr; /* start block address of checkpoint */
/* 0x50 */ uint32_t sit_blkaddr; /* start block address of SIT */
/* 0x54 */ uint32_t nat_blkaddr; /* start block address of NAT */
/* 0x58 */ uint32_t ssa_blkaddr; /* start block address of SSA */
/* 0x5C */ uint32_t main_blkaddr; /* start block address of main area */
/* 0x60 */ uint32_t root_ino; /* root inode number */
/* 0x64 */ uint32_t node_ino; /* node inode number */
/* 0x68 */ uint32_t meta_ino; /* meta inode number */
/* 0x6C */ uint8_t uuid[F2FS_UUID_SIZE]; /* 128-bit uuid for volume */
/* 0x7C */ uint16_t volume_name[F2FS_LABEL_SIZE]; /* volume name */
#if 0
/* 0x47C */ uint32_t extension_count; /* # of extensions below */
/* 0x480 */ uint8_t extension_list[64][8]; /* extension array */
#endif
} __attribute__((packed));
static int probe_f2fs(blkid_probe pr, const struct blkid_idmag *mag)
{
struct f2fs_super_block *sb;
uint16_t vermaj, vermin;
sb = blkid_probe_get_sb(pr, mag, struct f2fs_super_block);
if (!sb)
return errno ? -errno : 1;
vermaj = le16_to_cpu(sb->major_ver);
vermin = le16_to_cpu(sb->minor_ver);
/* For version 1.0 we cannot know the correct sb structure */
if (vermaj == 1 && vermin == 0)
return 0;
if (*((unsigned char *) sb->volume_name))
blkid_probe_set_utf8label(pr, (unsigned char *) sb->volume_name,
sizeof(sb->volume_name),
UL_ENCODE_UTF16LE);
blkid_probe_set_uuid(pr, sb->uuid);
blkid_probe_sprintf_version(pr, "%u.%u", vermaj, vermin);
if (le32_to_cpu(sb->log_blocksize) < 32)
blkid_probe_set_block_size(pr, 1U << le32_to_cpu(sb->log_blocksize));
return 0;
}
const struct blkid_idinfo f2fs_idinfo =
{
.name = "f2fs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_f2fs,
.magics =
{
{
.magic = F2FS_MAGIC,
.len = 4,
.kboff = F2FS_SB1_KBOFF,
.sboff = F2FS_MAGIC_OFF
},
{ NULL }
}
};
|