[syslinux:elflink] xfs: Implement xfs_fs_init() function

syslinux-bot for Paulo Alcantara pcacjr at zytor.com
Tue Nov 27 12:57:05 PST 2012


Commit-ID:  abd3b454729a3a7b6cf032ddb38e924123b72494
Gitweb:     http://www.syslinux.org/commit/abd3b454729a3a7b6cf032ddb38e924123b72494
Author:     Paulo Alcantara <pcacjr at zytor.com>
AuthorDate: Sat, 9 Jun 2012 06:19:49 -0300
Committer:  Paulo Alcantara <pcacjr at zytor.com>
CommitDate: Sat, 21 Jul 2012 01:21:45 -0300

xfs: Implement xfs_fs_init() function

The XFS filesystem driver is now able to read properly the XFS superblock
and store useful information to be used around the driver code, which is
kept (in memory) in the xfs_fs_info structure.

As XFS filesytems store their superblock's fields in big-endian format,
we need to have functions capable to transform a 16/32/64-bit big-endian
value into a 16/32/64-bit little-endian one, since Syslinux is only able
to boot up on x86 systems, which store values in litte-endian format. So,
the bexx_to_cpu() functions do this trick.

The driver isn't functional yet, but I'm looking forward to implement
the iget() family of functions ASAP, then we can to at least get a
"boot:" from a XFS filesystem.

Signed-off-by: Paulo Alcantara <pcacjr at zytor.com>

---
 core/fs/xfs/misc.h   |  50 ++++++++++
 core/fs/xfs/xfs.c    |  99 +++++++++++++++++--
 core/fs/xfs/xfs.h    | 156 +++++++++++++++++++++++++++++
 core/fs/xfs/xfs_ag.h | 227 +++++++++++++++++++++++++++++++++++++++++++
 core/fs/xfs/xfs_sb.h | 270 ---------------------------------------------------
 5 files changed, 522 insertions(+), 280 deletions(-)

diff --git a/core/fs/xfs/misc.h b/core/fs/xfs/misc.h
new file mode 100644
index 0000000..7f2f1b3
--- /dev/null
+++ b/core/fs/xfs/misc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr at zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef MISC_H_
+#define MISC_H_
+
+/* Return a 64-bit litte-endian value from a given 64-bit big-endian one */
+static inline uint64_t be64_to_cpu(uint64_t val)
+{
+    return (uint64_t)((((uint64_t)val & (uint64_t)0x00000000000000ffULL) << 56) |
+		      (((uint64_t)val & (uint64_t)0x000000000000ff00ULL) << 40) |
+		      (((uint64_t)val & (uint64_t)0x0000000000ff0000ULL) << 24) |
+		      (((uint64_t)val & (uint64_t)0x00000000ff000000ULL) <<  8) |
+		      (((uint64_t)val & (uint64_t)0x000000ff00000000ULL) >>  8) |
+		      (((uint64_t)val & (uint64_t)0x0000ff0000000000ULL) >> 24) |
+		      (((uint64_t)val & (uint64_t)0x00ff000000000000ULL) >> 40) |
+		      (((uint64_t)val & (uint64_t)0xff00000000000000ULL) >> 56));
+}
+
+/* Return a 32-bit litte-endian value from a given 32-bit big-endian one */
+static inline uint32_t be32_to_cpu(uint32_t val)
+{
+    return (uint32_t)((((uint32_t)val & (uint32_t)0x000000ffUL) << 24) |
+		      (((uint32_t)val & (uint32_t)0x0000ff00UL) <<  8) |
+		      (((uint32_t)val & (uint32_t)0x00ff0000UL) >>  8) |
+		      (((uint32_t)val & (uint32_t)0xff000000UL) >> 24));
+}
+
+/* Return a 16-bit litte-endian value from a given 16-bit big-endian one */
+static inline uint16_t be16_to_cpu(uint16_t val)
+{
+    return (uint16_t)((((uint16_t)val & (uint16_t)0x00ffU) << 8) |
+		      (((uint16_t)val & (uint16_t)0xff00U) >> 8));
+}
+
+#endif /* MISC_H_ */
diff --git a/core/fs/xfs/xfs.c b/core/fs/xfs/xfs.c
index 80969ff..b36feec 100644
--- a/core/fs/xfs/xfs.c
+++ b/core/fs/xfs/xfs.c
@@ -30,37 +30,116 @@
 #include "codepage.h"
 #include "xfs_types.h"
 #include "xfs_sb.h"
