[syslinux:elflink] xfs: Add xfs_getfssec() and xfs_next_extent() functions

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


Commit-ID:  8440ec2a8ea4fda9a3326d53b9e5189163d685d7
Gitweb:     http://www.syslinux.org/commit/8440ec2a8ea4fda9a3326d53b9e5189163d685d7
Author:     Paulo Alcantara <pcacjr at zytor.com>
AuthorDate: Mon, 16 Jul 2012 14:56:30 -0300
Committer:  Paulo Alcantara <pcacjr at zytor.com>
CommitDate: Sat, 21 Jul 2012 01:21:46 -0300

xfs: Add xfs_getfssec() and xfs_next_extent() functions

This is a initial implementation of both and they're not fully functional
yet.

xfs_getfssec() still needs to be modified to handle XFS-specific things
and xfs_next_extent() must handle inodes with different dinode formats
other than _only_ handling dinode format "extents".

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

---
 core/fs/xfs/xfs.c    | 107 ++++++++++++++++++++++++++++++++++++++++++++++-----
 core/fs/xfs/xfs.h    |  26 +++++++++++--
 core/fs/xfs/xfs_ag.h |  11 ------
 3 files changed, 120 insertions(+), 24 deletions(-)

diff --git a/core/fs/xfs/xfs.c b/core/fs/xfs/xfs.c
index 9269f27..79d5a5f 100644
--- a/core/fs/xfs/xfs.c
+++ b/core/fs/xfs/xfs.c
@@ -100,7 +100,6 @@ static xfs_dinode_t *xfs_get_ino_core(struct fs_info *fs, xfs_ino_t ino)
 	be16_to_cpu(*(uint16_t *)XFS_DINODE_MAGIC)) {
 	xfs_error("Inode core's magic number does not match!");
 	xfs_debug("magic number 0x%04x", (be16_to_cpu(core->di_magic)));
-
 	goto out;
     }
 
