(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
exfs.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   * Copyright (C) 2017 Hewlett Packard Enterprise Development LP
       9   *
      10   * This file may be redistributed under the terms of the
      11   * GNU Lesser General Public License.
      12   */
      13  
      14  #include <stdio.h>
      15  #include <stdlib.h>
      16  #include <unistd.h>
      17  #include <string.h>
      18  #include <errno.h>
      19  #include <ctype.h>
      20  #include <stdint.h>
      21  
      22  #include "superblocks.h"
      23  
      24  struct exfs_super_block {
      25  	uint32_t	sb_magicnum;	/* magic number == EXFS_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 == EXFS_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  
      60  	/* this is not all... but enough for libblkid */
      61  
      62  } __attribute__((packed));
      63  
      64  #define EXFS_MIN_BLOCKSIZE_LOG	9	/* i.e. 512 bytes */
      65  #define EXFS_MAX_BLOCKSIZE_LOG	16	/* i.e. 65536 bytes */
      66  #define EXFS_MIN_BLOCKSIZE	(1 << EXFS_MIN_BLOCKSIZE_LOG)
      67  #define EXFS_MAX_BLOCKSIZE	(1 << EXFS_MAX_BLOCKSIZE_LOG)
      68  #define EXFS_MIN_SECTORSIZE_LOG	9	/* i.e. 512 bytes */
      69  #define EXFS_MAX_SECTORSIZE_LOG	15	/* i.e. 32768 bytes */
      70  #define EXFS_MIN_SECTORSIZE	(1 << EXFS_MIN_SECTORSIZE_LOG)
      71  #define EXFS_MAX_SECTORSIZE	(1 << EXFS_MAX_SECTORSIZE_LOG)
      72  
      73  #define	EXFS_DINODE_MIN_LOG	8
      74  #define	EXFS_DINODE_MAX_LOG	11
      75  #define	EXFS_DINODE_MIN_SIZE	(1 << EXFS_DINODE_MIN_LOG)
      76  #define	EXFS_DINODE_MAX_SIZE	(1 << EXFS_DINODE_MAX_LOG)
      77  
      78  #define	EXFS_MAX_RTEXTSIZE	(1024 * 1024 * 1024)	/* 1GB */
      79  #define	EXFS_DFL_RTEXTSIZE	(64 * 1024)		/* 64kB */
      80  #define	EXFS_MIN_RTEXTSIZE	(4 * 1024)		/* 4kB */
      81  
      82  #define EXFS_MIN_AG_BLOCKS	64
      83  #define EXFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks)
      84  #define EXFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) *	\
      85  			 (s)->sb_agblocks + EXFS_MIN_AG_BLOCKS)
      86  
      87  
      88  static void sb_from_disk(struct exfs_super_block *from,
      89  			 struct exfs_super_block *to)
      90  {
      91  
      92  	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
      93  	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
      94  	to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
      95  	to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
      96  	to->sb_rextents = be64_to_cpu(from->sb_rextents);
      97  	to->sb_logstart = be64_to_cpu(from->sb_logstart);
      98  	to->sb_rootino = be64_to_cpu(from->sb_rootino);
      99  	to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
     100  	to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
     101  	to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
     102  	to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
     103  	to->sb_agcount = be32_to_cpu(from->sb_agcount);
     104  	to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
     105  	to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
     106  	to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
     107  	to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
     108  	to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
     109  	to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
     110  	to->sb_blocklog = from->sb_blocklog;
     111  	to->sb_sectlog = from->sb_sectlog;
     112  	to->sb_inodelog = from->sb_inodelog;
     113  	to->sb_inopblog = from->sb_inopblog;
     114  	to->sb_agblklog = from->sb_agblklog;
     115  	to->sb_rextslog = from->sb_rextslog;
     116  	to->sb_inprogress = from->sb_inprogress;
     117  	to->sb_imax_pct = from->sb_imax_pct;
     118  	to->sb_icount = be64_to_cpu(from->sb_icount);
     119  	to->sb_ifree = be64_to_cpu(from->sb_ifree);
     120  	to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
     121  	to->sb_frextents = be64_to_cpu(from->sb_frextents);
     122  }
     123  
     124  static int exfs_verify_sb(struct exfs_super_block *ondisk)
     125  {
     126  	struct exfs_super_block sb, *sbp = &sb;
     127  
     128  	/* beXX_to_cpu(), but don't convert UUID and fsname! */
     129  	sb_from_disk(ondisk, sbp);
     130  
     131  	/* sanity checks, we don't want to rely on magic string only */
     132  	if (sbp->sb_agcount <= 0					||
     133  	    sbp->sb_sectsize < EXFS_MIN_SECTORSIZE			||
     134  	    sbp->sb_sectsize > EXFS_MAX_SECTORSIZE			||
     135  	    sbp->sb_sectlog < EXFS_MIN_SECTORSIZE_LOG			||
     136  	    sbp->sb_sectlog > EXFS_MAX_SECTORSIZE_LOG			||
     137  	    sbp->sb_sectsize != (1 << sbp->sb_sectlog)			||
     138  	    sbp->sb_blocksize < EXFS_MIN_BLOCKSIZE			||
     139  	    sbp->sb_blocksize > EXFS_MAX_BLOCKSIZE			||
     140  	    sbp->sb_blocklog < EXFS_MIN_BLOCKSIZE_LOG			||
     141  	    sbp->sb_blocklog > EXFS_MAX_BLOCKSIZE_LOG			||
     142  	    sbp->sb_blocksize != (1ULL << sbp->sb_blocklog)		||
     143  	    sbp->sb_inodesize < EXFS_DINODE_MIN_SIZE			||
     144  	    sbp->sb_inodesize > EXFS_DINODE_MAX_SIZE			||
     145  	    sbp->sb_inodelog < EXFS_DINODE_MIN_LOG			||
     146  	    sbp->sb_inodelog > EXFS_DINODE_MAX_LOG			||
     147  	    sbp->sb_inodesize != (1 << sbp->sb_inodelog)		||
     148  	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
     149  	    (sbp->sb_rextsize * sbp->sb_blocksize > EXFS_MAX_RTEXTSIZE)	||
     150  	    (sbp->sb_rextsize * sbp->sb_blocksize < EXFS_MIN_RTEXTSIZE)	||
     151  	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)	||
     152  	    sbp->sb_dblocks == 0					||
     153  	    sbp->sb_dblocks > EXFS_MAX_DBLOCKS(sbp)			||
     154  	    sbp->sb_dblocks < EXFS_MIN_DBLOCKS(sbp))
     155  		return 0;
     156  	return 1;
     157  }
     158  
     159  static int probe_exfs(blkid_probe pr, const struct blkid_idmag *mag)
     160  {
     161  	struct exfs_super_block *xs;
     162  
     163  	xs = blkid_probe_get_sb(pr, mag, struct exfs_super_block);
     164  	if (!xs)
     165  		return errno ? -errno : 1;
     166  
     167  	if (!exfs_verify_sb(xs))
     168  		return 1;
     169  
     170  	if (*xs->sb_fname != '\0')
     171  		blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname,
     172  				sizeof(xs->sb_fname));
     173  
     174  	blkid_probe_set_uuid(pr, xs->sb_uuid);
     175  
     176  	blkid_probe_set_fsblocksize(pr, be32_to_cpu(xs->sb_blocksize));
     177  	blkid_probe_set_block_size(pr, be32_to_cpu(xs->sb_blocksize));
     178  
     179  	return 0;
     180  }
     181  
     182  const struct blkid_idinfo exfs_idinfo =
     183  {
     184  	.name		= "exfs",
     185  	.usage		= BLKID_USAGE_FILESYSTEM,
     186  	.probefunc	= probe_exfs,
     187  	.magics		=
     188  	{
     189  		{ .magic = "EXFS", .len = 4 },
     190  		{ NULL }
     191  	}
     192  };