+#include "xfs.h"
+#include "xfs_ag.h"
+#include "misc.h"
+
+static struct inode *xfs_iget_root(struct fs_info *unused)
+{
+    (void)unused;
+
+    xfs_debug("in");
+
+    return NULL;
+}
+
+static inline int xfs_read_superblock(struct fs_info *fs, xfs_sb_t *sb)
+{
+    struct disk *disk = fs->fs_dev->disk;
+
+    if (!disk->rdwr_sectors(disk, sb, XFS_SB_DADDR, 1, false))
+	return -1;
+
+    return 0;
+}
+
+static struct xfs_fs_info *xfs_new_sb_info(xfs_sb_t *sb)
+{
+    struct xfs_fs_info *info;
+
+    info = malloc(sizeof *info);
+    if (!info)
+	malloc_error("xfs_fs_info structure");
+
+    info->blocksize = be32_to_cpu(sb->sb_blocksize);
+    info->block_shift = sb->sb_blocklog;
+
+    /* Calculate the bits used in the Relative inode number */
+    info->ag_relative_ino_shift = sb->sb_inopblog + sb->sb_agblklog;
+    /* The MSB is the AG number in Absolute inode numbers */
+    info->ag_number_ino_shift = 8 * sizeof(xfs_ino_t) -
+				info->ag_relative_ino_shift;
+
+    info->rootino = be64_to_cpu(sb->sb_rootino);
+
+    info->agblocks = be32_to_cpu(sb->sb_agblocks);
+    info->agblocks_shift = sb->sb_agblklog;
+    info->agcount = be32_to_cpu(sb->sb_agcount);
+
+    info->inodesize = be16_to_cpu(sb->sb_inodesize);
+    info->inode_shift = sb->sb_inodelog;
+
+    return info;
+}
 
 static int xfs_fs_init(struct fs_info *fs)
 {
     struct disk *disk = fs->fs_dev->disk;
     xfs_sb_t sb;
-    int retval;
+    struct xfs_fs_info *info;
 
-    /* Read XFS superblock (LBA 0) */
-    retval = disk->rdwr_sectors(disk, &sb, 0, 1, 0);
-    if (!retval)
-	return -1;
+    xfs_debug("fs %p", fs);
+
+    SECTOR_SHIFT(fs) = disk->sector_shift;
+    SECTOR_SIZE(fs) = 1 << SECTOR_SHIFT(fs);
+
+    if (xfs_read_superblock(fs, &sb)) {
+	xfs_error("Superblock read failed");
+	goto out;
+    }
+
+    if (!xfs_is_valid_magicnum(&sb)) {
+	xfs_error("Invalid superblock");
+	goto out;
+    }
+
+    xfs_debug("magicnum 0x%lX", be32_to_cpu(sb.sb_magicnum));
+
+    info = xfs_new_sb_info(&sb);
+    if (!info) {
+	xfs_error("Failed to fill in filesystem-specific info structure");
+	goto out;
+    }
+
+    fs->fs_info = info;
+
+    xfs_debug("block_shift %u blocksize 0x%lX (%lu)", info->block_shift,
+	      info->blocksize, info->blocksize);
+
+    xfs_debug("rootino 0x%llX (%llu)", info->rootino, info->rootino);
+
+    BLOCK_SHIFT(fs) = info->block_shift;
+    BLOCK_SIZE(fs) = info->blocksize;
 
-    if (sb.sb_magicnum == *(uint32_t *)XFS_SB_MAGIC)
-	printf("Cool! It's a XFS filesystem! :-)\n");
+    cache_init(fs->fs_dev, BLOCK_SHIFT(fs));
 
-    /* Nothing to do for now... */
+    return BLOCK_SHIFT(fs);
 
+out:
     return -1;
 }
 
 const struct fs_ops xfs_fs_ops = {
-    .fs_name		= "ntfs",
+    .fs_name		= "xfs",
     .fs_flags		= FS_USEMEM | FS_THISIND,
     .fs_init		= xfs_fs_init,
+    .iget_root		= xfs_iget_root,
     .searchdir		= NULL,
     .getfssec		= NULL,
     .load_config	= NULL,
     .close_file         = NULL,
     .mangle_name	= NULL,
     .readdir		= NULL,
-    .iget_root		= NULL,
     .iget		= NULL,
     .next_extent	= NULL,
 };
