/src/util-linux/libblkid/src/superblocks/nilfs.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2010 by Jiro SEKIBA <jir@unicus.jp> |
3 | | * |
4 | | * This file may be redistributed under the terms of the |
5 | | * GNU Lesser General Public License |
6 | | */ |
7 | | #include <stddef.h> |
8 | | #include <string.h> |
9 | | |
10 | | #include "superblocks.h" |
11 | | #include "crc32.h" |
12 | | |
13 | | struct nilfs_super_block { |
14 | | uint32_t s_rev_level; |
15 | | uint16_t s_minor_rev_level; |
16 | | uint16_t s_magic; |
17 | | |
18 | | uint16_t s_bytes; |
19 | | |
20 | | uint16_t s_flags; |
21 | | uint32_t s_crc_seed; |
22 | | uint32_t s_sum; |
23 | | |
24 | | uint32_t s_log_block_size; |
25 | | |
26 | | uint64_t s_nsegments; |
27 | | uint64_t s_dev_size; |
28 | | uint64_t s_first_data_block; |
29 | | uint32_t s_blocks_per_segment; |
30 | | uint32_t s_r_segments_percentage; |
31 | | |
32 | | uint64_t s_last_cno; |
33 | | uint64_t s_last_pseg; |
34 | | uint64_t s_last_seq; |
35 | | uint64_t s_free_blocks_count; |
36 | | |
37 | | uint64_t s_ctime; |
38 | | |
39 | | uint64_t s_mtime; |
40 | | uint64_t s_wtime; |
41 | | uint16_t s_mnt_count; |
42 | | uint16_t s_max_mnt_count; |
43 | | uint16_t s_state; |
44 | | uint16_t s_errors; |
45 | | uint64_t s_lastcheck; |
46 | | |
47 | | uint32_t s_checkinterval; |
48 | | uint32_t s_creator_os; |
49 | | uint16_t s_def_resuid; |
50 | | uint16_t s_def_resgid; |
51 | | uint32_t s_first_ino; |
52 | | |
53 | | uint16_t s_inode_size; |
54 | | uint16_t s_dat_entry_size; |
55 | | uint16_t s_checkpoint_size; |
56 | | uint16_t s_segment_usage_size; |
57 | | |
58 | | uint8_t s_uuid[16]; |
59 | | char s_volume_name[80]; |
60 | | |
61 | | uint32_t s_c_interval; |
62 | | uint32_t s_c_block_max; |
63 | | uint32_t s_reserved[192]; |
64 | | } __attribute__((__packed__)); |
65 | | |
66 | 11.7k | #define NILFS_SB_MAGIC 0x3434 |
67 | 5.89k | #define NILFS_SB_OFFSET 0x400 |
68 | 5.88k | #define NILFS_SBB_OFFSET(_sz) ((((_sz) / 0x200) - 8) * 0x200) |
69 | | |
70 | | static int nilfs_valid_sb(blkid_probe pr, struct nilfs_super_block *sb, int is_bak) |
71 | 11.7k | { |
72 | 11.7k | static unsigned char sum[4]; |
73 | 11.7k | const int sumoff = offsetof(struct nilfs_super_block, s_sum); |
74 | 11.7k | size_t bytes; |
75 | 11.7k | const size_t crc_start = sumoff + 4; |
76 | 11.7k | uint32_t crc; |
77 | | |
78 | 11.7k | if (!sb || le16_to_cpu(sb->s_magic) != NILFS_SB_MAGIC) |
79 | 11.7k | return 0; |
80 | | |
81 | 25 | if (is_bak && blkid_probe_is_wholedisk(pr) && |
82 | 0 | sb->s_dev_size != pr->size) |
83 | 0 | return 0; |
84 | | |
85 | 25 | bytes = le16_to_cpu(sb->s_bytes); |
86 | | /* ensure that no underrun can happen in the length parameter |
87 | | * of the crc32 call or more data are processed than read into |
88 | | * sb */ |
89 | 25 | if (bytes < crc_start || bytes > sizeof(struct nilfs_super_block)) |
90 | 15 | return 0; |
91 | | |
92 | 10 | crc = ul_crc32(le32_to_cpu(sb->s_crc_seed), (unsigned char *)sb, sumoff); |
93 | 10 | crc = ul_crc32(crc, sum, 4); |
94 | 10 | crc = ul_crc32(crc, (unsigned char *)sb + crc_start, bytes - crc_start); |
95 | | |
96 | 10 | return blkid_probe_verify_csum(pr, crc, le32_to_cpu(sb->s_sum)); |
97 | 25 | } |
98 | | |
99 | | static int probe_nilfs2(blkid_probe pr, |
100 | | const struct blkid_idmag *mag __attribute__((__unused__))) |
101 | 5.88k | { |
102 | 5.88k | struct nilfs_super_block *sb, *sbp, *sbb; |
103 | 5.88k | int valid[2], swp = 0; |
104 | 5.88k | uint64_t magoff; |
105 | | |
106 | | /* primary */ |
107 | 5.88k | sbp = (struct nilfs_super_block *) blkid_probe_get_buffer( |
108 | 5.88k | pr, NILFS_SB_OFFSET, sizeof(struct nilfs_super_block)); |
109 | 5.88k | if (!sbp) |
110 | 0 | return errno ? -errno : 1; |
111 | | |
112 | 5.88k | valid[0] = nilfs_valid_sb(pr, sbp, 0); |
113 | | |
114 | | |
115 | | /* backup */ |
116 | 5.88k | sbb = (struct nilfs_super_block *) blkid_probe_get_buffer( |
117 | 5.88k | pr, NILFS_SBB_OFFSET(pr->size), sizeof(struct nilfs_super_block)); |
118 | 5.88k | if (!sbb) { |
119 | 0 | valid[1] = 0; |
120 | | |
121 | | /* If the primary block is valid then continue and ignore also |
122 | | * I/O errors for backup block. Note the this is probably CD |
123 | | * where I/O errors and the end of the disk/session are "normal". |
124 | | */ |
125 | 0 | if (!valid[0]) |
126 | 0 | return errno ? -errno : 1; |
127 | 0 | } else |
128 | 5.88k | valid[1] = nilfs_valid_sb(pr, sbb, 1); |
129 | | |
130 | | |
131 | | /* |
132 | | * Compare two super blocks and set 1 in swp if the secondary |
133 | | * super block is valid and newer. Otherwise, set 0 in swp. |
134 | | */ |
135 | 5.88k | if (!valid[0] && !valid[1]) |
136 | 5.88k | return 1; |
137 | | |
138 | 3 | swp = valid[1] && (!valid[0] || |
139 | 0 | le64_to_cpu(sbp->s_last_cno) > |
140 | 0 | le64_to_cpu(sbb->s_last_cno)); |
141 | 3 | sb = swp ? sbb : sbp; |
142 | | |
143 | 3 | DBG(LOWPROBE, ul_debug("nilfs2: primary=%d, backup=%d, swap=%d", |
144 | 3 | valid[0], valid[1], swp)); |
145 | | |
146 | 3 | if (*(sb->s_volume_name) != '\0') |
147 | 2 | blkid_probe_set_label(pr, (unsigned char *) sb->s_volume_name, |
148 | 2 | sizeof(sb->s_volume_name)); |
149 | | |
150 | 3 | blkid_probe_set_uuid(pr, sb->s_uuid); |
151 | 3 | blkid_probe_sprintf_version(pr, "%u", le32_to_cpu(sb->s_rev_level)); |
152 | | |
153 | 3 | magoff = swp ? NILFS_SBB_OFFSET(pr->size) : NILFS_SB_OFFSET; |
154 | 3 | magoff += offsetof(struct nilfs_super_block, s_magic); |
155 | | |
156 | 3 | if (blkid_probe_set_magic(pr, magoff, sizeof(sb->s_magic), |
157 | 3 | (unsigned char *) &sb->s_magic)) |
158 | 0 | return 1; |
159 | | |
160 | 3 | if (le32_to_cpu(sb->s_log_block_size) < 32){ |
161 | 3 | blkid_probe_set_fsblocksize(pr, 1024U << le32_to_cpu(sb->s_log_block_size)); |
162 | 3 | blkid_probe_set_block_size(pr, 1024U << le32_to_cpu(sb->s_log_block_size)); |
163 | 3 | } |
164 | | |
165 | 3 | return 0; |
166 | 3 | } |
167 | | |
168 | | const struct blkid_idinfo nilfs2_idinfo = |
169 | | { |
170 | | .name = "nilfs2", |
171 | | .usage = BLKID_USAGE_FILESYSTEM, |
172 | | .probefunc = probe_nilfs2, |
173 | | /* default min.size is 128MiB, but 1MiB for "mkfs.nilfs2 -b 1024 -B 16" */ |
174 | | .minsz = (1024 * 1024), |
175 | | .magics = BLKID_NONE_MAGIC |
176 | | }; |