[syslinux:elflink] xfs: Add xfs_iget_root() to XFS filesystem ops

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


Commit-ID:  13546ed6db73f7d179292fb9db1613d5d03c2848
Gitweb:     http://www.syslinux.org/commit/13546ed6db73f7d179292fb9db1613d5d03c2848
Author:     Paulo Alcantara <pcacjr at zytor.com>
AuthorDate: Mon, 9 Jul 2012 14:35:14 -0300
Committer:  Paulo Alcantara <pcacjr at zytor.com>
CommitDate: Sat, 21 Jul 2012 01:21:45 -0300

xfs: Add xfs_iget_root() to XFS filesystem ops

This patch adds initial implementation of the xfs_iget_root() filesystem
operation.

Note also that this is not going to work with inode B+trees with any
level associated with it other than only leafs in the tree. I intend to
finish these remaining features in xfs_iget_root() once I get xfs_iget()
function working properly.

I'm looking forward to implement xfs_iget() function since we have now
xfs_iget_root() function at some point.

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

---
 core/fs/xfs/xfs.c    | 151 +++++++++++++++++++++++++++++++++++++++++++++++++--
 core/fs/xfs/xfs.h    | 121 +++++++++++++++++++++++++++++++++++++++--
 core/fs/xfs/xfs_ag.h |  27 ---------
 3 files changed, 260 insertions(+), 39 deletions(-)

diff --git a/core/fs/xfs/xfs.c b/core/fs/xfs/xfs.c
index b36feec..b3cc351 100644
--- a/core/fs/xfs/xfs.c
+++ b/core/fs/xfs/xfs.c
@@ -34,15 +34,154 @@
 #include "xfs_ag.h"
 #include "misc.h"
 
-static struct inode *xfs_iget_root(struct fs_info *unused)
+static inline struct inode *xfs_new_inode(struct fs_info *fs)
 {
-    (void)unused;
+    struct inode *inode;
+
+    inode = alloc_inode(fs, 0, sizeof(struct xfs_inode));
+    if (!inode)
+	malloc_error("xfs_inode structure");
+
+    return inode;
+}
+
+static xfs_dinode_t *xfs_get_dinode(struct fs_info *fs, xfs_ino_t ino)
+{
+    block_t blk;
+    block_t blk_offset;
+    xfs_dinode_t *dino;
+
+    blk = ino << XFS_INFO(fs)->inode_shift >> BLOCK_SHIFT(fs);
+    blk_offset = (blk << BLOCK_SHIFT(fs)) % BLOCK_SIZE(fs);
+
+    dino = (xfs_dinode_t *)((uint8_t *)get_cache(fs->fs_dev, blk) +
+			    blk_offset);
+    if (!dino) {
+	xfs_error("Error in reading filesystem block 0x%llX (%llu)", blk, blk);
+	goto out;
+    }
+
+    if (be16_to_cpu(dino->di_magic) !=
+	be16_to_cpu(*(uint16_t *)XFS_DINODE_MAGIC)) {
+	xfs_error("Inode core's magic number does not match!");
+	goto out;
+    }
+
+    return dino;
+
+out:
+    return NULL;
+}
+
+static struct inode *xfs_iget(const char *unused_0, struct inode *unused_1)
+{
+    (void)unused_0;
+    (void)unused_1;
 
     xfs_debug("in");
 
     return NULL;
 }
 