diff --git a/core/fs/xfs/xfs.h b/core/fs/xfs/xfs.h
new file mode 100644
index 0000000..466ce00
--- /dev/null
+++ b/core/fs/xfs/xfs.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr at zytor.com>
+ *
+ * Some parts borrowed from Linux kernel tree (linux/fs/xfs):
+ *
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef XFS_H_
+#define XFS_H_
+
+#include <disk.h>
+#include <fs.h>
+
+#include "xfs_types.h"
+#include "xfs_ag.h"
+
+#define xfs_error(fmt, args...) \
+    printf("xfs: " fmt "\n", ## args);
+
+#define xfs_debug(fmt, args...) \
+    printf("%s: " fmt "\n", __func__, ## args);
+
+struct xfs_fs_info;
+
+#define XFS_INFO(fs) ((struct xfs_fs_info *)((fs)->fs_info))
+#define XFS_PVT(ino) ((xfs_agi_t *)((ino)->pvt))
+
+#define XFS_AG_BLOCK(fs, bytes) \
+    ((block_t)(((bytes) + XFS_INFO((fs))->agblocks - 1) / \
+	       XFS_INFO((fs))->agblocks) - 1)
+
+#define XFS_AGI_OFFSET(fs, mp) \
+    ((xfs_agi_t *)((uint8_t *)(mp) + 2 * SECTOR_SIZE((fs))))
+
+/* Superblock's LBA */
+#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */
+
+/*
+ * NOTE: The fields in the superblock are stored in big-endian format on disk.
+ */
+typedef struct xfs_sb {
+    uint32_t	sb_magicnum;	/* magic number == XFS_SB_MAGIC */
+    uint32_t	sb_blocksize;	/* logical block size, bytes */
+    xfs_drfsbno_t	sb_dblocks;	/* number of data blocks */
+    xfs_drfsbno_t	sb_rblocks;	/* number of realtime blocks */
+    xfs_drtbno_t	sb_rextents;	/* number of realtime extents */
+    uuid_t		sb_uuid;	/* file system unique id */
+    xfs_dfsbno_t	sb_logstart;	/* starting block of log if internal */
+    xfs_ino_t	sb_rootino;	/* root inode number */
+    xfs_ino_t	sb_rbmino;	/* bitmap inode for realtime extents */
+    xfs_ino_t	sb_rsumino;	/* summary inode for rt bitmap */
+    xfs_agblock_t	sb_rextsize;	/* realtime extent size, blocks */
+    xfs_agblock_t	sb_agblocks;	/* size of an allocation group */
+    xfs_agnumber_t	sb_agcount;	/* number of allocation groups */
+    xfs_extlen_t	sb_rbmblocks;	/* number of rt bitmap blocks */
+    xfs_extlen_t	sb_logblocks;	/* number of log blocks */
+    uint16_t	sb_versionnum;	/* header version == XFS_SB_VERSION */
+    uint16_t	sb_sectsize;	/* volume sector size, bytes */
+    uint16_t	sb_inodesize;	/* inode size, bytes */
+    uint16_t	sb_inopblock;	/* inodes per block */
+    char	sb_fname[12];	/* file system name */
+    uint8_t	sb_blocklog;	/* log2 of sb_blocksize */
+    uint8_t	sb_sectlog;	/* log2 of sb_sectsize */
+    uint8_t	sb_inodelog;	/* log2 of sb_inodesize */
+    uint8_t	sb_inopblog;	/* log2 of sb_inopblock */
+    uint8_t	sb_agblklog;	/* log2 of sb_agblocks (rounded up) */
+    uint8_t	sb_rextslog;	/* log2 of sb_rextents */
+    uint8_t	sb_inprogress;	/* mkfs is in progress, don't mount */
+    uint8_t	sb_imax_pct;	/* max % of fs for inode space */
+					/* statistics */
+    /*
+     * These fields must remain contiguous.  If you really
+     * want to change their layout, make sure you fix the
+     * code in xfs_trans_apply_sb_deltas().
+     */
+    uint64_t	sb_icount;	/* allocated inodes */
+    uint64_t	sb_ifree;	/* free inodes */
+    uint64_t	sb_fdblocks;	/* free data blocks */
+    uint64_t	sb_frextents;	/* free realtime extents */
+    /*
+     * End contiguous fields.
+     */
+    xfs_ino_t	sb_uquotino;	/* user quota inode */
+    xfs_ino_t	sb_gquotino;	/* group quota inode */
+    uint16_t	sb_qflags;	/* quota flags */
+    uint8_t	sb_flags;	/* misc. flags */
+    uint8_t	sb_shared_vn;	/* shared version number */
+    xfs_extlen_t	sb_inoalignmt;	/* inode chunk alignment, fsblocks */
+    uint32_t	sb_unit;	/* stripe or raid unit */
+    uint32_t	sb_width;	/* stripe or raid width */
+    uint8_t	sb_dirblklog;	/* log2 of dir block size (fsbs) */
+    uint8_t	sb_logsectlog;	/* log2 of the log sector size */
+    uint16_t	sb_logsectsize;	/* sector size for the log, bytes */
+    uint32_t	sb_logsunit;	/* stripe unit size for the log */
+    uint32_t	sb_features2;	/* additional feature bits */
+
+    /*
+     * bad features2 field as a result of failing to pad the sb
+     * structure to 64 bits. Some machines will be using this field
+     * for features2 bits. Easiest just to mark it bad and not use
+     * it for anything else.
+     */
+    uint32_t	sb_bad_features2;
+    uint8_t	pad[304]; /* must be padded to a sector boundary */
+} __attribute__((__packed__)) xfs_sb_t;
+
+/* In-memory structure that stores filesystem-specific information.
+ * The information stored is basically retrieved from the XFS superblock
+ * to be used statically around the driver.
+ */
+struct xfs_fs_info {
+    uint32_t 		blocksize; /* Filesystem block size */
+    uint8_t		block_shift; /* Filesystem block size in bits */
+
+    /* AG relative inode number bits (found within AG's inode structures) */
+    uint8_t		ag_relative_ino_shift;
+    /* AG number bits (MSB of the inode number) */
+    uint8_t		ag_number_ino_shift;
+
+    xfs_ino_t 		rootino; /* Root inode number for the filesystem */
+
+    xfs_agblock_t	agblocks; /* Size of each AG in blocks */
+    uint8_t		agblocks_shift; /* agblocks in bits */
+    xfs_agnumber_t	agcount; /* Number of AGs in the filesytem */
+
+    uint16_t		inodesize; /* Size of the inode in bytes */
+    uint8_t		inode_shift; /* Inode size in bits */
+} __attribute__((__packed__));
+
+static inline bool xfs_is_valid_magicnum(const xfs_sb_t *sb)
+{
+    return sb->sb_magicnum == *(uint32_t *)XFS_SB_MAGIC;
+}
+
+static inline bool xfs_is_valid_agi(xfs_agi_t *agi)
+{
+    return agi->agi_magicnum == *(uint32_t *)XFS_AGI_MAGIC;
+}
+
+#endif /* XFS_H_ */
diff --git a/core/fs/xfs/xfs_ag.h b/core/fs/xfs/xfs_ag.h
new file mode 100644
index 0000000..9167a0a
--- /dev/null
+++ b/core/fs/xfs/xfs_ag.h
@@ -0,0 +1,227 @@
+/*
+ * Taken from Linux kernel tree (linux/fs/xfs)
+ *
+ * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr at zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef XFS_AG_H_
+#define	XFS_AG_H_
+
+#include "xfs_types.h"
+
+/*
+ * Allocation group header
+ * This is divided into three structures, placed in sequential 512-byte
+ * buffers after a copy of the superblock (also in a 512-byte buffer).
+ */
+
+typedef uint32_t xfs_agino_t;
+
+struct xfs_buf;
+struct xfs_mount;
+struct xfs_trans;
+
+#define	XFS_AGF_MAGIC	"XAGF"
+#define	XFS_AGI_MAGIC	"XAGI"
+#define	XFS_AGF_VERSION	1
+#define	XFS_AGI_VERSION	1
+
+#define	XFS_AGF_GOOD_VERSION(v)	((v) == XFS_AGF_VERSION)
+#define	XFS_AGI_GOOD_VERSION(v)	((v) == XFS_AGI_VERSION)
+
+/*
+ * Btree number 0 is bno, 1 is cnt.  This value gives the size of the
+ * arrays below.
+ */
+#define	XFS_BTNUM_AGF	((int)XFS_BTNUM_CNTi + 1)
+
+/*
+ * The second word of agf_levels in the first a.g. overlaps the EFS
+ * superblock's magic number.  Since the magic numbers valid for EFS
+ * are > 64k, our value cannot be confused for an EFS superblock's.
+ */
+
+typedef struct xfs_agf {
+	/*
+	 * Common allocation group header information
+	 */
+	uint32_t		agf_magicnum;	/* magic number == XFS_AGF_MAGIC */
+	uint32_t		agf_versionnum;	/* header version == XFS_AGF_VERSION */
+	uint32_t		agf_seqno;	/* sequence # starting from 0 */
+	uint32_t		agf_length;	/* size in blocks of a.g. */
+	/*
+	 * Freespace information
+	 */
+	uint32_t		agf_roots[XFS_BTNUM_AGF];	/* root blocks */
+	uint32_t		agf_spare0;	/* spare field */
+	uint32_t		agf_levels[XFS_BTNUM_AGF];	/* btree levels */
+	uint32_t		agf_spare1;	/* spare field */
+	uint32_t		agf_flfirst;	/* first freelist block's index */
+	uint32_t		agf_fllast;	/* last freelist block's index */
+	uint32_t		agf_flcount;	/* count of blocks in freelist */
+	uint32_t		agf_freeblks;	/* total free blocks */
+	uint32_t		agf_longest;	/* longest free space */
+	uint32_t		agf_btreeblks;	/* # of blocks held in AGF btrees */
+} xfs_agf_t;
+
+#define	XFS_AGF_MAGICNUM	0x00000001
+#define	XFS_AGF_VERSIONNUM	0x00000002
+#define	XFS_AGF_SEQNO		0x00000004
+#define	XFS_AGF_LENGTH		0x00000008
+#define	XFS_AGF_ROOTS		0x00000010
+#define	XFS_AGF_LEVELS		0x00000020
+#define	XFS_AGF_FLFIRST		0x00000040
+#define	XFS_AGF_FLLAST		0x00000080
+#define	XFS_AGF_FLCOUNT		0x00000100
+#define	XFS_AGF_FREEBLKS	0x00000200
+#define	XFS_AGF_LONGEST		0x00000400
+#define	XFS_AGF_BTREEBLKS	0x00000800
+#define	XFS_AGF_NUM_BITS	12
+#define	XFS_AGF_ALL_BITS	((1 << XFS_AGF_NUM_BITS) - 1)
+
+#define XFS_AGF_FLAGS \
+	{ XFS_AGF_MAGICNUM,	"MAGICNUM" }, \
+	{ XFS_AGF_VERSIONNUM,	"VERSIONNUM" }, \
+	{ XFS_AGF_SEQNO,	"SEQNO" }, \
+	{ XFS_AGF_LENGTH,	"LENGTH" }, \
+	{ XFS_AGF_ROOTS,	"ROOTS" }, \
+	{ XFS_AGF_LEVELS,	"LEVELS" }, \
+	{ XFS_AGF_FLFIRST,	"FLFIRST" }, \
+	{ XFS_AGF_FLLAST,	"FLLAST" }, \
+	{ XFS_AGF_FLCOUNT,	"FLCOUNT" }, \
+	{ XFS_AGF_FREEBLKS,	"FREEBLKS" }, \
+	{ XFS_AGF_LONGEST,	"LONGEST" }, \
+	{ XFS_AGF_BTREEBLKS,	"BTREEBLKS" }
+
+/* disk block (xfs_daddr_t) in the AG */
+#define XFS_AGF_DADDR(mp)	((xfs_daddr_t)(1 << (mp)->m_sectbb_log))
+#define	XFS_AGF_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
+#define	XFS_BUF_TO_AGF(bp)	((xfs_agf_t *)((bp)->b_addr))
+
+extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
+			xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
+
+/*
+ * Size of the unlinked inode hash table in the agi.
+ */
+#define	XFS_AGI_UNLINKED_BUCKETS	64
+
+typedef struct xfs_agi {
+	/*
+	 * Common allocation group header information
+	 */
+	uint32_t		agi_magicnum;	/* magic number == XFS_AGI_MAGIC */
+	uint32_t		agi_versionnum;	/* header version == XFS_AGI_VERSION */
+	uint32_t		agi_seqno;	/* sequence # starting from 0 */
+	uint32_t		agi_length;	/* size in blocks of a.g. */
+	/*
+	 * Inode information
+	 * Inodes are mapped by interpreting the inode number, so no
+	 * mapping data is needed here.
+	 */
+	uint32_t		agi_count;	/* count of allocated inodes */
+	uint32_t		agi_root;	/* root of inode btree */
+	uint32_t		agi_level;	/* levels in inode btree */
+	uint32_t		agi_freecount;	/* number of free inodes */
+	uint32_t		agi_newino;	/* new inode just allocated */
+	uint32_t		agi_dirino;	/* last directory inode chunk */
+	/*
+	 * Hash table of inodes which have been unlinked but are
+	 * still being referenced.
+	 */
+	uint32_t		agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
+} xfs_agi_t;
+
+#define	XFS_AGI_MAGICNUM	0x00000001
+#define	XFS_AGI_VERSIONNUM	0x00000002
+#define	XFS_AGI_SEQNO		0x00000004
+#define	XFS_AGI_LENGTH		0x00000008
+#define	XFS_AGI_COUNT		0x00000010
+#define	XFS_AGI_ROOT		0x00000020
+#define	XFS_AGI_LEVEL		0x00000040
+#define	XFS_AGI_FREECOUNT	0x00000080
+#define	XFS_AGI_NEWINO		0x00000100
+#define	XFS_AGI_DIRINO		0x00000200
+#define	XFS_AGI_UNLINKED	0x00000400
+#define	XFS_AGI_NUM_BITS	11
+#define	XFS_AGI_ALL_BITS	((1 << XFS_AGI_NUM_BITS) - 1)
+
+/* disk block (xfs_daddr_t) in the AG */
+#define XFS_AGI_DADDR(mp)	((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
+#define	XFS_AGI_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
+#define	XFS_BUF_TO_AGI(bp)	((xfs_agi_t *)((bp)->b_addr))
+
+extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
+				xfs_agnumber_t agno, struct xfs_buf **bpp);
+
+/*
+ * The third a.g. block contains the a.g. freelist, an array
+ * of block pointers to blocks owned by the allocation btree code.
+ */
+#define XFS_AGFL_DADDR(mp)	((xfs_daddr_t)(3 << (mp)->m_sectbb_log))
+#define	XFS_AGFL_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp))
+#define XFS_AGFL_SIZE(mp)	((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
+#define	XFS_BUF_TO_AGFL(bp)	((xfs_agfl_t *)((bp)->b_addr))
+
+typedef struct xfs_agfl {
+	uint32_t		agfl_bno[1];	/* actually XFS_AGFL_SIZE(mp) */
+} xfs_agfl_t;
+
+/*
+ * tags for inode radix tree
+ */
+#define XFS_ICI_NO_TAG		(-1)	/* special flag for an untagged lookup
+					   in xfs_inode_ag_iterator */
+#define XFS_ICI_RECLAIM_TAG	0	/* inode is to be reclaimed */
+
+#define	XFS_AG_MAXLEVELS(mp)		((mp)->m_ag_maxlevels)
+#define	XFS_MIN_FREELIST_RAW(bl,cl,mp)	\
+	(MIN(bl + 1, XFS_AG_MAXLEVELS(mp)) + MIN(cl + 1, XFS_AG_MAXLEVELS(mp)))
+#define	XFS_MIN_FREELIST(a,mp)		\
+	(XFS_MIN_FREELIST_RAW(		\
+		be32_to_cpu((a)->agf_levels[XFS_BTNUM_BNOi]), \
+		be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp))
+#define	XFS_MIN_FREELIST_PAG(pag,mp)	\
+	(XFS_MIN_FREELIST_RAW(		\
+		(unsigned int)(pag)->pagf_levels[XFS_BTNUM_BNOi], \
+		(unsigned int)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp))
+
+#define XFS_AGB_TO_FSB(mp,agno,agbno)	\
+	(((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno))
+#define	XFS_FSB_TO_AGNO(mp,fsbno)	\
+	((xfs_agnumber_t)((fsbno) >> (mp)->m_sb.sb_agblklog))
+#define	XFS_FSB_TO_AGBNO(mp,fsbno)	\
+	((xfs_agblock_t)((fsbno) & xfs_mask32lo((mp)->m_sb.sb_agblklog)))
+#define	XFS_AGB_TO_DADDR(mp,agno,agbno)	\
+	((xfs_daddr_t)XFS_FSB_TO_BB(mp, \
+		(xfs_fsblock_t)(agno) * (mp)->m_sb.sb_agblocks + (agbno)))
+#define	XFS_AG_DADDR(mp,agno,d)		(XFS_AGB_TO_DADDR(mp, agno, 0) + (d))
+
+/*
+ * For checking for bad ranges of xfs_daddr_t's, covering multiple
+ * allocation groups or a single xfs_daddr_t that's a superblock copy.
+ */
+#define	XFS_AG_CHECK_DADDR(mp,d,len)	\
+	((len) == 1 ? \
+	    ASSERT((d) == XFS_SB_DADDR || \
+		   xfs_daddr_to_agbno(mp, d) != XFS_SB_DADDR) : \
+	    ASSERT(xfs_daddr_to_agno(mp, d) == \
+		   xfs_daddr_to_agno(mp, (d) + (len) - 1)))
+
+#endif	/* XFS_AG_H_ */
diff --git a/core/fs/xfs/xfs_sb.h b/core/fs/xfs/xfs_sb.h
index 2290e6a..12024ab 100644
--- a/core/fs/xfs/xfs_sb.h
+++ b/core/fs/xfs/xfs_sb.h
@@ -103,76 +103,6 @@ struct xfs_mount;
 	 XFS_SB_VERSION2_OKSASHFBITS )
 
 /*
- * Superblock - in core version.  Must match the ondisk version below.
- * Must be padded to 64 bit alignment.
- */
-typedef struct xfs_sb {
-    uint32_t	sb_magicnum;	/* magic number == XFS_SB_MAGIC */
-    uint32_t	sb_blocksize;	/* logical block size, bytes */
-    xfs_drfsbno_t	sb_dblocks;	/* number of data blocks */
-    xfs_drfsbno_t	sb_rblocks;	/* number of realtime blocks */
-    xfs_drtbno_t	sb_rextents;	/* number of realtime extents */
-    uuid_t		sb_uuid;	/* file system unique id */
-    xfs_dfsbno_t	sb_logstart;	/* starting block of log if internal */
-    xfs_ino_t	sb_rootino;	/* root inode number */
-    xfs_ino_t	sb_rbmino;	/* bitmap inode for realtime extents */
-    xfs_ino_t	sb_rsumino;	/* summary inode for rt bitmap */
-    xfs_agblock_t	sb_rextsize;	/* realtime extent size, blocks */
-    xfs_agblock_t	sb_agblocks;	/* size of an allocation group */
-    xfs_agnumber_t	sb_agcount;	/* number of allocation groups */
-    xfs_extlen_t	sb_rbmblocks;	/* number of rt bitmap blocks */
-    xfs_extlen_t	sb_logblocks;	/* number of log blocks */
-    uint16_t	sb_versionnum;	/* header version == XFS_SB_VERSION */
-    uint16_t	sb_sectsize;	/* volume sector size, bytes */
-    uint16_t	sb_inodesize;	/* inode size, bytes */
-    uint16_t	sb_inopblock;	/* inodes per block */
-    char	sb_fname[12];	/* file system name */
-    uint8_t	sb_blocklog;	/* log2 of sb_blocksize */
-    uint8_t	sb_sectlog;	/* log2 of sb_sectsize */
-    uint8_t	sb_inodelog;	/* log2 of sb_inodesize */
-    uint8_t	sb_inopblog;	/* log2 of sb_inopblock */
-    uint8_t	sb_agblklog;	/* log2 of sb_agblocks (rounded up) */
-    uint8_t	sb_rextslog;	/* log2 of sb_rextents */
-    uint8_t	sb_inprogress;	/* mkfs is in progress, don't mount */
-    uint8_t	sb_imax_pct;	/* max % of fs for inode space */
-					/* statistics */
-    /*
-     * These fields must remain contiguous.  If you really
-     * want to change their layout, make sure you fix the
-     * code in xfs_trans_apply_sb_deltas().
-     */
-    uint64_t	sb_icount;	/* allocated inodes */
-    uint64_t	sb_ifree;	/* free inodes */
-    uint64_t	sb_fdblocks;	/* free data blocks */
-    uint64_t	sb_frextents;	/* free realtime extents */
-    /*
-     * End contiguous fields.
-     */
-    xfs_ino_t	sb_uquotino;	/* user quota inode */
-    xfs_ino_t	sb_gquotino;	/* group quota inode */
-    uint16_t	sb_qflags;	/* quota flags */
-    uint8_t	sb_flags;	/* misc. flags */
-    uint8_t	sb_shared_vn;	/* shared version number */
-    xfs_extlen_t	sb_inoalignmt;	/* inode chunk alignment, fsblocks */
-    uint32_t	sb_unit;	/* stripe or raid unit */
-    uint32_t	sb_width;	/* stripe or raid width */
-    uint8_t	sb_dirblklog;	/* log2 of dir block size (fsbs) */
-    uint8_t	sb_logsectlog;	/* log2 of the log sector size */
-    uint16_t	sb_logsectsize;	/* sector size for the log, bytes */
-    uint32_t	sb_logsunit;	/* stripe unit size for the log */
-    uint32_t	sb_features2;	/* additional feature bits */
-
-    /*
-     * bad features2 field as a result of failing to pad the sb
-     * structure to 64 bits. Some machines will be using this field
-     * for features2 bits. Easiest just to mark it bad and not use
-     * it for anything else.
-     */
-    uint32_t	sb_bad_features2;
-    uint8_t	pad[304]; /* must be padded to a sector boundary */
-} __attribute__((__packed__)) xfs_sb_t;
-
-/*
  * Sequence number values for the fields.
  */
 typedef enum {
@@ -238,210 +168,10 @@ typedef enum {
 
 #define	XFS_SB_VERSION_NUM(sbp)	((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS)
 
-static inline int xfs_sb_good_version(xfs_sb_t *sbp)
-{
-	/* We always support version 1-3 */
-	if (sbp->sb_versionnum >= XFS_SB_VERSION_1 &&
-	    sbp->sb_versionnum <= XFS_SB_VERSION_3)
-		return 1;
-
-	/* We support version 4 if all feature bits are supported */
-	if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) {
-		if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) ||
-		    ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) &&
-		     (sbp->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
-			return 0;
-
-		if ((sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) &&
-		    sbp->sb_shared_vn > XFS_SB_MAX_SHARED_VN)
-			return 0;
-
-		return 1;
-	}
-
-	return 0;
-}
-
-/*
- * Detect a mismatched features2 field.  Older kernels read/wrote
- * this into the wrong slot, so to be safe we keep them in sync.
- */
-static inline int xfs_sb_has_mismatched_features2(xfs_sb_t *sbp)
-{
-	return (sbp->sb_bad_features2 != sbp->sb_features2);
-}
-
-static inline unsigned xfs_sb_version_tonew(unsigned v)
-{
-	if (v == XFS_SB_VERSION_1)
-		return XFS_SB_VERSION_4;
-
-	if (v == XFS_SB_VERSION_2)
-		return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT;
-
-	return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT |
-		XFS_SB_VERSION_NLINKBIT;
-}
-
-static inline unsigned xfs_sb_version_toold(unsigned v)
-{
-	if (v & (XFS_SB_VERSION_QUOTABIT | XFS_SB_VERSION_ALIGNBIT))
-		return 0;
-	if (v & XFS_SB_VERSION_NLINKBIT)
-		return XFS_SB_VERSION_3;
-	if (v & XFS_SB_VERSION_ATTRBIT)
-		return XFS_SB_VERSION_2;
-	return XFS_SB_VERSION_1;
-}
-
-static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp)
-{
-	return sbp->sb_versionnum == XFS_SB_VERSION_2 ||
-		sbp->sb_versionnum == XFS_SB_VERSION_3 ||
-		(XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		 (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT));
-}
-
-static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)
-{
-	if (sbp->sb_versionnum == XFS_SB_VERSION_1)
-		sbp->sb_versionnum = XFS_SB_VERSION_2;
-	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
-		sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
-	else
-		sbp->sb_versionnum = XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT;
-}
-
-static inline int xfs_sb_version_hasnlink(xfs_sb_t *sbp)
-{
-	return sbp->sb_versionnum == XFS_SB_VERSION_3 ||
-		 (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		  (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT));
-}
-
-static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)
-{
-	if (sbp->sb_versionnum <= XFS_SB_VERSION_2)
-		sbp->sb_versionnum = XFS_SB_VERSION_3;
-	else
-		sbp->sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
-}
-
-static inline int xfs_sb_version_hasquota(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT);
-}
-
-static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)
-{
-	if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
-		sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT;
-	else
-		sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) |
-					XFS_SB_VERSION_QUOTABIT;
-}
-
-static inline int xfs_sb_version_hasalign(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT);
-}
-
-static inline int xfs_sb_version_hasdalign(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT);
-}
-
-static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT);
-}
-
-static inline int xfs_sb_version_hasdirv2(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
-}
-
-static inline int xfs_sb_version_haslogv2(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT);
-}
-
-static inline int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT);
-}
-
-static inline int xfs_sb_version_hassector(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
-}
-
-static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
-}
-
-static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
-{
-	return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
-		(sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT);
-}
-
-/*
- * sb_features2 bit version macros.
- *
- * For example, for a bit defined as XFS_SB_VERSION2_FUNBIT, has a macro:
- *
- * SB_VERSION_HASFUNBIT(xfs_sb_t *sbp)
- *	((xfs_sb_version_hasmorebits(sbp) &&
- *	 ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
- */
-
-static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp)
-{
-	return xfs_sb_version_hasmorebits(sbp) &&
-		(sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT);
-}
-
-static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
-{
-	return xfs_sb_version_hasmorebits(sbp) &&
-		(sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT);
-}
-
-static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
-{
-	sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
-	sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
-}
-
-static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)
-{
-	sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
-	if (!sbp->sb_features2)
-		sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
-}
-
-static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
-{
-	return xfs_sb_version_hasmorebits(sbp) &&
-		(sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
-}
-
 /*
  * end of superblock version macros
  */
 
-#define XFS_SB_DADDR		((xfs_daddr_t)0) /* daddr in filesystem/ag */
 #define	XFS_SB_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
 #define XFS_BUF_TO_SBP(bp)	((xfs_dsb_t *)((bp)->b_addr))
 


More information about the Syslinux-commits mailing list