2 * Copyright (C) 1999 by Andries Brouwer
3 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4 * Copyright (C) 2001 by Andreas Dilger
5 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
7 * Copyright (C) 2013 Eric Sandeen <sandeen@redhat.com>
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
21 #include "superblocks.h"
23 struct xfs_super_block
{
24 uint32_t sb_magicnum
; /* magic number == XFS_SB_MAGIC */
25 uint32_t sb_blocksize
; /* logical block size, bytes */
26 uint64_t sb_dblocks
; /* number of data blocks */
27 uint64_t sb_rblocks
; /* number of realtime blocks */
28 uint64_t sb_rextents
; /* number of realtime extents */
29 unsigned char sb_uuid
[16]; /* file system unique id */
30 uint64_t sb_logstart
; /* starting block of log if internal */
31 uint64_t sb_rootino
; /* root inode number */
32 uint64_t sb_rbmino
; /* bitmap inode for realtime extents */
33 uint64_t sb_rsumino
; /* summary inode for rt bitmap */
34 uint32_t sb_rextsize
; /* realtime extent size, blocks */
35 uint32_t sb_agblocks
; /* size of an allocation group */
36 uint32_t sb_agcount
; /* number of allocation groups */
37 uint32_t sb_rbmblocks
; /* number of rt bitmap blocks */
38 uint32_t sb_logblocks
; /* number of log blocks */
40 uint16_t sb_versionnum
; /* header version == XFS_SB_VERSION */
41 uint16_t sb_sectsize
; /* volume sector size, bytes */
42 uint16_t sb_inodesize
; /* inode size, bytes */
43 uint16_t sb_inopblock
; /* inodes per block */
44 char sb_fname
[12]; /* file system name */
45 uint8_t sb_blocklog
; /* log2 of sb_blocksize */
46 uint8_t sb_sectlog
; /* log2 of sb_sectsize */
47 uint8_t sb_inodelog
; /* log2 of sb_inodesize */
48 uint8_t sb_inopblog
; /* log2 of sb_inopblock */
49 uint8_t sb_agblklog
; /* log2 of sb_agblocks (rounded up) */
50 uint8_t sb_rextslog
; /* log2 of sb_rextents */
51 uint8_t sb_inprogress
; /* mkfs is in progress, don't mount */
52 uint8_t sb_imax_pct
; /* max % of fs for inode space */
54 uint64_t sb_icount
; /* allocated inodes */
55 uint64_t sb_ifree
; /* free inodes */
56 uint64_t sb_fdblocks
; /* free data blocks */
57 uint64_t sb_frextents
; /* free realtime extents */
59 /* this is not all... but enough for libblkid */
61 } __attribute__((packed
));
63 #define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */
64 #define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */
65 #define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG)
66 #define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG)
67 #define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */
68 #define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */
69 #define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG)
70 #define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG)
72 #define XFS_DINODE_MIN_LOG 8
73 #define XFS_DINODE_MAX_LOG 11
74 #define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG)
75 #define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG)
77 #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */
78 #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */
79 #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */
81 #define XFS_MIN_AG_BLOCKS 64
82 #define XFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks)
83 #define XFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) * \
84 (s)->sb_agblocks + XFS_MIN_AG_BLOCKS)
87 static void sb_from_disk(struct xfs_super_block
*from
,
88 struct xfs_super_block
*to
)
91 to
->sb_magicnum
= be32_to_cpu(from
->sb_magicnum
);
92 to
->sb_blocksize
= be32_to_cpu(from
->sb_blocksize
);
93 to
->sb_dblocks
= be64_to_cpu(from
->sb_dblocks
);
94 to
->sb_rblocks
= be64_to_cpu(from
->sb_rblocks
);
95 to
->sb_rextents
= be64_to_cpu(from
->sb_rextents
);
96 to
->sb_logstart
= be64_to_cpu(from
->sb_logstart
);
97 to
->sb_rootino
= be64_to_cpu(from
->sb_rootino
);
98 to
->sb_rbmino
= be64_to_cpu(from
->sb_rbmino
);
99 to
->sb_rsumino
= be64_to_cpu(from
->sb_rsumino
);
100 to
->sb_rextsize
= be32_to_cpu(from
->sb_rextsize
);
101 to
->sb_agblocks
= be32_to_cpu(from
->sb_agblocks
);
102 to
->sb_agcount
= be32_to_cpu(from
->sb_agcount
);
103 to
->sb_rbmblocks
= be32_to_cpu(from
->sb_rbmblocks
);
104 to
->sb_logblocks
= be32_to_cpu(from
->sb_logblocks
);
105 to
->sb_versionnum
= be16_to_cpu(from
->sb_versionnum
);
106 to
->sb_sectsize
= be16_to_cpu(from
->sb_sectsize
);
107 to
->sb_inodesize
= be16_to_cpu(from
->sb_inodesize
);
108 to
->sb_inopblock
= be16_to_cpu(from
->sb_inopblock
);
109 to
->sb_blocklog
= from
->sb_blocklog
;
110 to
->sb_sectlog
= from
->sb_sectlog
;
111 to
->sb_inodelog
= from
->sb_inodelog
;
112 to
->sb_inopblog
= from
->sb_inopblog
;
113 to
->sb_agblklog
= from
->sb_agblklog
;
114 to
->sb_rextslog
= from
->sb_rextslog
;
115 to
->sb_inprogress
= from
->sb_inprogress
;
116 to
->sb_imax_pct
= from
->sb_imax_pct
;
117 to
->sb_icount
= be64_to_cpu(from
->sb_icount
);
118 to
->sb_ifree
= be64_to_cpu(from
->sb_ifree
);
119 to
->sb_fdblocks
= be64_to_cpu(from
->sb_fdblocks
);
120 to
->sb_frextents
= be64_to_cpu(from
->sb_frextents
);
123 static int xfs_verify_sb(struct xfs_super_block
*ondisk
)
125 struct xfs_super_block sb
, *sbp
= &sb
;
127 /* beXX_to_cpu(), but don't convert UUID and fsname! */
128 sb_from_disk(ondisk
, sbp
);
130 /* sanity checks, we don't want to rely on magic string only */
131 if (sbp
->sb_agcount
<= 0 ||
132 sbp
->sb_sectsize
< XFS_MIN_SECTORSIZE
||
133 sbp
->sb_sectsize
> XFS_MAX_SECTORSIZE
||
134 sbp
->sb_sectlog
< XFS_MIN_SECTORSIZE_LOG
||
135 sbp
->sb_sectlog
> XFS_MAX_SECTORSIZE_LOG
||
136 sbp
->sb_sectsize
!= (1 << sbp
->sb_sectlog
) ||
137 sbp
->sb_blocksize
< XFS_MIN_BLOCKSIZE
||
138 sbp
->sb_blocksize
> XFS_MAX_BLOCKSIZE
||
139 sbp
->sb_blocklog
< XFS_MIN_BLOCKSIZE_LOG
||
140 sbp
->sb_blocklog
> XFS_MAX_BLOCKSIZE_LOG
||
141 sbp
->sb_blocksize
!= (1ULL << sbp
->sb_blocklog
) ||
142 sbp
->sb_inodesize
< XFS_DINODE_MIN_SIZE
||
143 sbp
->sb_inodesize
> XFS_DINODE_MAX_SIZE
||
144 sbp
->sb_inodelog
< XFS_DINODE_MIN_LOG
||
145 sbp
->sb_inodelog
> XFS_DINODE_MAX_LOG
||
146 sbp
->sb_inodesize
!= (1 << sbp
->sb_inodelog
) ||
147 (sbp
->sb_blocklog
- sbp
->sb_inodelog
!= sbp
->sb_inopblog
) ||
148 (sbp
->sb_rextsize
* sbp
->sb_blocksize
> XFS_MAX_RTEXTSIZE
) ||
149 (sbp
->sb_rextsize
* sbp
->sb_blocksize
< XFS_MIN_RTEXTSIZE
) ||
150 (sbp
->sb_imax_pct
> 100 /* zero sb_imax_pct is valid */) ||
151 sbp
->sb_dblocks
== 0 ||
152 sbp
->sb_dblocks
> XFS_MAX_DBLOCKS(sbp
) ||
153 sbp
->sb_dblocks
< XFS_MIN_DBLOCKS(sbp
))
156 /* TODO: version 5 has also checksum CRC32, maybe we can check it too */
161 static int probe_xfs(blkid_probe pr
, const struct blkid_idmag
*mag
)
163 struct xfs_super_block
*xs
;
165 xs
= blkid_probe_get_sb(pr
, mag
, struct xfs_super_block
);
167 return errno
? -errno
: 1;
169 if (!xfs_verify_sb(xs
))
172 if (*xs
->sb_fname
!= '\0')
173 blkid_probe_set_label(pr
, (unsigned char *) xs
->sb_fname
,
174 sizeof(xs
->sb_fname
));
175 blkid_probe_set_uuid(pr
, xs
->sb_uuid
);
176 blkid_probe_set_block_size(pr
, xs
->sb_sectsize
* 256);
180 const struct blkid_idinfo xfs_idinfo
=
183 .usage
= BLKID_USAGE_FILESYSTEM
,
184 .probefunc
= probe_xfs
,
187 { .magic
= "XFSB", .len
= 4 },
192 struct xlog_rec_header
{
194 uint32_t h_dummy1
[1];
197 uint32_t h_dummy2
[71];
199 unsigned char h_uuid
[16];
200 } __attribute__((packed
));
202 #define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe
205 * For very small filesystems, the minimum log size
206 * can be smaller, but that seems vanishingly unlikely
207 * when used with an external log (which is used for
208 * performance reasons; tiny conflicts with that goal).
210 #define XFS_MIN_LOG_BYTES (10 * 1024 * 1024)
212 #define XLOG_FMT_LINUX_LE 1
213 #define XLOG_FMT_LINUX_BE 2
214 #define XLOG_FMT_IRIX_BE 3
216 #define XLOG_VERSION_1 1
217 #define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */
218 #define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2)
220 static int xlog_valid_rec_header(struct xlog_rec_header
*rhead
)
224 if (rhead
->h_magicno
!= cpu_to_be32(XLOG_HEADER_MAGIC_NUM
))
227 if (!rhead
->h_version
||
228 (be32_to_cpu(rhead
->h_version
) & (~XLOG_VERSION_OKBITS
)))
231 /* LR body must have data or it wouldn't have been written */
232 hlen
= be32_to_cpu(rhead
->h_len
);
233 if (hlen
<= 0 || hlen
> INT_MAX
)
236 if (rhead
->h_fmt
!= cpu_to_be32(XLOG_FMT_LINUX_LE
) &&
237 rhead
->h_fmt
!= cpu_to_be32(XLOG_FMT_LINUX_BE
) &&
238 rhead
->h_fmt
!= cpu_to_be32(XLOG_FMT_IRIX_BE
))
244 /* xlog record header will be in some sector in the first 256k */
245 static int probe_xfs_log(blkid_probe pr
,
246 const struct blkid_idmag
*mag
__attribute__((__unused__
)))
249 struct xlog_rec_header
*rhead
;
252 buf
= blkid_probe_get_buffer(pr
, 0, 256*1024);
254 return errno
? -errno
: 1;
256 if (memcmp(buf
, "XFSB", 4) == 0)
257 return 1; /* this is regular XFS, ignore */
259 /* check the first 512 512-byte sectors */
260 for (i
= 0; i
< 512; i
++) {
261 rhead
= (struct xlog_rec_header
*)&buf
[i
*512];
263 if (xlog_valid_rec_header(rhead
)) {
264 blkid_probe_set_uuid_as(pr
, rhead
->h_uuid
, "LOGUUID");
266 if (blkid_probe_set_magic(pr
, i
* 512,
267 sizeof(rhead
->h_magicno
),
268 (unsigned char *) &rhead
->h_magicno
))
278 const struct blkid_idinfo xfs_log_idinfo
=
280 .name
= "xfs_external_log",
281 .usage
= BLKID_USAGE_OTHER
,
282 .probefunc
= probe_xfs_log
,
283 .magics
= BLKID_NONE_MAGIC
,
284 .minsz
= XFS_MIN_LOG_BYTES
,