(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
xfs.c
       1  /*
       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>
       8   *
       9   * This file may be redistributed under the terms of the
      10   * GNU Lesser General Public License.
      11   */
      12  
      13  #include <stdio.h>
      14  #include <stdlib.h>
      15  #include <unistd.h>
      16  #include <string.h>
      17  #include <errno.h>
      18  #include <ctype.h>
      19  #include <stdint.h>
      20  
      21  #include "superblocks.h"
      22  #include "crc32c.h"
      23  
      24  struct xfs_super_block {
      25  	uint32_t	sb_magicnum;	/* magic number == XFS_SB_MAGIC */
      26  	uint32_t	sb_blocksize;	/* logical block size, bytes */
      27  	uint64_t	sb_dblocks;	/* number of data blocks */
      28  	uint64_t	sb_rblocks;	/* number of realtime blocks */
      29  	uint64_t	sb_rextents;	/* number of realtime extents */
      30  	unsigned char	sb_uuid[16];	/* file system unique id */
      31  	uint64_t	sb_logstart;	/* starting block of log if internal */
      32  	uint64_t	sb_rootino;	/* root inode number */
      33  	uint64_t	sb_rbmino;	/* bitmap inode for realtime extents */
      34  	uint64_t	sb_rsumino;	/* summary inode for rt bitmap */
      35  	uint32_t	sb_rextsize;	/* realtime extent size, blocks */
      36  	uint32_t	sb_agblocks;	/* size of an allocation group */
      37  	uint32_t	sb_agcount;	/* number of allocation groups */
      38  	uint32_t	sb_rbmblocks;	/* number of rt bitmap blocks */
      39  	uint32_t	sb_logblocks;	/* number of log blocks */
      40  
      41  	uint16_t	sb_versionnum;	/* header version == XFS_SB_VERSION */
      42  	uint16_t	sb_sectsize;	/* volume sector size, bytes */
      43  	uint16_t	sb_inodesize;	/* inode size, bytes */
      44  	uint16_t	sb_inopblock;	/* inodes per block */
      45  	char		sb_fname[12];	/* file system name */
      46  	uint8_t		sb_blocklog;	/* log2 of sb_blocksize */
      47  	uint8_t		sb_sectlog;	/* log2 of sb_sectsize */
      48  	uint8_t		sb_inodelog;	/* log2 of sb_inodesize */
      49  	uint8_t		sb_inopblog;	/* log2 of sb_inopblock */
      50  	uint8_t		sb_agblklog;	/* log2 of sb_agblocks (rounded up) */
      51  	uint8_t		sb_rextslog;	/* log2 of sb_rextents */
      52  	uint8_t		sb_inprogress;	/* mkfs is in progress, don't mount */
      53  	uint8_t		sb_imax_pct;	/* max % of fs for inode space */
      54  					/* statistics */
      55  	uint64_t	sb_icount;	/* allocated inodes */
      56  	uint64_t	sb_ifree;	/* free inodes */
      57  	uint64_t	sb_fdblocks;	/* free data blocks */
      58  	uint64_t	sb_frextents;	/* free realtime extents */
      59  	uint64_t	sb_uquotino;	/* inode for user quotas */
      60  	uint64_t	sb_gquotino;	/* inode for group or project quotas */
      61  	uint16_t	sb_qflags;	/* quota flags */
      62  	uint8_t		sb_flags;	/* misc flags */
      63  	uint8_t		sb_shared_vn;	/* reserved, zeroed */
      64  	uint32_t	sb_inoalignmt;	/* inode alignment */
      65  	uint32_t	sb_unit;	/* stripe or raid unit */
      66  	uint32_t	sb_width;	/* stripe or raid width */
      67  	uint8_t		sb_dirblklog;	/* directory block allocation granularity */
      68  	uint8_t		sb_logsectlog;	/* log sector sector size */
      69  	uint16_t	sb_logsectsize;	/* log sector size */
      70  	uint32_t	sb_logsunit;	/* log device stripe or raid unit */
      71  	uint32_t	sb_features2;	/* additional version flags */
      72  	uint32_t	sb_bad_features2;	/* mirror of sb_features2 */
      73  
      74  	/* version 5 fields */
      75  	uint32_t	sb_features_compat;		/* rw compatible flags */
      76  	uint32_t	sb_features_ro_compat;		/* ro compatible flags */
      77  	uint32_t	sb_features_incompat;		/* rw incompatible flags */
      78  	uint32_t	sb_features_log_incompat;	/* rw log incompatible flags */
      79  	uint32_t	sb_crc;				/* superblock checksum */
      80  	uint32_t	sb_spino_align;			/* sparse inode alignment */
      81  	uint64_t	sb_pquotino;			/* project quote inode */
      82  	uint64_t	sb_lsn;			/* superblock update sequence number */
      83  	unsigned char	sb_meta_uuid[16]; 	/* superblock meta uuid */
      84  	uint64_t	sb_rrmapino;		/* realtime reversemapping inode */
      85  } __attribute__((packed));
      86  
      87  #define XFS_MIN_BLOCKSIZE_LOG	9	/* i.e. 512 bytes */
      88  #define XFS_MAX_BLOCKSIZE_LOG	16	/* i.e. 65536 bytes */
      89  #define XFS_MIN_BLOCKSIZE	(1 << XFS_MIN_BLOCKSIZE_LOG)
      90  #define XFS_MAX_BLOCKSIZE	(1 << XFS_MAX_BLOCKSIZE_LOG)
      91  #define XFS_MIN_SECTORSIZE_LOG	9	/* i.e. 512 bytes */
      92  #define XFS_MAX_SECTORSIZE_LOG	15	/* i.e. 32768 bytes */
      93  #define XFS_MIN_SECTORSIZE	(1 << XFS_MIN_SECTORSIZE_LOG)
      94  #define XFS_MAX_SECTORSIZE	(1 << XFS_MAX_SECTORSIZE_LOG)
      95  
      96  #define	XFS_DINODE_MIN_LOG	8
      97  #define	XFS_DINODE_MAX_LOG	11
      98  #define	XFS_DINODE_MIN_SIZE	(1 << XFS_DINODE_MIN_LOG)
      99  #define	XFS_DINODE_MAX_SIZE	(1 << XFS_DINODE_MAX_LOG)
     100  
     101  #define	XFS_MAX_RTEXTSIZE	(1024 * 1024 * 1024)	/* 1GB */
     102  #define	XFS_DFL_RTEXTSIZE	(64 * 1024)	        /* 64kB */
     103  #define	XFS_MIN_RTEXTSIZE	(4 * 1024)		/* 4kB */
     104  
     105  #define XFS_MIN_AG_BLOCKS	64
     106  #define XFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks)
     107  #define XFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) *	\
     108  			 (s)->sb_agblocks + XFS_MIN_AG_BLOCKS)
     109  
     110  #define XFS_SB_VERSION_MOREBITSBIT	0x8000
     111  #define XFS_SB_VERSION2_CRCBIT		0x00000100
     112  
     113  
     114  static void sb_from_disk(struct xfs_super_block *from,
     115  			 struct xfs_super_block *to)
     116  {
     117  
     118  	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
     119  	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
     120  	to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
     121  	to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
     122  	to->sb_rextents = be64_to_cpu(from->sb_rextents);
     123  	to->sb_logstart = be64_to_cpu(from->sb_logstart);
     124  	to->sb_rootino = be64_to_cpu(from->sb_rootino);
     125  	to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
     126  	to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
     127  	to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
     128  	to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
     129  	to->sb_agcount = be32_to_cpu(from->sb_agcount);
     130  	to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
     131  	to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
     132  	to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
     133  	to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
     134  	to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
     135  	to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
     136  	to->sb_blocklog = from->sb_blocklog;
     137  	to->sb_sectlog = from->sb_sectlog;
     138  	to->sb_inodelog = from->sb_inodelog;
     139  	to->sb_inopblog = from->sb_inopblog;
     140  	to->sb_agblklog = from->sb_agblklog;
     141  	to->sb_rextslog = from->sb_rextslog;
     142  	to->sb_inprogress = from->sb_inprogress;
     143  	to->sb_imax_pct = from->sb_imax_pct;
     144  	to->sb_icount = be64_to_cpu(from->sb_icount);
     145  	to->sb_ifree = be64_to_cpu(from->sb_ifree);
     146  	to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
     147  	to->sb_frextents = be64_to_cpu(from->sb_frextents);
     148  	to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
     149  	to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
     150  	to->sb_qflags = be16_to_cpu(from->sb_qflags);
     151  	to->sb_flags = from-> sb_flags;
     152  	to->sb_shared_vn = from-> sb_shared_vn;
     153  	to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
     154  	to->sb_unit = be32_to_cpu(from->sb_unit);
     155  	to->sb_width = be32_to_cpu(from->sb_width);
     156  	to->sb_dirblklog = from-> sb_dirblklog;
     157  	to->sb_logsectlog = from-> sb_logsectlog;
     158  	to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
     159  	to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
     160  	to->sb_features2 = be32_to_cpu(from->sb_features2);
     161  	to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
     162  	to->sb_features_compat = be32_to_cpu(from->sb_features_compat);
     163  	to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat);
     164  	to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat);
     165  	to->sb_features_log_incompat = be32_to_cpu(from->sb_features_log_incompat);
     166  	to->sb_crc = be32_to_cpu(from->sb_crc);
     167  	to->sb_spino_align = be32_to_cpu(from->sb_spino_align);
     168  	to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
     169  	to->sb_lsn = be64_to_cpu(from->sb_lsn);
     170  	to->sb_rrmapino = be64_to_cpu(from->sb_rrmapino);
     171  }
     172  
     173  static int xfs_verify_sb(struct xfs_super_block *ondisk, blkid_probe pr,
     174  		const struct blkid_idmag *mag)
     175  {
     176  	struct xfs_super_block sb, *sbp = &sb;
     177  
     178  	/* beXX_to_cpu(), but don't convert UUID and fsname! */
     179  	sb_from_disk(ondisk, sbp);
     180  
     181  	/* sanity checks, we don't want to rely on magic string only */
     182  	if (sbp->sb_agcount <= 0					||
     183  	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||
     184  	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||
     185  	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||
     186  	    sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG			||
     187  	    sbp->sb_sectsize != (1 << sbp->sb_sectlog)			||
     188  	    sbp->sb_blocksize < XFS_MIN_BLOCKSIZE			||
     189  	    sbp->sb_blocksize > XFS_MAX_BLOCKSIZE			||
     190  	    sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG			||
     191  	    sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG			||
     192  	    sbp->sb_blocksize != (1ULL << sbp->sb_blocklog)		||
     193  	    sbp->sb_inodesize < XFS_DINODE_MIN_SIZE			||
     194  	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||
     195  	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||
     196  	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||
     197  	    sbp->sb_inodesize != (1 << sbp->sb_inodelog)		||
     198  	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
     199  	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
     200  	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
     201  	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)	||
     202  	    sbp->sb_dblocks == 0					||
     203  	    sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)			||
     204  	    sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))
     205  		return 0;
     206  
     207  	if ((sbp->sb_versionnum & 0x0f) == 5) {
     208  		uint32_t expected, crc;
     209  		unsigned char *csummed;
     210  
     211  		if (!(sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT))
     212  			return 0;
     213  		if (!(sbp->sb_features2 & XFS_SB_VERSION2_CRCBIT))
     214  			return 0;
     215  
     216  		expected = sbp->sb_crc;
     217  		csummed = blkid_probe_get_sb_buffer(pr, mag, sbp->sb_sectsize);
     218  		if (!csummed)
     219  			return 0;
     220  
     221  		crc = ul_crc32c_exclude_offset(~0LL, csummed, sbp->sb_sectsize,
     222  			                       offsetof(struct xfs_super_block, sb_crc),
     223  			                       sizeof_member(struct xfs_super_block, sb_crc));
     224  		crc = bswap_32(crc ^ ~0LL);
     225  
     226  		if (!blkid_probe_verify_csum(pr, crc, expected))
     227  			return 0;
     228  	}
     229  
     230  	return 1;
     231  }
     232  
     233  static uint64_t xfs_fssize(struct xfs_super_block *xs)
     234  {
     235  	uint32_t lsize = xs->sb_logstart ? xs->sb_logblocks : 0;
     236  	uint64_t avail_blocks = be64_to_cpu(xs->sb_dblocks) - be32_to_cpu(lsize);
     237  	uint64_t fssize = avail_blocks*be32_to_cpu(xs->sb_blocksize);
     238  
     239  	return fssize;
     240  }
     241  
     242  static int probe_xfs(blkid_probe pr, const struct blkid_idmag *mag)
     243  {
     244  	struct xfs_super_block *xs;
     245  
     246  	xs = blkid_probe_get_sb(pr, mag, struct xfs_super_block);
     247  	if (!xs)
     248  		return errno ? -errno : 1;
     249  
     250  	if (!xfs_verify_sb(xs, pr, mag))
     251  		return 1;
     252  
     253  	if (*xs->sb_fname != '\0')
     254  		blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname,
     255  				sizeof(xs->sb_fname));
     256  	blkid_probe_set_uuid(pr, xs->sb_uuid);
     257  	blkid_probe_set_fssize(pr, xfs_fssize(xs));
     258  	blkid_probe_set_fslastblock(pr, be64_to_cpu(xs->sb_dblocks));
     259  	blkid_probe_set_fsblocksize(pr, be32_to_cpu(xs->sb_blocksize));
     260  	blkid_probe_set_block_size(pr, be16_to_cpu(xs->sb_sectsize));
     261  	return 0;
     262  }
     263  
     264  const struct blkid_idinfo xfs_idinfo =
     265  {
     266  	.name		= "xfs",
     267  	.usage		= BLKID_USAGE_FILESYSTEM,
     268  	.probefunc	= probe_xfs,
     269  	.magics		=
     270  	{
     271  		{ .magic = "XFSB", .len = 4 },
     272  		{ NULL }
     273  	}
     274  };
     275  
     276  struct xlog_rec_header {
     277  	uint32_t	h_magicno;
     278  	uint32_t	h_dummy1[1];
     279  	uint32_t	h_version;
     280  	uint32_t	h_len;
     281  	uint32_t	h_dummy2[71];
     282  	uint32_t	h_fmt;
     283  	unsigned char	h_uuid[16];
     284  } __attribute__((packed));
     285  
     286  #define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe
     287  
     288  /*
     289   * For very small filesystems, the minimum log size
     290   * can be smaller, but that seems vanishingly unlikely
     291   * when used with an external log (which is used for
     292   * performance reasons; tiny conflicts with that goal).
     293   */
     294  #define XFS_MIN_LOG_BYTES	(10 * 1024 * 1024)
     295  
     296  #define XLOG_FMT_LINUX_LE	1
     297  #define XLOG_FMT_LINUX_BE	2
     298  #define XLOG_FMT_IRIX_BE	3
     299  
     300  #define XLOG_VERSION_1		1
     301  #define XLOG_VERSION_2		2	/* Large IClogs, Log sunit */
     302  #define XLOG_VERSION_OKBITS	(XLOG_VERSION_1 | XLOG_VERSION_2)
     303  
     304  static int xlog_valid_rec_header(struct xlog_rec_header *rhead)
     305  {
     306  	uint32_t hlen;
     307  
     308  	if (rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))
     309  		return 0;
     310  
     311  	if (!rhead->h_version ||
     312              (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS)))
     313  		return 0;
     314  
     315  	/* LR body must have data or it wouldn't have been written */
     316  	hlen = be32_to_cpu(rhead->h_len);
     317  	if (hlen <= 0 || hlen > INT_MAX)
     318  		return 0;
     319  
     320  	if (rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_LE) &&
     321  	    rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_BE) &&
     322  	    rhead->h_fmt != cpu_to_be32(XLOG_FMT_IRIX_BE))
     323  		return 0;
     324  
     325  	return 1;
     326  }
     327  
     328  /* xlog record header will be in some sector in the first 256k */
     329  static int probe_xfs_log(blkid_probe pr,
     330  		const struct blkid_idmag *mag __attribute__((__unused__)))
     331  {
     332  	int i;
     333  	struct xlog_rec_header *rhead;
     334  	unsigned char *buf;
     335  
     336  	buf = blkid_probe_get_buffer(pr, 0, 256*1024);
     337  	if (!buf)
     338  		return errno ? -errno : 1;
     339  
     340  	/* check the first 512 512-byte sectors */
     341  	for (i = 0; i < 512; i++) {
     342  		/* this is regular XFS (maybe with some sectors shift), ignore */
     343  		if (memcmp(&buf[i*512], "XFSB", 4) == 0)
     344  			return 1;
     345  
     346  		rhead = (struct xlog_rec_header *)&buf[i*512];
     347  
     348  		if (xlog_valid_rec_header(rhead)) {
     349  			blkid_probe_set_uuid_as(pr, rhead->h_uuid, "LOGUUID");
     350  
     351  			if (blkid_probe_set_magic(pr, i * 512,
     352  						sizeof(rhead->h_magicno),
     353  						(unsigned char *) &rhead->h_magicno))
     354  				return 1;
     355  
     356  			return 0;
     357  		}
     358  	}
     359  
     360  	return 1;
     361  }
     362  
     363  const struct blkid_idinfo xfs_log_idinfo =
     364  {
     365  	.name		= "xfs_external_log",
     366  	.usage		= BLKID_USAGE_OTHER,
     367  	.probefunc	= probe_xfs_log,
     368  	.magics		= BLKID_NONE_MAGIC,
     369  	.minsz		= XFS_MIN_LOG_BYTES,
     370  };