1 /*
2 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
6 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <stdint.h>
12
13 #include "superblocks.h"
14
15 /* Common gfs/gfs2 constants: */
16 #define GFS_LOCKNAME_LEN 64
17
18 /* gfs1 constants: */
19 #define GFS_FORMAT_FS 1309
20 #define GFS_FORMAT_MULTI 1401
21
22 struct gfs2_meta_header {
23 uint32_t mh_magic;
24 uint32_t mh_type;
25 uint64_t __pad0; /* Was generation number in gfs1 */
26 uint32_t mh_format;
27 uint32_t __pad1; /* Was incarnation number in gfs1 */
28 };
29
30 struct gfs2_inum {
31 uint64_t no_formal_ino;
32 uint64_t no_addr;
33 };
34
35 struct gfs2_sb {
36 struct gfs2_meta_header sb_header;
37
38 uint32_t sb_fs_format;
39 uint32_t sb_multihost_format;
40 uint32_t __pad0; /* Was superblock flags in gfs1 */
41
42 uint32_t sb_bsize;
43 uint32_t sb_bsize_shift;
44 uint32_t __pad1; /* Was journal segment size in gfs1 */
45
46 struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */
47 struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */
48 struct gfs2_inum sb_root_dir;
49
50 char sb_lockproto[GFS_LOCKNAME_LEN];
51 char sb_locktable[GFS_LOCKNAME_LEN];
52
53 struct gfs2_inum __pad3; /* Was quota inode in gfs1 */
54 struct gfs2_inum __pad4; /* Was license inode in gfs1 */
55 uint8_t sb_uuid[16]; /* The UUID maybe 0 for backwards compat */
56 } __attribute__((packed));
57
58
59
60 static int probe_gfs(blkid_probe pr, const struct blkid_idmag *mag)
61 {
62 struct gfs2_sb *sbd;
63
64 sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb);
65 if (!sbd)
66 return errno ? -errno : 1;
67
68 if (be32_to_cpu(sbd->sb_fs_format) == GFS_FORMAT_FS &&
69 be32_to_cpu(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
70 {
71 if (*sbd->sb_locktable)
72 blkid_probe_set_label(pr,
73 (unsigned char *) sbd->sb_locktable,
74 sizeof(sbd->sb_locktable));
75
76 blkid_probe_set_uuid(pr, sbd->sb_uuid);
77 return 0;
78 }
79
80 return 1;
81 }
82
83 static inline int gfs2_format_is_valid(uint32_t format)
84 {
85 return (format >= 1800 && format < 1900);
86 }
87 static inline int gfs2_multiformat_is_valid(uint32_t multi)
88 {
89 return (multi >= 1900 && multi < 2000);
90 }
91
92 static int probe_gfs2(blkid_probe pr, const struct blkid_idmag *mag)
93 {
94 struct gfs2_sb *sbd;
95
96 sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb);
97 if (!sbd)
98 return errno ? -errno : 1;
99
100 if (gfs2_format_is_valid(be32_to_cpu(sbd->sb_fs_format)) &&
101 gfs2_multiformat_is_valid(be32_to_cpu(sbd->sb_multihost_format)))
102 {
103 if (*sbd->sb_locktable)
104 blkid_probe_set_label(pr,
105 (unsigned char *) sbd->sb_locktable,
106 sizeof(sbd->sb_locktable));
107 blkid_probe_set_uuid(pr, sbd->sb_uuid);
108 blkid_probe_set_version(pr, "1");
109 blkid_probe_set_fsblocksize(pr, be32_to_cpu(sbd->sb_bsize));
110 blkid_probe_set_block_size(pr, be32_to_cpu(sbd->sb_bsize));
111 return 0;
112 }
113 return 1;
114 }
115
116 const struct blkid_idinfo gfs_idinfo =
117 {
118 .name = "gfs",
119 .usage = BLKID_USAGE_FILESYSTEM,
120 .probefunc = probe_gfs,
121 .minsz = 32 * 1024 * 1024, /* minimal size of GFS journal */
122 .magics =
123 {
124 { .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 },
125 { NULL }
126 }
127 };
128
129 const struct blkid_idinfo gfs2_idinfo =
130 {
131 .name = "gfs2",
132 .usage = BLKID_USAGE_FILESYSTEM,
133 .probefunc = probe_gfs2,
134 .minsz = 32 * 1024 * 1024, /* minimal size of GFS journal */
135 .magics =
136 {
137 { .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 },
138 { NULL }
139 }
140 };
141