+static struct inode *xfs_iget_root(struct fs_info *fs)
+{
+    xfs_agnumber_t agno;
+    block_t blk;
+    xfs_agi_t *agi;
+    xfs_btree_sblock_t *ibt_hdr;
+    uint32_t i;
+    xfs_inobt_rec_t *rec;
+    xfs_dinode_t *dino;
+    struct inode *inode = xfs_new_inode(fs);
+
+    xfs_debug("Looking for the root inode...");
+
+    agno = XFS_INO_TO_AGNO(fs, XFS_INFO(fs)->rootino);
+    if (agno >= XFS_INFO(fs)->agcount) {
+	xfs_error("Invalid AG number");
+	goto out;
+    }
+
+    blk = XFS_AGNO_TO_FSB(fs, agno);
+    agi = XFS_AGI_OFFS(fs, get_cache(fs->fs_dev, blk));
+    if (!agi) {
+	xfs_error("Error in reading filesystem block 0x%llX (%llu)", blk, blk);
+	goto out;
+    }
+
+    XFS_PVT(inode)->i_agblock = blk;
+
+    if (be32_to_cpu(agi->agi_magicnum) !=
+	be32_to_cpu(*(uint32_t *)XFS_AGI_MAGIC)) {
+	xfs_error("AGI's magic number does not match!");
+	goto out;
+    }
+
+    xfs_debug("agi_count %lu", be32_to_cpu(agi->agi_count));
+    xfs_debug("agi_level %lu", be32_to_cpu(agi->agi_level));
+
+    /* Get block number relative to the AG containing the root of the inode
+     * B+tree.
+     */
+    blk = agno + be32_to_cpu(agi->agi_root);
+
+    xfs_debug("inode B+tree's block %llu", blk);
+
+    ibt_hdr = (xfs_btree_sblock_t *)get_cache(fs->fs_dev, blk);
+    if (!ibt_hdr) {
+	xfs_error("Error in reading filesystem block 0x%llX (%llu)", blk, blk);
+	goto out;
+    }
+
+    if (be32_to_cpu(ibt_hdr->bb_magic) !=
+	be32_to_cpu(*(uint32_t *)XFS_IBT_MAGIC)) {
+	xfs_error("AGI inode B+tree header's magic number does not match!");
+	goto out;
+    }
+
+    xfs_debug("bb_level %lu", ibt_hdr->bb_level);
+    xfs_debug("bb_numrecs %lu", ibt_hdr->bb_numrecs);
+
+    rec = (xfs_inobt_rec_t *)((uint8_t *)ibt_hdr + sizeof *ibt_hdr);
+    i = ibt_hdr->bb_numrecs;
+    for ( ; i--; rec++) {
+	if (be32_to_cpu(rec->ir_startino) == XFS_INFO(fs)->rootino)
+	    goto found;
+    }
+
+    xfs_error("Root inode not found!");
+    goto not_found;
+
+found:
+    xfs_debug("Root inode has been found!");
+
+    inode->ino = XFS_INFO(fs)->rootino;
+
+    dino = xfs_get_dinode(fs, XFS_INFO(fs)->rootino);
+    if (!dino) {
+	xfs_error("Failed to get inode core from inode %lu",
+		  XFS_INFO(fs)->rootino);
+	goto out;
+    }
+
+    if (!(be16_to_cpu(dino->di_mode) & S_IFDIR)) {
+	xfs_error("root inode is not a directory ?! No makes sense...");
+	goto out;
+    }
+
+    inode->mode = DT_DIR;
+    inode->size = dino->di_size;
+
+    return inode;
+
+not_found:
+
+out:
+    free(inode);
+
+    return NULL;
+}
+
 static inline int xfs_read_superblock(struct fs_info *fs, xfs_sb_t *sb)
 {
     struct disk *disk = fs->fs_dev->disk;
@@ -136,10 +275,10 @@ const struct fs_ops xfs_fs_ops = {
     .iget_root		= xfs_iget_root,
     .searchdir		= NULL,
     .getfssec		= NULL,
-    .load_config	= NULL,
-    .close_file         = NULL,
-    .mangle_name	= NULL,
+    .load_config	= generic_load_config,
+    .close_file         = generic_close_file,
+    .mangle_name	= generic_mangle_name,
     .readdir		= NULL,
-    .iget		= NULL,
+    .iget		= xfs_iget,
     .next_extent	= NULL,
 };
diff --git a/core/fs/xfs/xfs.h b/core/fs/xfs/xfs.h
index 466ce00..9300027 100644
--- a/core/fs/xfs/xfs.h
+++ b/core/fs/xfs/xfs.h
@@ -39,18 +39,38 @@
 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_PVT(ino) ((struct xfs_inode *)((ino)->pvt))
 
-#define XFS_AG_BLOCK(fs, bytes) \
-    ((block_t)(((bytes) + XFS_INFO((fs))->agblocks - 1) / \
-	       XFS_INFO((fs))->agblocks) - 1)
+#define XFS_INO_TO_AGNO(fs, ino) \
+    (xfs_agnumber_t)((ino) >> XFS_INFO((fs))->ag_relative_ino_shift)
 
-#define XFS_AGI_OFFSET(fs, mp) \
-    ((xfs_agi_t *)((uint8_t *)(mp) + 2 * SECTOR_SIZE((fs))))
+#define XFS_AGNO_TO_FSB(fs, agno) \
+    (block_t)((agno) << XFS_INFO((fs))->agblocks_shift)
+
+#define XFS_AGI_OFFS(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 */
 
+/* Magic numbers */
+#define	XFS_AGI_MAGIC 		"XAGI"
+#define XFS_IBT_MAGIC 		"IABT"
+#define XFS_DINODE_MAGIC	"IN"
+
+/* File types and modes */
+#define S_IFMT  	00170000
+#define S_IFSOCK 	0140000
+#define S_IFLNK 	0120000
+#define S_IFREG  	0100000
+#define S_IFBLK  	0060000
+#define S_IFDIR  	0040000
+#define S_IFCHR  	0020000
+#define S_IFIFO  	0010000
+#define S_ISUID  	0004000
+#define S_ISGID  	0002000
+#define S_ISVTX  	0001000
+
 /*
  * NOTE: The fields in the superblock are stored in big-endian format on disk.
  */
@@ -143,6 +163,95 @@ struct xfs_fs_info {
     uint8_t		inode_shift; /* Inode size in bits */
 } __attribute__((__packed__));
 
+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];
+} __attribute__((__packed__)) xfs_agi_t;
+
+typedef struct xfs_btree_sblock {
+    uint32_t bb_magic;
+    uint16_t bb_level;
+    uint16_t bb_numrecs;
+    uint32_t bb_leftsib;
+    uint32_t bb_rightsib;
+} __attribute__((__packed__)) xfs_btree_sblock_t;
+
+typedef struct xfs_inobt_rec {
+    uint32_t ir_startino;
+    uint32_t ir_freecount;
+    uint64_t ir_free;
+} __attribute__((__packed__)) xfs_inobt_rec_t;
+
+typedef struct xfs_timestamp {
+    int32_t t_sec;
+    int32_t t_nsec;
+} __attribute__((__packed__)) xfs_timestamp_t;
+
+typedef enum xfs_dinode_fmt {
+    XFS_DINODE_FMT_DEV,
+    XFS_DINODE_FMT_LOCAL,
+    XFS_DINODE_FMT_EXTENTS,
+    XFS_DINODE_FMT_BTREE,
+    XFS_DINODE_FMT_UUID,
+} xfs_dinode_fmt_t;
+
+typedef struct xfs_dinode {
+    uint16_t		di_magic;	/* inode magic # = XFS_DINODE_MAGIC */
+    uint16_t		di_mode;	/* mode and type of file */
+    uint8_t		di_version;	/* inode version */
+    uint8_t		di_format;	/* format of di_c data */
+    uint16_t		di_onlink;	/* old number of links to file */
+    uint32_t		di_uid;		/* owner's user id */
+    uint32_t		di_gid;		/* owner's group id */
+    uint32_t		di_nlink;	/* number of links to file */
+    uint16_t		di_projid_lo;	/* lower part of owner's project id */
+    uint16_t		di_projid_hi;	/* higher part owner's project id */
+    uint8_t		di_pad[6];	/* unused, zeroed space */
+    uint16_t		di_flushiter;	/* incremented on flush */
+    xfs_timestamp_t	di_atime;	/* time last accessed */
+    xfs_timestamp_t	di_mtime;	/* time last modified */
+    xfs_timestamp_t	di_ctime;	/* time created/inode modified */
+    uint64_t		di_size;	/* number of bytes in file */
+    uint64_t		di_nblocks;	/* # of direct & btree blocks used */
+    uint32_t		di_extsize;	/* basic/minimum extent size for file */
+    uint32_t		di_nextents;	/* number of extents in data fork */
+    uint16_t		di_anextents;	/* number of extents in attribute fork*/
+    uint8_t		di_forkoff;	/* attr fork offs, <<3 for 64b align */
+    int8_t		di_aformat;	/* format of attr fork's data */
+    uint32_t		di_dmevmask;	/* DMIG event mask */
+    uint16_t		di_dmstate;	/* DMIG state info */
+    uint16_t		di_flags;	/* random flags, XFS_DIFLAG_... */
+    uint32_t		di_gen;		/* generation number */
+
+    /* di_next_unlinked is the only non-core field in the old dinode */
+    uint32_t		di_next_unlinked;/* agi unlinked list ptr */
+} __attribute__((packed)) xfs_dinode_t;
+
+struct xfs_inode {
+    xfs_agblock_t i_agblock;
+};
+
 static inline bool xfs_is_valid_magicnum(const xfs_sb_t *sb)
 {
     return sb->sb_magicnum == *(uint32_t *)XFS_SB_MAGIC;
diff --git a/core/fs/xfs/xfs_ag.h b/core/fs/xfs/xfs_ag.h
index 9167a0a..808e1c9 100644
--- a/core/fs/xfs/xfs_ag.h
+++ b/core/fs/xfs/xfs_ag.h
@@ -38,7 +38,6 @@ 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
 
@@ -122,32 +121,6 @@ extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
  */
 #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


More information about the Syslinux-commits mailing list