@@ -115,9 +114,10 @@ out:
  */
 static const void *xfs_get_ino_chunk(struct fs_info *fs, xfs_ino_t ino)
 {
-    const int len = 64 * XFS_INFO(fs)->inodesize;
+    int nblks = ((64 * XFS_INFO(fs)->inodesize) + BLOCK_SIZE(fs) - 1) >>
+		BLOCK_SHIFT(fs);
+    const int len = (nblks + 1) << BLOCK_SHIFT(fs);
     void *buf;
-    block_t nblks;
     uint8_t *p;
     block_t start_blk = ino_to_bytes(fs, ino) >> BLOCK_SHIFT(fs);
     off_t offset = 0;
@@ -128,7 +128,6 @@ static const void *xfs_get_ino_chunk(struct fs_info *fs, xfs_ino_t ino)
 
     memset(buf, 0, len);
 
-    nblks = len >> BLOCK_SHIFT(fs);
     while (nblks--) {
 	p = (uint8_t *)get_cache(fs->fs_dev, start_blk++);
 
@@ -298,6 +297,7 @@ found:
 	if (ncore) {
 	    if (be16_to_cpu(ncore->di_magic) ==
 		be16_to_cpu(*(uint16_t *)XFS_DINODE_MAGIC)) {
+		xfs_debug("Inode's core has been found");
 		goto core_found;
 	    } else {
 		xfs_error("Inode core's magic number does not match!");
@@ -321,18 +321,96 @@ core_found:
     XFS_PVT(inode)->i_ino_blk	= ino_to_bytes(fs, ino) >> BLOCK_SHIFT(fs);
     inode->size 		= be64_to_cpu(ncore->di_size);
 
-    if (be16_to_cpu(ncore->di_mode) & S_IFDIR)
+    if (be16_to_cpu(ncore->di_mode) & S_IFDIR) {
 	inode->mode = DT_DIR;
-    else if (be16_to_cpu(ncore->di_mode) & S_IFREG)
+	xfs_debug("Found a directory inode!");
+    } else if (be16_to_cpu(ncore->di_mode) & S_IFREG) {
 	inode->mode = DT_REG;
-
-    xfs_debug("Found a %s inode", inode->mode == DT_DIR ? "directory" : "file");
+	xfs_debug("Found a file inode!");
+	xfs_debug("inode size %llu", inode->size);
+    }
 
     xfs_ino_core_free(inode, ncore);
 
     return inode;
 }
 
+static uint32_t xfs_getfssec(struct file *file, char *buf, int sectors,
+			     bool *have_more)
+{
+    xfs_debug("in");
+
+    return generic_getfssec(file, buf, sectors, have_more);
+}
+
+static int xfs_next_extent(struct inode *inode, uint32_t lstart)
+{
+    struct fs_info *fs = inode->fs;
+    xfs_dinode_t *core = NULL;
+    xfs_bmbt_rec_t *rec;
+    uint64_t startoff;
+    uint64_t startblock;
+    uint64_t blockcount;
+    block_t blk;
+
+    (void)lstart;
+
+    xfs_debug("in");
+
+    /* Check if we need the region for the chunk of 64 inodes */
+    if (XFS_PVT(inode)->i_chunk_offset) {
+	core = (xfs_dinode_t *)((uint8_t *)xfs_get_ino_chunk(fs, inode->ino) +
+				XFS_PVT(inode)->i_chunk_offset);
+
+	xfs_debug("core's magic number 0x%04x", be16_to_cpu(core->di_magic));
+
+	if (be16_to_cpu(core->di_magic) !=
+	    be16_to_cpu(*(uint16_t *)XFS_DINODE_MAGIC)) {
+	    xfs_error("Inode core's magic number does not match!");
+	    goto out;
+	}
+    } else {
+	core = xfs_get_ino_core(fs, inode->ino);
+    }
+
+    if (core->di_format == XFS_DINODE_FMT_EXTENTS) {
+	/* The data fork contains the file's data extents */
+	if (XFS_PVT(inode)->i_cur_extent == be32_to_cpu(core->di_nextents))
+	    goto out;
+
+	rec = (xfs_bmbt_rec_t *)&core->di_literal_area[0] +
+				XFS_PVT(inode)->i_cur_extent++;
+
+	xfs_debug("l0 0x%llx l1 0x%llx", rec->l0, rec->l1);
+
+	/* l0:9-62 are startoff */
+	startoff = (be64_to_cpu(rec->l0) & ((1ULL << 63) -1)) >> 9;
+	/* l0:0-8 and l1:21-63 are startblock */
+	startblock = (be64_to_cpu(rec->l0) & ((1ULL << 9) - 1)) |
+			(be64_to_cpu(rec->l1) >> 21);
+	/* l1:0-20 are blockcount */
+	blockcount = be64_to_cpu(rec->l1) & ((1ULL << 21) - 1);
+
+	xfs_debug("startoff 0x%llx startblock 0x%llx blockcount 0x%llx",
+		  startoff, startblock, blockcount);
+
+	blk = fsblock_to_bytes(fs, startblock) >> BLOCK_SHIFT(fs);
+
+	xfs_debug("blk %llu", blk);
+
+	XFS_PVT(inode)->i_offset = startoff;
+
+	inode->next_extent.pstart = blk << BLOCK_SHIFT(fs) >> SECTOR_SHIFT(fs);
+	inode->next_extent.len = ((blockcount << BLOCK_SHIFT(fs)) +
+				  SECTOR_SIZE(fs) - 1) >> SECTOR_SHIFT(fs);
+    }
+
+    return 0;
+
+out:
+    return -1;
+}
+
 static struct inode *xfs_iget(const char *dname, struct inode *parent)
 {
     struct fs_info *fs = parent->fs;
@@ -360,12 +438,21 @@ static struct inode *xfs_iget(const char *dname, struct inode *parent)
     /* TODO: Handle both shortform and block directories */
     if (core->di_format == XFS_DINODE_FMT_LOCAL) {
 	inode = xfs_fmt_local_find_entry(dname, parent, core);
+	if (!inode) {
+	    xfs_error("Entry not found!");
+	    goto out;
+	}
     } else {
 	xfs_debug("format %hhu", core->di_format);
 	xfs_debug("TODO: format \"local\" is the only supported ATM");
 	goto out;
     }
 
+    if (inode->mode == DT_REG) {
+	XFS_PVT(inode)->i_offset = 0;
+	XFS_PVT(inode)->i_cur_extent = 0;
+    }
+
     xfs_ino_core_free(inode, core);
 
     return inode;
@@ -557,11 +644,11 @@ const struct fs_ops xfs_fs_ops = {
     .fs_init		= xfs_fs_init,
     .iget_root		= xfs_iget_root,
     .searchdir		= NULL,
-    .getfssec		= NULL,
+    .getfssec		= xfs_getfssec,
     .load_config	= generic_load_config,
     .close_file         = generic_close_file,
     .mangle_name	= generic_mangle_name,
     .readdir		= NULL,
     .iget		= xfs_iget,
-    .next_extent	= NULL,
+    .next_extent	= xfs_next_extent,
 };
diff --git a/core/fs/xfs/xfs.h b/core/fs/xfs/xfs.h
index 17720f8..73fee37 100644
--- a/core/fs/xfs/xfs.h
+++ b/core/fs/xfs/xfs.h
@@ -72,15 +72,21 @@ struct xfs_fs_info;
     (((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
      ((xfs_ino_t)XFS_DI_HI(di) << 32))
 
+#define XFS_FSB_TO_AGNO(fs, fsbno) \
+    ((xfs_agnumber_t)((fsbno) >> XFS_INFO((fs))->agblk_shift))
+#define XFS_FSB_TO_AGBNO(fs, fsbno) \
+    ((xfs_agblock_t)((fsbno) & (uint32_t)((1ULL << \
+					   XFS_INFO((fs))->agblk_shift) - 1)))
+
 #define agblock_to_bytes(fs, x) \
     ((uint64_t)(x) << BLOCK_SHIFT((fs)))
 #define agino_to_bytes(fs, x) \
     ((uint64_t)(x) << XFS_INFO((fs))->inode_shift)
 #define agnumber_to_bytes(fs, x) \
     agblock_to_bytes(fs, (uint64_t)(x) * XFS_INFO((fs))->agblocks)
-#define fsblock_to_bytes(x)     \
-    (agnumber_to_bytes(fs, XFS_FSB_TO_AGNO(mp, (x))) +	\
-     agblock_to_bytes(fs, XFS_FSB_TO_AGBNO(mp, (x))))
+#define fsblock_to_bytes(fs,x)				\
+    (agnumber_to_bytes(fs, XFS_FSB_TO_AGNO(fs, (x))) +	\
+     agblock_to_bytes(fs, XFS_FSB_TO_AGBNO(fs, (x))))
 #define ino_to_bytes(fs, x)			   \
     (agnumber_to_bytes(fs, XFS_INO_TO_AGNO(fs, (x))) +	\
      agino_to_bytes(fs, XFS_INO_TO_AGINO(fs, (x))))
@@ -286,6 +292,8 @@ struct xfs_inode {
     xfs_agblock_t 	i_agblock;
     block_t		i_ino_blk;
     uint64_t		i_chunk_offset;
+    uint64_t		i_offset;
+    uint32_t		i_cur_extent;
 };
 
 typedef struct { uint8_t i[8]; } __attribute__((__packed__)) xfs_dir2_ino8_t;
@@ -316,6 +324,18 @@ typedef struct xfs_dir2_sf {
     xfs_dir2_sf_entry_t     list[1];        /* shortform entries */
 } __attribute__((__packed__)) xfs_dir2_sf_t;
 
+typedef enum {
+    XFS_EXT_NORM,
+    XFS_EXT_UNWRITTEN,
+    XFS_EXT_DMAPI_OFFLINE,
+    XFS_EXT_INVALID,
+} xfs_exntst_t;
+
+typedef struct xfs_bmbt_rec {
+    uint64_t l0;
+    uint64_t l1;
+} __attribute__((__packed__)) xfs_bmbt_rec_t;
+
 typedef xfs_ino_t	xfs_intino_t;
 
 static inline xfs_intino_t xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp,
diff --git a/core/fs/xfs/xfs_ag.h b/core/fs/xfs/xfs_ag.h
index 808e1c9..a2988b1 100644
--- a/core/fs/xfs/xfs_ag.h
+++ b/core/fs/xfs/xfs_ag.h
@@ -175,17 +175,6 @@ typedef struct xfs_agfl {
 		(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.


More information about the Syslinux-commits mailing list