* XFS support for pygrub patch
@ 2010-11-26 11:16 Marco Nenciarini
2010-12-13 17:06 ` Stefano Stabellini
0 siblings, 1 reply; 12+ messages in thread
From: Marco Nenciarini @ 2010-11-26 11:16 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 255 bytes --]
Hi,
I've ported the xfs code from grub to pygrub for our company internal use.
If you find it useful fell free to merge with main code.
Regards,
Marco
--
Marco Nenciarini - System manager @ Devise.IT
marco.nenciarini@devise.it | http://www.devise.it
[-- Attachment #2: pygrub-xfs-support.patch --]
[-- Type: text/x-patch, Size: 34956 bytes --]
diff -r 14709d196e43 tools/libfsimage/Makefile
--- a/tools/libfsimage/Makefile Wed Jun 30 18:26:13 2010 +0100
+++ b/tools/libfsimage/Makefile Fri Nov 26 12:10:07 2010 +0100
@@ -1,7 +1,7 @@
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
-SUBDIRS-y = common ufs reiserfs iso9660 fat zfs
+SUBDIRS-y = common ufs reiserfs iso9660 fat zfs xfs
SUBDIRS-y += $(shell env CC="$(CC)" ./check-libext2fs)
.PHONY: all clean install
diff -r 14709d196e43 tools/libfsimage/xfs/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/xfs/Makefile Fri Nov 26 12:10:07 2010 +0100
@@ -0,0 +1,13 @@
+XEN_ROOT = ../../..
+
+LIB_SRCS-y = fsys_xfs.c
+
+FS = xfs
+
+.PHONY: all
+all: fs-all
+
+.PHONY: install
+install: fs-install
+
+include $(XEN_ROOT)/tools/libfsimage/Rules.mk
diff -r 14709d196e43 tools/libfsimage/xfs/fsys_xfs.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/xfs/fsys_xfs.c Fri Nov 26 12:10:07 2010 +0100
@@ -0,0 +1,637 @@
+/* fsys_xfs.c - an implementation for the SGI XFS file system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will 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 to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <fsimage_grub.h>
+#include <limits.h>
+#include "xfs.h"
+
+#define MAX_LINK_COUNT 8
+
+typedef struct xad {
+ xfs_fileoff_t offset;
+ xfs_fsblock_t start;
+ xfs_filblks_t len;
+} xad_t;
+
+struct xfs_info {
+ int bsize;
+ int dirbsize;
+ int isize;
+ unsigned int agblocks;
+ int bdlog;
+ int blklog;
+ int inopblog;
+ int agblklog;
+ int agnolog;
+ unsigned int nextents;
+ xfs_daddr_t next;
+ xfs_daddr_t daddr;
+ xfs_dablk_t forw;
+ xfs_dablk_t dablk;
+ xfs_bmbt_rec_32_t *xt;
+ xfs_bmbt_ptr_t ptr0;
+ int btnode_ptr0_off;
+ int i8param;
+ int dirpos;
+ int dirmax;
+ int blkoff;
+ int fpos;
+ xfs_ino_t rootino;
+};
+
+static struct xfs_info xfs;
+
+#define dirbuf ((char *)FSYS_BUF)
+#define filebuf ((char *)FSYS_BUF + 4096)
+#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
+#define icore (inode->di_core)
+
+#define mask32lo(n) (((xfs_uint32_t)1 << (n)) - 1)
+
+#define XFS_INO_MASK(k) ((xfs_uint32_t)((1ULL << (k)) - 1))
+#define XFS_INO_OFFSET_BITS xfs.inopblog
+#define XFS_INO_AGBNO_BITS xfs.agblklog
+#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog)
+#define XFS_INO_AGNO_BITS xfs.agnolog
+
+static inline xfs_agblock_t
+agino2agbno (xfs_agino_t agino)
+{
+ return agino >> XFS_INO_OFFSET_BITS;
+}
+
+static inline xfs_agnumber_t
+ino2agno (xfs_ino_t ino)
+{
+ return ino >> XFS_INO_AGINO_BITS;
+}
+
+static inline xfs_agino_t
+ino2agino (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
+}
+
+static inline int
+ino2offset (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
+}
+
+static inline xfs_uint16_t
+le16 (xfs_uint16_t x)
+{
+ __asm__("xchgb %b0,%h0" \
+ : "=q" (x) \
+ : "0" (x)); \
+ return x;
+}
+
+static inline xfs_uint32_t
+le32 (xfs_uint32_t x)
+{
+#if 0
+ /* 386 doesn't have bswap. */
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+#else
+ /* This is slower but this works on all x86 architectures. */
+ __asm__("xchgb %b0, %h0" \
+ "\n\troll $16, %0" \
+ "\n\txchgb %b0, %h0" \
+ : "=q" (x) : "0" (x));
+#endif
+ return x;
+}
+
+static inline xfs_uint64_t
+le64 (xfs_uint64_t x)
+{
+ xfs_uint32_t h = x >> 32;
+ xfs_uint32_t l = x & ((1ULL<<32)-1);
+ return (((xfs_uint64_t)le32(l)) << 32) | ((xfs_uint64_t)(le32(h)));
+}
+
+
+static xfs_fsblock_t
+xt_start (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
+ (((xfs_fsblock_t)le32 (r->l2)) << 11) |
+ (((xfs_fsblock_t)le32 (r->l3)) >> 21);
+}
+
+static xfs_fileoff_t
+xt_offset (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fileoff_t)le32 (r->l0) &
+ mask32lo(31)) << 23) |
+ (((xfs_fileoff_t)le32 (r->l1)) >> 9);
+}
+
+static xfs_filblks_t
+xt_len (xfs_bmbt_rec_32_t *r)
+{
+ return le32(r->l3) & mask32lo(21);
+}
+
+static inline int
+xfs_highbit32(xfs_uint32_t v)
+{
+ int i;
+
+ if (--v) {
+ for (i = 0; i < 31; i++, v >>= 1) {
+ if (v == 0)
+ return i;
+ }
+ }
+ return 0;
+}
+
+static int
+isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
+{
+ return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
+}
+
+static xfs_daddr_t
+agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
+{
+ return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
+}
+
+static xfs_daddr_t
+fsb2daddr (xfs_fsblock_t fsbno)
+{
+ return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
+ (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
+}
+
+#undef offsetof
+#define offsetof(t,m) ((size_t)&(((t *)0)->m))
+
+static inline int
+btroot_maxrecs (fsi_file_t *ffi)
+{
+ int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
+
+ return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
+}
+
+static int
+di_read (fsi_file_t *ffi, xfs_ino_t ino)
+{
+ xfs_agino_t agino;
+ xfs_agnumber_t agno;
+ xfs_agblock_t agbno;
+ xfs_daddr_t daddr;
+ int offset;
+
+ agno = ino2agno (ino);
+ agino = ino2agino (ino);
+ agbno = agino2agbno (agino);
+ offset = ino2offset (ino);
+ daddr = agb2daddr (agno, agbno);
+
+ devread (ffi, daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+
+ xfs.ptr0 = *(xfs_bmbt_ptr_t *)
+ (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
+ + btroot_maxrecs (ffi)*sizeof(xfs_bmbt_key_t));
+
+ return 1;
+}
+
+static void
+init_extents (fsi_file_t *ffi)
+{
+ xfs_bmbt_ptr_t ptr0;
+ xfs_btree_lblock_t h;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ xfs.xt = inode->di_u.di_bmx;
+ xfs.nextents = le32 (icore.di_nextents);
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ ptr0 = xfs.ptr0;
+ for (;;) {
+ xfs.daddr = fsb2daddr (le64(ptr0));
+ devread (ffi, xfs.daddr, 0,
+ sizeof(xfs_btree_lblock_t), (char *)&h);
+ if (!h.bb_level) {
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ return;
+ }
+ devread (ffi, xfs.daddr, xfs.btnode_ptr0_off,
+ sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
+ }
+ }
+}
+
+static xad_t *
+next_extent (fsi_file_t *ffi)
+{
+ static xad_t xad;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ if (xfs.nextents == 0)
+ return NULL;
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ if (xfs.nextents == 0) {
+ xfs_btree_lblock_t h;
+ if (xfs.next == 0)
+ return NULL;
+ xfs.daddr = xfs.next;
+ devread (ffi, xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ }
+ /* Yeah, I know that's slow, but I really don't care */
+ devread (ffi, xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
+ xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
+ xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
+ }
+ xad.offset = xt_offset (xfs.xt);
+ xad.start = xt_start (xfs.xt);
+ xad.len = xt_len (xfs.xt);
+ ++xfs.xt;
+ --xfs.nextents;
+
+ return &xad;
+}
+
+/*
+ * Name lies - the function reads only first 100 bytes
+ */
+static void
+xfs_dabread (fsi_file_t *ffi)
+{
+ xad_t *xad;
+ xfs_fileoff_t offset;;
+
+ init_extents (ffi);
+ while ((xad = next_extent (ffi))) {
+ offset = xad->offset;
+ if (isinxt (xfs.dablk, offset, xad->len)) {
+ devread (ffi, fsb2daddr (xad->start + xfs.dablk - offset),
+ 0, 100, dirbuf);
+ break;
+ }
+ }
+}
+
+static inline xfs_ino_t
+sf_ino (char *sfe, int namelen)
+{
+ void *p = sfe + namelen + 3;
+
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)p) : le32(*(xfs_uint32_t *)p);
+}
+
+static inline xfs_ino_t
+sf_parent_ino (fsi_file_t *ffi)
+{
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
+ : le32(*(xfs_uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
+}
+
+static inline int
+roundup8 (int n)
+{
+ return ((n+7)&~7);
+}
+
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len);
+
+static char *
+next_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
+{
+ int namelen = 1;
+ int toread;
+ static char usual[2][3] = {".", ".."};
+ static xfs_dir2_sf_entry_t *sfe;
+ char *name = usual[0];
+
+ if (xfs.dirpos >= xfs.dirmax) {
+ if (xfs.forw == 0)
+ return NULL;
+ xfs.dablk = xfs.forw;
+ xfs_dabread (ffi);
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+#undef h
+ xfs.dirpos = 0;
+ }
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ switch (xfs.dirpos) {
+ case -2:
+ *ino = 0;
+ break;
+ case -1:
+ *ino = sf_parent_ino (ffi);
+ ++name;
+ ++namelen;
+ sfe = (xfs_dir2_sf_entry_t *)
+ (inode->di_u.di_c
+ + sizeof(xfs_dir2_sf_hdr_t)
+ - xfs.i8param);
+ break;
+ default:
+ namelen = sfe->namelen;
+ *ino = sf_ino ((char *)sfe, namelen);
+ name = (char *)sfe->name;
+ sfe = (xfs_dir2_sf_entry_t *)
+ ((char *)sfe + namelen + 11 - xfs.i8param);
+ }
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_EXTENTS:
+#define dau ((xfs_dir2_data_union_t *)dirbuf)
+ for (;;) {
+ if (xfs.blkoff >= xfs.dirbsize) {
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos &= ~(xfs.dirbsize - 1);
+ filepos |= xfs.blkoff;
+ }
+ xfs_read (ffi, dirbuf, 4);
+ xfs.blkoff += 4;
+ if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
+ toread = roundup8 (le16(dau->unused.length)) - 4;
+ xfs.blkoff += toread;
+ filepos += toread;
+ continue;
+ }
+ break;
+ }
+ xfs_read (ffi, (char *)dirbuf + 4, 5);
+ *ino = le64 (dau->entry.inumber);
+ namelen = dau->entry.namelen;
+#undef dau
+ toread = roundup8 (namelen + 11) - 9;
+ xfs_read (ffi, dirbuf, toread);
+ name = (char *)dirbuf;
+ xfs.blkoff += toread + 5;
+ }
+ ++xfs.dirpos;
+ name[namelen] = 0;
+
+ return name;
+}
+
+static char *
+first_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
+{
+ xfs.forw = 0;
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
+ xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
+ xfs.dirpos = -2;
+ break;
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ filepos = 0;
+ xfs_read (ffi, dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
+#define tail ((xfs_dir2_block_tail_t *)dirbuf)
+ filepos = xfs.dirbsize - sizeof(*tail);
+ xfs_read (ffi, dirbuf, sizeof(*tail));
+ xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
+#undef tail
+ } else {
+ xfs.dablk = (1ULL << 35) >> xfs.blklog;
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+#define n ((xfs_da_intnode_t *)dirbuf)
+ for (;;) {
+ xfs_dabread (ffi);
+ if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
+ || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+ break;
+ }
+ xfs.dablk = le32 (n->btree[0].before);
+ }
+#undef n
+#undef h
+ }
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos = xfs.blkoff;
+ xfs.dirpos = 0;
+ }
+ return next_dentry (ffi, ino);
+}
+
+static int
+xfs_mount (fsi_file_t *ffi, const char *options)
+{
+ xfs_sb_t super;
+
+ if (!devread (ffi, 0, 0, sizeof(super), (char *)&super)
+ || (le32(super.sb_magicnum) != XFS_SB_MAGIC)
+ || ((le16(super.sb_versionnum)
+ & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
+ return 0;
+ }
+
+ xfs.bsize = le32 (super.sb_blocksize);
+ xfs.blklog = super.sb_blocklog;
+ xfs.bdlog = xfs.blklog - SECTOR_BITS;
+ xfs.rootino = le64 (super.sb_rootino);
+ xfs.isize = le16 (super.sb_inodesize);
+ xfs.agblocks = le32 (super.sb_agblocks);
+ xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
+
+ xfs.inopblog = super.sb_inopblog;
+ xfs.agblklog = super.sb_agblklog;
+ xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));
+
+ xfs.btnode_ptr0_off =
+ ((xfs.bsize - sizeof(xfs_btree_block_t)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
+ * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
+
+ return 1;
+}
+
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len)
+{
+ xad_t *xad;
+ xfs_fileoff_t endofprev, endofcur, offset;
+ xfs_filblks_t xadlen;
+ int toread, startpos, endpos;
+
+ if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
+ grub_memmove (buf, inode->di_u.di_c + filepos, len);
+ filepos += len;
+ return len;
+ }
+
+ startpos = filepos;
+ endpos = filepos + len;
+ endofprev = (xfs_fileoff_t)-1;
+ init_extents (ffi);
+ while (len > 0 && (xad = next_extent (ffi))) {
+ offset = xad->offset;
+ xadlen = xad->len;
+ if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
+ endofcur = (offset + xadlen) << xfs.blklog;
+ toread = (endofcur >= endpos)
+ ? len : (endofcur - filepos);
+
+ disk_read_func = disk_read_hook;
+ devread (ffi, fsb2daddr (xad->start),
+ filepos - (offset << xfs.blklog), toread, buf);
+ disk_read_func = NULL;
+
+ buf += toread;
+ len -= toread;
+ filepos += toread;
+ } else if (offset > endofprev) {
+ toread = ((offset << xfs.blklog) >= endpos)
+ ? len : ((offset - endofprev) << xfs.blklog);
+ len -= toread;
+ filepos += toread;
+ for (; toread; toread--) {
+ *buf++ = 0;
+ }
+ continue;
+ }
+ endofprev = offset + xadlen;
+ }
+
+ return filepos - startpos;
+}
+
+static int
+xfs_dir (fsi_file_t *ffi, char *dirname)
+{
+ xfs_ino_t ino, parent_ino, new_ino;
+ xfs_fsize_t di_size;
+ int di_mode;
+ int cmp, n, link_count;
+ char linkbuf[xfs.bsize];
+ char *rest, *name, ch;
+
+ parent_ino = ino = xfs.rootino;
+ link_count = 0;
+ for (;;) {
+ di_read (ffi, ino);
+ di_size = le64 (icore.di_size);
+ di_mode = le16 (icore.di_mode);
+
+ if ((di_mode & IFMT) == IFLNK) {
+ if (++link_count > MAX_LINK_COUNT) {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+ if (di_size < xfs.bsize - 1) {
+ filepos = 0;
+ filemax = di_size;
+ n = xfs_read (ffi, linkbuf, filemax);
+ } else {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
+ while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
+ linkbuf[n] = 0;
+ dirname = linkbuf;
+ continue;
+ }
+
+ if (!*dirname || isspace (*dirname)) {
+ if ((di_mode & IFMT) != IFREG) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ filepos = 0;
+ filemax = di_size;
+ return 1;
+ }
+
+ if ((di_mode & IFMT) != IFDIR) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ for (; *dirname == '/'; dirname++);
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+ name = first_dentry (ffi, &new_ino);
+ for (;;) {
+ cmp = (!*dirname) ? -1 : substring (dirname, name);
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/' && cmp <= 0) {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (name);
+ } else
+#endif
+ if (cmp == 0) {
+ parent_ino = ino;
+ if (new_ino)
+ ino = new_ino;
+ *(dirname = rest) = ch;
+ break;
+ }
+ name = next_dentry (ffi, &new_ino);
+ if (name == NULL) {
+ if (print_possibilities < 0)
+ return 1;
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+ }
+ }
+ }
+}
+
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+ static fsig_plugin_ops_t ops = {
+ FSIMAGE_PLUGIN_VERSION,
+ .fpo_mount = xfs_mount,
+ .fpo_dir = xfs_dir,
+ .fpo_read = xfs_read
+ };
+
+ *name = "xfs";
+ return (fsig_init(fp, &ops));
+}
diff -r 14709d196e43 tools/libfsimage/xfs/xfs.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/xfs/xfs.h Fri Nov 26 12:10:07 2010 +0100
@@ -0,0 +1,544 @@
+/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2001,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+typedef signed char xfs_int8_t;
+typedef unsigned char xfs_uint8_t;
+typedef short xfs_int16_t;
+typedef unsigned short xfs_uint16_t;
+typedef int xfs_int32_t;
+typedef unsigned int xfs_uint32_t;
+typedef long long xfs_int64_t;
+typedef unsigned long long xfs_uint64_t;
+
+typedef xfs_uint64_t xfs_ino_t;
+typedef xfs_uint32_t xfs_agino_t;
+typedef xfs_int64_t xfs_daddr_t;
+typedef xfs_int64_t xfs_off_t;
+typedef xfs_uint8_t uuid_t[16];
+
+
+/* those are from xfs_types.h */
+
+typedef xfs_uint32_t xfs_agblock_t; /* blockno in alloc. group */
+typedef xfs_uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef xfs_uint32_t xfs_agnumber_t; /* allocation group number */
+typedef xfs_int32_t xfs_extnum_t; /* # of extents in a file */
+typedef xfs_int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef xfs_int64_t xfs_fsize_t; /* bytes in a file */
+
+typedef xfs_uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
+typedef xfs_uint32_t xfs_dahash_t; /* dir/attr hash value */
+
+/*
+ * Disk based types:
+ */
+typedef xfs_uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
+typedef xfs_uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
+typedef xfs_uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
+typedef xfs_uint64_t xfs_dfiloff_t; /* block number in a file */
+
+typedef xfs_uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
+typedef xfs_uint64_t xfs_fileoff_t; /* block number in a file */
+typedef xfs_uint64_t xfs_filblks_t; /* number of blocks in a file */
+
+
+/* those are from xfs_sb.h */
+
+#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/
+#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
+#define XFS_SB_VERSION_NUMBITS 0x000f
+
+typedef struct xfs_sb
+{
+ xfs_uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ xfs_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 */
+ xfs_uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
+ xfs_uint16_t sb_sectsize; /* volume sector size, bytes */
+ xfs_uint16_t sb_inodesize; /* inode size, bytes */
+ xfs_uint16_t sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ xfs_uint8_t sb_blocklog; /* log2 of sb_blocksize */
+ xfs_uint8_t sb_sectlog; /* log2 of sb_sectsize */
+ xfs_uint8_t sb_inodelog; /* log2 of sb_inodesize */
+ xfs_uint8_t sb_inopblog; /* log2 of sb_inopblock */
+ xfs_uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ xfs_uint8_t sb_rextslog; /* log2 of sb_rextents */
+ xfs_uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
+ xfs_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().
+ */
+ xfs_uint64_t sb_icount; /* allocated inodes */
+ xfs_uint64_t sb_ifree; /* free inodes */
+ xfs_uint64_t sb_fdblocks; /* free data blocks */
+ xfs_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 */
+ xfs_uint16_t sb_qflags; /* quota flags */
+ xfs_uint8_t sb_flags; /* misc. flags */
+ xfs_uint8_t sb_shared_vn; /* shared version number */
+ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ xfs_uint32_t sb_unit; /* stripe or raid unit */
+ xfs_uint32_t sb_width; /* stripe or raid width */
+ xfs_uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
+ xfs_uint8_t sb_dummy[7]; /* padding */
+} xfs_sb_t;
+
+
+/* those are from xfs_btree.h */
+
+/*
+ * Long form header: bmap btrees.
+ */
+typedef struct xfs_btree_lblock
+{
+ xfs_uint32_t bb_magic; /* magic number for block type */
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+ xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */
+ xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */
+} xfs_btree_lblock_t;
+
+/*
+ * Combined header and structure, used by common code.
+ */
+typedef struct xfs_btree_hdr
+{
+ xfs_uint32_t bb_magic; /* magic number for block type */
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+} xfs_btree_hdr_t;
+
+typedef struct xfs_btree_block
+{
+ xfs_btree_hdr_t bb_h; /* header */
+ union {
+ struct {
+ xfs_agblock_t bb_leftsib;
+ xfs_agblock_t bb_rightsib;
+ } s; /* short form pointers */
+ struct {
+ xfs_dfsbno_t bb_leftsib;
+ xfs_dfsbno_t bb_rightsib;
+ } l; /* long form pointers */
+ } bb_u; /* rest */
+} xfs_btree_block_t;
+
+/* those are from xfs_bmap_btree.h */
+
+/*
+ * Bmap root header, on-disk form only.
+ */
+typedef struct xfs_bmdr_block
+{
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+} xfs_bmdr_block_t;
+
+/*
+ * Bmap btree record and extent descriptor.
+ * For 32-bit kernels,
+ * l0:31 is an extent flag (value 1 indicates non-normal).
+ * l0:0-30 and l1:9-31 are startoff.
+ * l1:0-8, l2:0-31, and l3:21-31 are startblock.
+ * l3:0-20 are blockcount.
+ * For 64-bit kernels,
+ * l0:63 is an extent flag (value 1 indicates non-normal).
+ * l0:9-62 are startoff.
+ * l0:0-8 and l1:21-63 are startblock.
+ * l1:0-20 are blockcount.
+ */
+
+#define BMBT_USE_64 1
+
+typedef struct xfs_bmbt_rec_32
+{
+ xfs_uint32_t l0, l1, l2, l3;
+} xfs_bmbt_rec_32_t;
+typedef struct xfs_bmbt_rec_64
+{
+ xfs_uint64_t l0, l1;
+} xfs_bmbt_rec_64_t;
+
+#if BMBT_USE_64
+typedef xfs_uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#else /* !BMBT_USE_64 */
+typedef xfs_uint32_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#endif /* BMBT_USE_64 */
+
+/*
+ * Key structure for non-leaf levels of the tree.
+ */
+typedef struct xfs_bmbt_key
+{
+ xfs_dfiloff_t br_startoff; /* starting file offset */
+} xfs_bmbt_key_t, xfs_bmdr_key_t;
+
+typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
+ /* btree block header type */
+typedef struct xfs_btree_lblock xfs_bmbt_block_t;
+
+
+/* those are from xfs_dir2.h */
+/*
+ * Directory version 2.
+ * There are 4 possible formats:
+ * shortform
+ * single block - data with embedded leaf at the end
+ * multiple data blocks, single leaf+freeindex block
+ * data blocks, node&leaf blocks (btree), freeindex blocks
+ *
+ * The shortform format is in xfs_dir2_sf.h.
+ * The single block format is in xfs_dir2_block.h.
+ * The data block format is in xfs_dir2_data.h.
+ * The leaf and freeindex block formats are in xfs_dir2_leaf.h.
+ * Node blocks are the same as the other version, in xfs_da_btree.h.
+ */
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef xfs_uint16_t xfs_dir2_data_off_t;
+
+/*
+ * Byte offset in a directory.
+ */
+typedef xfs_off_t xfs_dir2_off_t;
+
+/* those are from xfs_da_btree.h */
+/*========================================================================
+ * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
+ *========================================================================*/
+
+/*
+ * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
+ *
+ * Is is used to manage a doubly linked list of all blocks at the same
+ * level in the Btree, and to identify which type of block this is.
+ */
+#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
+
+typedef struct xfs_da_blkinfo {
+ xfs_dablk_t forw; /* previous block in list */
+ xfs_dablk_t back; /* following block in list */
+ xfs_uint16_t magic; /* validity check on block */
+ xfs_uint16_t pad; /* unused */
+} xfs_da_blkinfo_t;
+
+/*
+ * This is the structure of the root and intermediate nodes in the Btree.
+ * The leaf nodes are defined above.
+ *
+ * Entries are not packed.
+ *
+ * Since we have duplicate keys, use a binary search but always follow
+ * all match in the block, not just the first match found.
+ */
+
+typedef struct xfs_da_intnode {
+ struct xfs_da_node_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ xfs_uint16_t count; /* count of active entries */
+ xfs_uint16_t level; /* level above leaves (leaf == 0) */
+ } hdr;
+ struct xfs_da_node_entry {
+ xfs_dahash_t hashval; /* hash value for this descendant */
+ xfs_dablk_t before; /* Btree block before this key */
+ } btree[1]; /* variable sized array of keys */
+} xfs_da_intnode_t;
+
+
+/* those are from xfs_dir2_data.h */
+/*
+ * Directory format 2, data block structures.
+ */
+
+/*
+ * Constants.
+ */
+#define XFS_DIR2_DATA_FREE_TAG 0xffff
+#define XFS_DIR2_DATA_FD_COUNT 3
+
+/*
+ * Structures.
+ */
+
+/*
+ * Describe a free area in the data block.
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+ xfs_dir2_data_off_t offset; /* start of freespace */
+ xfs_dir2_data_off_t length; /* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ * Always at the beginning of a directory-sized block.
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+ xfs_uint32_t magic; /* XFS_DIR2_DATA_MAGIC */
+ /* or XFS_DIR2_BLOCK_MAGIC */
+ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * Active entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_entry {
+ xfs_ino_t inumber; /* inode number */
+ xfs_uint8_t namelen; /* name length */
+ xfs_uint8_t name[1]; /* name bytes, no null */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_unused {
+ xfs_uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
+ xfs_dir2_data_off_t length; /* total free length */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+typedef union {
+ xfs_dir2_data_entry_t entry;
+ xfs_dir2_data_unused_t unused;
+} xfs_dir2_data_union_t;
+
+
+/* those are from xfs_dir2_leaf.h */
+/*
+ * Directory version 2, leaf block structures.
+ */
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+ xfs_da_blkinfo_t info; /* header for da routines */
+ xfs_uint16_t count; /* count of entries */
+ xfs_uint16_t stale; /* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+
+/* those are from xfs_dir2_block.h */
+/*
+ * xfs_dir2_block.h
+ * Directory version 2, single block format structures
+ */
+
+/*
+ * The single block format is as follows:
+ * xfs_dir2_data_hdr_t structure
+ * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
+ * xfs_dir2_leaf_entry_t structures
+ * xfs_dir2_block_tail_t structure
+ */
+
+#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
+
+typedef struct xfs_dir2_block_tail {
+ xfs_uint32_t count; /* count of leaf entries */
+ xfs_uint32_t stale; /* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+
+/* those are from xfs_dir2_sf.h */
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to
+ * fit into the literal area of the inode.
+ */
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef struct { xfs_uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { xfs_uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+ xfs_dir2_ino8_t i8;
+ xfs_dir2_ino4_t i4;
+} xfs_dir2_inou_t;
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { xfs_uint8_t i[2]; } xfs_dir2_sf_off_t;
+
+/*
+ * The parent directory has a dedicated field, and the self-pointer must
+ * be calculated on the fly.
+ *
+ * Entries are packed toward the top as tightly as possible. The header
+ * and the elements must be bcopy()'d out into a work area to get correct
+ * alignment for the inode number fields.
+ */
+typedef struct xfs_dir2_sf_hdr {
+ xfs_uint8_t count; /* count of entries */
+ xfs_uint8_t i8count; /* count of 8-byte inode #s */
+ xfs_dir2_inou_t parent; /* parent dir inode number */
+} xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+ xfs_uint8_t namelen; /* actual name length */
+ xfs_dir2_sf_off_t offset; /* saved offset */
+ xfs_uint8_t name[1]; /* name, variable size */
+ xfs_dir2_inou_t inumber; /* inode number, var. offset */
+} xfs_dir2_sf_entry_t;
+
+typedef struct xfs_dir2_sf {
+ xfs_dir2_sf_hdr_t hdr; /* shortform header */
+ xfs_dir2_sf_entry_t list[1]; /* shortform entries */
+} xfs_dir2_sf_t;
+
+/* those are from xfs_dinode.h */
+
+#define XFS_DINODE_VERSION_1 1
+#define XFS_DINODE_VERSION_2 2
+#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
+
+/*
+ * Disk inode structure.
+ * This is just the header; the inode is expanded to fill a variable size
+ * with the last field expanding. It is split into the core and "other"
+ * because we only need the core part in the in-core inode.
+ */
+typedef struct xfs_timestamp {
+ xfs_int32_t t_sec; /* timestamp seconds */
+ xfs_int32_t t_nsec; /* timestamp nanoseconds */
+} xfs_timestamp_t;
+
+/*
+ * Note: Coordinate changes to this structure with the XFS_DI_* #defines
+ * below and the offsets table in xfs_ialloc_log_di().
+ */
+typedef struct xfs_dinode_core
+{
+ xfs_uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ xfs_uint16_t di_mode; /* mode and type of file */
+ xfs_int8_t di_version; /* inode version */
+ xfs_int8_t di_format; /* format of di_c data */
+ xfs_uint16_t di_onlink; /* old number of links to file */
+ xfs_uint32_t di_uid; /* owner's user id */
+ xfs_uint32_t di_gid; /* owner's group id */
+ xfs_uint32_t di_nlink; /* number of links to file */
+ xfs_uint16_t di_projid; /* owner's project id */
+ xfs_uint8_t di_pad[10]; /* unused, zeroed space */
+ 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 */
+ xfs_fsize_t di_size; /* number of bytes in file */
+ xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
+ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
+ xfs_extnum_t di_nextents; /* number of extents in data fork */
+ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ xfs_uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
+ xfs_int8_t di_aformat; /* format of attr fork's data */
+ xfs_uint32_t di_dmevmask; /* DMIG event mask */
+ xfs_uint16_t di_dmstate; /* DMIG state info */
+ xfs_uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
+ xfs_uint32_t di_gen; /* generation number */
+} xfs_dinode_core_t;
+
+typedef struct xfs_dinode
+{
+ xfs_dinode_core_t di_core;
+ xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
+ union {
+ xfs_bmdr_block_t di_bmbt; /* btree root block */
+ xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
+ xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
+ char di_c[1]; /* local contents */
+ } di_u;
+} xfs_dinode_t;
+
+/*
+ * Values for di_format
+ */
+typedef enum xfs_dinode_fmt
+{
+ XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
+ XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
+ /* LNK: di_symlink */
+ XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
+ XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
+ XFS_DINODE_FMT_UUID /* MNT: di_uuid */
+} xfs_dinode_fmt_t;
+
+/*
+ * File types (mode field)
+ */
+#define IFMT 0170000 /* type of file */
+#define IFDIR 0040000 /* directory */
+#define IFREG 0100000 /* regular */
+#define IFLNK 0120000 /* symbolic link */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
[not found] <22752968ADD47840A7D404102C7563B005A82DE827@vasco-be-exch2.vasco.com>
@ 2010-12-08 22:39 ` Marco Nenciarini
0 siblings, 0 replies; 12+ messages in thread
From: Marco Nenciarini @ 2010-12-08 22:39 UTC (permalink / raw)
To: Wouter D'Haeseleer; +Cc: xen-devel
On 08/12/2010 22:50, Wouter D'Haeseleer wrote:
> Hi Marco,
>
> I'm struggling with the same issue as you had.
> Did you by any change compiled it for debian amd64 ?
>
> I'm getting errors like:
> fsys_xfs.c:409: error: extended registers have no high halves
>
> Any idea what I can do to solve it?
>
I developed it on a CentOS, because I need it on a XCP server, and there
it works without problems.
I've just tried on a Debian unstable x86_64 and the problem is always
reproducible. Sincerely I have no idea on why it happens, but I've
discovered that turning off the optimization (with -O0) it compiles
without problems.
Maybe some gcc guru can suggest a better solution.
Regards,
Marco
--
Marco Nenciarini - System manager @ Devise.IT
marco.nenciarini@devise.it | http://www.devise.it
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2010-11-26 11:16 XFS support for pygrub patch Marco Nenciarini
@ 2010-12-13 17:06 ` Stefano Stabellini
2010-12-14 22:23 ` Marco Nenciarini
0 siblings, 1 reply; 12+ messages in thread
From: Stefano Stabellini @ 2010-12-13 17:06 UTC (permalink / raw)
To: Marco Nenciarini; +Cc: xen-devel@lists.xensource.com
On Fri, 26 Nov 2010, Marco Nenciarini wrote:
>
> Hi,
> I've ported the xfs code from grub to pygrub for our company internal use.
>
> If you find it useful fell free to merge with main code.
Can anybody test this patch and confirm it works properly?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2010-12-13 17:06 ` Stefano Stabellini
@ 2010-12-14 22:23 ` Marco Nenciarini
2010-12-23 15:27 ` Marco Nenciarini
0 siblings, 1 reply; 12+ messages in thread
From: Marco Nenciarini @ 2010-12-14 22:23 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: xen-devel@lists.xensource.com
[-- Attachment #1: Type: text/plain, Size: 1566 bytes --]
On 13/12/2010 18:06, Stefano Stabellini wrote:
> On Fri, 26 Nov 2010, Marco Nenciarini wrote:
>>
>> Hi,
>> I've ported the xfs code from grub to pygrub for our company internal use.
>>
>> If you find it useful fell free to merge with main code.
>
> Can anybody test this patch and confirm it works properly?
To help you testing the patch and auditing the code, I've attached to
this message the diff against xfs code in grub-0.97.
As stated before, the resulting fsimage.so works perfectly for me when
installed in XCP-0.5 as /usr/lib/fs/xfs/fsimage.so
Actually I've 3 Debian Squeeze machines and one Ubuntu 10.10 machine in
our testing environment booting from xfs with pygrub.
The only problem I've found is that the module doesn't compile on Debian
based system due to some bug in gcc code optimizer. On such a systems
the compiler returns the following error:
gcc -DPIC -O2 -fomit-frame-pointer -m64 -fno-strict-aliasing -std=gnu99
-Wall -Wstrict-prototypes -Wno-unused-value
-Wdeclaration-after-statement -D__XEN_TOOLS__ -MMD -MF .fsys_xfs.opic.d
-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
-I../../../tools/libfsimage/common/ -Werror -fPIC -c -o fsys_xfs.opic
fsys_xfs.c
fsys_xfs.c: In function ‘next_dentry’:
fsys_xfs.c:409: error: extended registers have no high halves
fsys_xfs.c:409: error: extended registers have no high halves
The problem disappear if you turn off optimization with -O0
Regards,
Marco
--
Marco Nenciarini - System manager @ Devise.IT
marco.nenciarini@devise.it | http://www.devise.it
[-- Attachment #2: fsys_xfs.c.diff --]
[-- Type: text/x-patch, Size: 9206 bytes --]
--- ../fsys_xfs.c 2010-11-16 11:23:01.560322529 +0100
+++ tools/libfsimage/xfs/fsys_xfs.c 2010-11-26 10:39:42.000000000 +0100
@@ -18,10 +18,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifdef FSYS_XFS
-
-#include "shared.h"
-#include "filesys.h"
+#include <fsimage_grub.h>
+#include <limits.h>
#include "xfs.h"
#define MAX_LINK_COUNT 8
@@ -97,7 +95,7 @@
return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
}
-static inline __const__ xfs_uint16_t
+static inline xfs_uint16_t
le16 (xfs_uint16_t x)
{
__asm__("xchgb %b0,%h0" \
@@ -106,7 +104,7 @@
return x;
}
-static inline __const__ xfs_uint32_t
+static inline xfs_uint32_t
le32 (xfs_uint32_t x)
{
#if 0
@@ -122,7 +120,7 @@
return x;
}
-static inline __const__ xfs_uint64_t
+static inline xfs_uint64_t
le64 (xfs_uint64_t x)
{
xfs_uint32_t h = x >> 32;
@@ -187,10 +185,10 @@
}
#undef offsetof
-#define offsetof(t,m) ((int)&(((t *)0)->m))
+#define offsetof(t,m) ((size_t)&(((t *)0)->m))
static inline int
-btroot_maxrecs (void)
+btroot_maxrecs (fsi_file_t *ffi)
{
int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
@@ -199,7 +197,7 @@
}
static int
-di_read (xfs_ino_t ino)
+di_read (fsi_file_t *ffi, xfs_ino_t ino)
{
xfs_agino_t agino;
xfs_agnumber_t agno;
@@ -213,17 +211,17 @@
offset = ino2offset (ino);
daddr = agb2daddr (agno, agbno);
- devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+ devread (ffi, daddr, offset*xfs.isize, xfs.isize, (char *)inode);
xfs.ptr0 = *(xfs_bmbt_ptr_t *)
(inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
- + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
+ + btroot_maxrecs (ffi)*sizeof(xfs_bmbt_key_t));
return 1;
}
static void
-init_extents (void)
+init_extents (fsi_file_t *ffi)
{
xfs_bmbt_ptr_t ptr0;
xfs_btree_lblock_t h;
@@ -237,7 +235,7 @@
ptr0 = xfs.ptr0;
for (;;) {
xfs.daddr = fsb2daddr (le64(ptr0));
- devread (xfs.daddr, 0,
+ devread (ffi, xfs.daddr, 0,
sizeof(xfs_btree_lblock_t), (char *)&h);
if (!h.bb_level) {
xfs.nextents = le16(h.bb_numrecs);
@@ -245,14 +243,14 @@
xfs.fpos = sizeof(xfs_btree_block_t);
return;
}
- devread (xfs.daddr, xfs.btnode_ptr0_off,
+ devread (ffi, xfs.daddr, xfs.btnode_ptr0_off,
sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
}
}
}
static xad_t *
-next_extent (void)
+next_extent (fsi_file_t *ffi)
{
static xad_t xad;
@@ -267,13 +265,13 @@
if (xfs.next == 0)
return NULL;
xfs.daddr = xfs.next;
- devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
+ devread (ffi, xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
xfs.nextents = le16(h.bb_numrecs);
xfs.next = fsb2daddr (le64(h.bb_rightsib));
xfs.fpos = sizeof(xfs_btree_block_t);
}
/* Yeah, I know that's slow, but I really don't care */
- devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
+ devread (ffi, xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
}
@@ -290,16 +288,16 @@
* Name lies - the function reads only first 100 bytes
*/
static void
-xfs_dabread (void)
+xfs_dabread (fsi_file_t *ffi)
{
xad_t *xad;
xfs_fileoff_t offset;;
- init_extents ();
- while ((xad = next_extent ())) {
+ init_extents (ffi);
+ while ((xad = next_extent (ffi))) {
offset = xad->offset;
if (isinxt (xfs.dablk, offset, xad->len)) {
- devread (fsb2daddr (xad->start + xfs.dablk - offset),
+ devread (ffi, fsb2daddr (xad->start + xfs.dablk - offset),
0, 100, dirbuf);
break;
}
@@ -316,7 +314,7 @@
}
static inline xfs_ino_t
-sf_parent_ino (void)
+sf_parent_ino (fsi_file_t *ffi)
{
return (xfs.i8param == 0)
? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
@@ -329,8 +327,11 @@
return ((n+7)&~7);
}
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len);
+
static char *
-next_dentry (xfs_ino_t *ino)
+next_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
{
int namelen = 1;
int toread;
@@ -342,7 +343,7 @@
if (xfs.forw == 0)
return NULL;
xfs.dablk = xfs.forw;
- xfs_dabread ();
+ xfs_dabread (ffi);
#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
xfs.dirmax = le16 (h->count) - le16 (h->stale);
xfs.forw = le32 (h->info.forw);
@@ -357,7 +358,7 @@
*ino = 0;
break;
case -1:
- *ino = sf_parent_ino ();
+ *ino = sf_parent_ino (ffi);
++name;
++namelen;
sfe = (xfs_dir2_sf_entry_t *)
@@ -368,7 +369,7 @@
default:
namelen = sfe->namelen;
*ino = sf_ino ((char *)sfe, namelen);
- name = sfe->name;
+ name = (char *)sfe->name;
sfe = (xfs_dir2_sf_entry_t *)
((char *)sfe + namelen + 11 - xfs.i8param);
}
@@ -382,7 +383,7 @@
filepos &= ~(xfs.dirbsize - 1);
filepos |= xfs.blkoff;
}
- xfs_read (dirbuf, 4);
+ xfs_read (ffi, dirbuf, 4);
xfs.blkoff += 4;
if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
toread = roundup8 (le16(dau->unused.length)) - 4;
@@ -392,12 +393,12 @@
}
break;
}
- xfs_read ((char *)dirbuf + 4, 5);
+ xfs_read (ffi, (char *)dirbuf + 4, 5);
*ino = le64 (dau->entry.inumber);
namelen = dau->entry.namelen;
#undef dau
toread = roundup8 (namelen + 11) - 9;
- xfs_read (dirbuf, toread);
+ xfs_read (ffi, dirbuf, toread);
name = (char *)dirbuf;
xfs.blkoff += toread + 5;
}
@@ -408,7 +409,7 @@
}
static char *
-first_dentry (xfs_ino_t *ino)
+first_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
{
xfs.forw = 0;
switch (icore.di_format) {
@@ -420,11 +421,11 @@
case XFS_DINODE_FMT_EXTENTS:
case XFS_DINODE_FMT_BTREE:
filepos = 0;
- xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ xfs_read (ffi, dirbuf, sizeof(xfs_dir2_data_hdr_t));
if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
#define tail ((xfs_dir2_block_tail_t *)dirbuf)
filepos = xfs.dirbsize - sizeof(*tail);
- xfs_read (dirbuf, sizeof(*tail));
+ xfs_read (ffi, dirbuf, sizeof(*tail));
xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
#undef tail
} else {
@@ -432,7 +433,7 @@
#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
#define n ((xfs_da_intnode_t *)dirbuf)
for (;;) {
- xfs_dabread ();
+ xfs_dabread (ffi);
if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
|| (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
xfs.dirmax = le16 (h->count) - le16 (h->stale);
@@ -448,15 +449,15 @@
filepos = xfs.blkoff;
xfs.dirpos = 0;
}
- return next_dentry (ino);
+ return next_dentry (ffi, ino);
}
-int
-xfs_mount (void)
+static int
+xfs_mount (fsi_file_t *ffi, const char *options)
{
xfs_sb_t super;
- if (!devread (0, 0, sizeof(super), (char *)&super)
+ if (!devread (ffi, 0, 0, sizeof(super), (char *)&super)
|| (le32(super.sb_magicnum) != XFS_SB_MAGIC)
|| ((le16(super.sb_versionnum)
& XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
@@ -483,8 +484,8 @@
return 1;
}
-int
-xfs_read (char *buf, int len)
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len)
{
xad_t *xad;
xfs_fileoff_t endofprev, endofcur, offset;
@@ -500,8 +501,8 @@
startpos = filepos;
endpos = filepos + len;
endofprev = (xfs_fileoff_t)-1;
- init_extents ();
- while (len > 0 && (xad = next_extent ())) {
+ init_extents (ffi);
+ while (len > 0 && (xad = next_extent (ffi))) {
offset = xad->offset;
xadlen = xad->len;
if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
@@ -510,7 +511,7 @@
? len : (endofcur - filepos);
disk_read_func = disk_read_hook;
- devread (fsb2daddr (xad->start),
+ devread (ffi, fsb2daddr (xad->start),
filepos - (offset << xfs.blklog), toread, buf);
disk_read_func = NULL;
@@ -533,8 +534,8 @@
return filepos - startpos;
}
-int
-xfs_dir (char *dirname)
+static int
+xfs_dir (fsi_file_t *ffi, char *dirname)
{
xfs_ino_t ino, parent_ino, new_ino;
xfs_fsize_t di_size;
@@ -546,7 +547,7 @@
parent_ino = ino = xfs.rootino;
link_count = 0;
for (;;) {
- di_read (ino);
+ di_read (ffi, ino);
di_size = le64 (icore.di_size);
di_mode = le16 (icore.di_mode);
@@ -558,7 +559,7 @@
if (di_size < xfs.bsize - 1) {
filepos = 0;
filemax = di_size;
- n = xfs_read (linkbuf, filemax);
+ n = xfs_read (ffi, linkbuf, filemax);
} else {
errnum = ERR_FILELENGTH;
return 0;
@@ -591,7 +592,7 @@
for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
*rest = 0;
- name = first_dentry (&new_ino);
+ name = first_dentry (ffi, &new_ino);
for (;;) {
cmp = (!*dirname) ? -1 : substring (dirname, name);
#ifndef STAGE1_5
@@ -608,7 +609,7 @@
*(dirname = rest) = ch;
break;
}
- name = next_dentry (&new_ino);
+ name = next_dentry (ffi, &new_ino);
if (name == NULL) {
if (print_possibilities < 0)
return 1;
@@ -621,4 +622,16 @@
}
}
-#endif /* FSYS_XFS */
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+ static fsig_plugin_ops_t ops = {
+ FSIMAGE_PLUGIN_VERSION,
+ .fpo_mount = xfs_mount,
+ .fpo_dir = xfs_dir,
+ .fpo_read = xfs_read
+ };
+
+ *name = "xfs";
+ return (fsig_init(fp, &ops));
+}
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2010-12-14 22:23 ` Marco Nenciarini
@ 2010-12-23 15:27 ` Marco Nenciarini
2011-01-19 12:44 ` Marco Nenciarini
0 siblings, 1 reply; 12+ messages in thread
From: Marco Nenciarini @ 2010-12-23 15:27 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: xen-devel@lists.xensource.com
On 14/12/2010 23:23, Marco Nenciarini wrote:
> On 13/12/2010 18:06, Stefano Stabellini wrote:
>> On Fri, 26 Nov 2010, Marco Nenciarini wrote:
>>>
>>> Hi,
>>> I've ported the xfs code from grub to pygrub for our company internal use.
>>>
>>> If you find it useful fell free to merge with main code.
>>
>> Can anybody test this patch and confirm it works properly?
>
> To help you testing the patch and auditing the code, I've attached to
> this message the diff against xfs code in grub-0.97.
>
> As stated before, the resulting fsimage.so works perfectly for me when
> installed in XCP-0.5 as /usr/lib/fs/xfs/fsimage.so
>
> Actually I've 3 Debian Squeeze machines and one Ubuntu 10.10 machine in
> our testing environment booting from xfs with pygrub.
>
> The only problem I've found is that the module doesn't compile on Debian
> based system due to some bug in gcc code optimizer. On such a systems
> the compiler returns the following error:
>
> gcc -DPIC -O2 -fomit-frame-pointer -m64 -fno-strict-aliasing -std=gnu99
> -Wall -Wstrict-prototypes -Wno-unused-value
> -Wdeclaration-after-statement -D__XEN_TOOLS__ -MMD -MF .fsys_xfs.opic.d
> -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> -I../../../tools/libfsimage/common/ -Werror -fPIC -c -o fsys_xfs.opic
> fsys_xfs.c
> fsys_xfs.c: In function ‘next_dentry’:
> fsys_xfs.c:409: error: extended registers have no high halves
> fsys_xfs.c:409: error: extended registers have no high halves
>
> The problem disappear if you turn off optimization with -O0
>
I've solved the compilation error on Ubuntu/Debian x86_64 (sed
s/"=q"/"=Q"/), but the resulting libary doesn't works (it doesn't even
recognize the XFS partition). I'll debug it during the next week.
Regards,
Marco
--
Marco Nenciarini - System manager @ Devise.IT
marco.nenciarini@devise.it | http://www.devise.it
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2010-12-23 15:27 ` Marco Nenciarini
@ 2011-01-19 12:44 ` Marco Nenciarini
2011-01-20 16:10 ` Ian Jackson
0 siblings, 1 reply; 12+ messages in thread
From: Marco Nenciarini @ 2011-01-19 12:44 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: xen-devel@lists.xensource.com
[-- Attachment #1: Type: text/plain, Size: 336 bytes --]
Attached there is the version of pygrub xfs support patch.
I've tested it against XCP, CentOS and latest Debian Unstable i386/amd64.
There is also my git patch queue against original grub code to show what
I've done.
Regards,
Marco
--
Marco Nenciarini - System manager @ Devise.IT
marco.nenciarini@devise.it | http://www.devise.it
[-- Attachment #2: pygrub-xfs-support.patch --]
[-- Type: text/x-patch, Size: 34934 bytes --]
diff -r 116a979f9d0f tools/libfsimage/Makefile
--- a/tools/libfsimage/Makefile Thu Dec 09 16:15:55 2010 +0000
+++ b/tools/libfsimage/Makefile Wed Jan 19 13:18:16 2011 +0100
@@ -1,7 +1,7 @@
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
-SUBDIRS-y = common ufs reiserfs iso9660 fat zfs
+SUBDIRS-y = common ufs reiserfs iso9660 fat zfs xfs
SUBDIRS-y += $(shell env CC="$(CC)" ./check-libext2fs)
.PHONY: all clean install
diff -r 116a979f9d0f tools/libfsimage/xfs/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/xfs/Makefile Wed Jan 19 13:18:16 2011 +0100
@@ -0,0 +1,13 @@
+XEN_ROOT = ../../..
+
+LIB_SRCS-y = fsys_xfs.c
+
+FS = xfs
+
+.PHONY: all
+all: fs-all
+
+.PHONY: install
+install: fs-install
+
+include $(XEN_ROOT)/tools/libfsimage/Rules.mk
diff -r 116a979f9d0f tools/libfsimage/xfs/fsys_xfs.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/xfs/fsys_xfs.c Wed Jan 19 13:18:16 2011 +0100
@@ -0,0 +1,636 @@
+/* fsys_xfs.c - an implementation for the SGI XFS file system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will 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 to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <fsimage_grub.h>
+#include "xfs.h"
+
+#define MAX_LINK_COUNT 8
+
+typedef struct xad {
+ xfs_fileoff_t offset;
+ xfs_fsblock_t start;
+ xfs_filblks_t len;
+} xad_t;
+
+struct xfs_info {
+ int bsize;
+ int dirbsize;
+ int isize;
+ unsigned int agblocks;
+ int bdlog;
+ int blklog;
+ int inopblog;
+ int agblklog;
+ int agnolog;
+ unsigned int nextents;
+ xfs_daddr_t next;
+ xfs_daddr_t daddr;
+ xfs_dablk_t forw;
+ xfs_dablk_t dablk;
+ xfs_bmbt_rec_32_t *xt;
+ xfs_bmbt_ptr_t ptr0;
+ int btnode_ptr0_off;
+ int i8param;
+ int dirpos;
+ int dirmax;
+ int blkoff;
+ int fpos;
+ xfs_ino_t rootino;
+};
+
+static struct xfs_info xfs;
+
+#define dirbuf ((char *)FSYS_BUF)
+#define filebuf ((char *)FSYS_BUF + 4096)
+#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
+#define icore (inode->di_core)
+
+#define mask32lo(n) (((xfs_uint32_t)1 << (n)) - 1)
+
+#define XFS_INO_MASK(k) ((xfs_uint32_t)((1ULL << (k)) - 1))
+#define XFS_INO_OFFSET_BITS xfs.inopblog
+#define XFS_INO_AGBNO_BITS xfs.agblklog
+#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog)
+#define XFS_INO_AGNO_BITS xfs.agnolog
+
+static inline xfs_agblock_t
+agino2agbno (xfs_agino_t agino)
+{
+ return agino >> XFS_INO_OFFSET_BITS;
+}
+
+static inline xfs_agnumber_t
+ino2agno (xfs_ino_t ino)
+{
+ return ino >> XFS_INO_AGINO_BITS;
+}
+
+static inline xfs_agino_t
+ino2agino (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
+}
+
+static inline int
+ino2offset (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
+}
+
+static inline xfs_uint16_t
+le16 (xfs_uint16_t x)
+{
+ __asm__("xchgb %b0,%h0" \
+ : "=Q" (x) \
+ : "0" (x)); \
+ return x;
+}
+
+static inline xfs_uint32_t
+le32 (xfs_uint32_t x)
+{
+#if 0
+ /* 386 doesn't have bswap. */
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+#else
+ /* This is slower but this works on all x86 architectures. */
+ __asm__("xchgb %b0, %h0" \
+ "\n\troll $16, %0" \
+ "\n\txchgb %b0, %h0" \
+ : "=Q" (x) : "0" (x));
+#endif
+ return x;
+}
+
+static inline xfs_uint64_t
+le64 (xfs_uint64_t x)
+{
+ xfs_uint32_t h = x >> 32;
+ xfs_uint32_t l = x & ((1ULL<<32)-1);
+ return (((xfs_uint64_t)le32(l)) << 32) | ((xfs_uint64_t)(le32(h)));
+}
+
+
+static xfs_fsblock_t
+xt_start (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
+ (((xfs_fsblock_t)le32 (r->l2)) << 11) |
+ (((xfs_fsblock_t)le32 (r->l3)) >> 21);
+}
+
+static xfs_fileoff_t
+xt_offset (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fileoff_t)le32 (r->l0) &
+ mask32lo(31)) << 23) |
+ (((xfs_fileoff_t)le32 (r->l1)) >> 9);
+}
+
+static xfs_filblks_t
+xt_len (xfs_bmbt_rec_32_t *r)
+{
+ return le32(r->l3) & mask32lo(21);
+}
+
+static inline int
+xfs_highbit32(xfs_uint32_t v)
+{
+ int i;
+
+ if (--v) {
+ for (i = 0; i < 31; i++, v >>= 1) {
+ if (v == 0)
+ return i;
+ }
+ }
+ return 0;
+}
+
+static int
+isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
+{
+ return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
+}
+
+static xfs_daddr_t
+agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
+{
+ return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
+}
+
+static xfs_daddr_t
+fsb2daddr (xfs_fsblock_t fsbno)
+{
+ return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
+ (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
+}
+
+#undef offsetof
+#define offsetof(t,m) ((size_t)&(((t *)0)->m))
+
+static inline int
+btroot_maxrecs (fsi_file_t *ffi)
+{
+ int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
+
+ return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
+}
+
+static int
+di_read (fsi_file_t *ffi, xfs_ino_t ino)
+{
+ xfs_agino_t agino;
+ xfs_agnumber_t agno;
+ xfs_agblock_t agbno;
+ xfs_daddr_t daddr;
+ int offset;
+
+ agno = ino2agno (ino);
+ agino = ino2agino (ino);
+ agbno = agino2agbno (agino);
+ offset = ino2offset (ino);
+ daddr = agb2daddr (agno, agbno);
+
+ devread (ffi, daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+
+ xfs.ptr0 = *(xfs_bmbt_ptr_t *)
+ (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
+ + btroot_maxrecs (ffi)*sizeof(xfs_bmbt_key_t));
+
+ return 1;
+}
+
+static void
+init_extents (fsi_file_t *ffi)
+{
+ xfs_bmbt_ptr_t ptr0;
+ xfs_btree_lblock_t h;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ xfs.xt = inode->di_u.di_bmx;
+ xfs.nextents = le32 (icore.di_nextents);
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ ptr0 = xfs.ptr0;
+ for (;;) {
+ xfs.daddr = fsb2daddr (le64(ptr0));
+ devread (ffi, xfs.daddr, 0,
+ sizeof(xfs_btree_lblock_t), (char *)&h);
+ if (!h.bb_level) {
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ return;
+ }
+ devread (ffi, xfs.daddr, xfs.btnode_ptr0_off,
+ sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
+ }
+ }
+}
+
+static xad_t *
+next_extent (fsi_file_t *ffi)
+{
+ static xad_t xad;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ if (xfs.nextents == 0)
+ return NULL;
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ if (xfs.nextents == 0) {
+ xfs_btree_lblock_t h;
+ if (xfs.next == 0)
+ return NULL;
+ xfs.daddr = xfs.next;
+ devread (ffi, xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ }
+ /* Yeah, I know that's slow, but I really don't care */
+ devread (ffi, xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
+ xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
+ xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
+ }
+ xad.offset = xt_offset (xfs.xt);
+ xad.start = xt_start (xfs.xt);
+ xad.len = xt_len (xfs.xt);
+ ++xfs.xt;
+ --xfs.nextents;
+
+ return &xad;
+}
+
+/*
+ * Name lies - the function reads only first 100 bytes
+ */
+static void
+xfs_dabread (fsi_file_t *ffi)
+{
+ xad_t *xad;
+ xfs_fileoff_t offset;;
+
+ init_extents (ffi);
+ while ((xad = next_extent (ffi))) {
+ offset = xad->offset;
+ if (isinxt (xfs.dablk, offset, xad->len)) {
+ devread (ffi, fsb2daddr (xad->start + xfs.dablk - offset),
+ 0, 100, dirbuf);
+ break;
+ }
+ }
+}
+
+static inline xfs_ino_t
+sf_ino (char *sfe, int namelen)
+{
+ void *p = sfe + namelen + 3;
+
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)p) : le32(*(xfs_uint32_t *)p);
+}
+
+static inline xfs_ino_t
+sf_parent_ino (fsi_file_t *ffi)
+{
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
+ : le32(*(xfs_uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
+}
+
+static inline int
+roundup8 (int n)
+{
+ return ((n+7)&~7);
+}
+
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len);
+
+static char *
+next_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
+{
+ int namelen = 1;
+ int toread;
+ static char usual[2][3] = {".", ".."};
+ static xfs_dir2_sf_entry_t *sfe;
+ char *name = usual[0];
+
+ if (xfs.dirpos >= xfs.dirmax) {
+ if (xfs.forw == 0)
+ return NULL;
+ xfs.dablk = xfs.forw;
+ xfs_dabread (ffi);
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+#undef h
+ xfs.dirpos = 0;
+ }
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ switch (xfs.dirpos) {
+ case -2:
+ *ino = 0;
+ break;
+ case -1:
+ *ino = sf_parent_ino (ffi);
+ ++name;
+ ++namelen;
+ sfe = (xfs_dir2_sf_entry_t *)
+ (inode->di_u.di_c
+ + sizeof(xfs_dir2_sf_hdr_t)
+ - xfs.i8param);
+ break;
+ default:
+ namelen = sfe->namelen;
+ *ino = sf_ino ((char *)sfe, namelen);
+ name = (char *)sfe->name;
+ sfe = (xfs_dir2_sf_entry_t *)
+ ((char *)sfe + namelen + 11 - xfs.i8param);
+ }
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_EXTENTS:
+#define dau ((xfs_dir2_data_union_t *)dirbuf)
+ for (;;) {
+ if (xfs.blkoff >= xfs.dirbsize) {
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos &= ~(xfs.dirbsize - 1);
+ filepos |= xfs.blkoff;
+ }
+ xfs_read (ffi, dirbuf, 4);
+ xfs.blkoff += 4;
+ if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
+ toread = roundup8 (le16(dau->unused.length)) - 4;
+ xfs.blkoff += toread;
+ filepos += toread;
+ continue;
+ }
+ break;
+ }
+ xfs_read (ffi, (char *)dirbuf + 4, 5);
+ *ino = le64 (dau->entry.inumber);
+ namelen = dau->entry.namelen;
+#undef dau
+ toread = roundup8 (namelen + 11) - 9;
+ xfs_read (ffi, dirbuf, toread);
+ name = (char *)dirbuf;
+ xfs.blkoff += toread + 5;
+ }
+ ++xfs.dirpos;
+ name[namelen] = 0;
+
+ return name;
+}
+
+static char *
+first_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
+{
+ xfs.forw = 0;
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
+ xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
+ xfs.dirpos = -2;
+ break;
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ filepos = 0;
+ xfs_read (ffi, dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
+#define tail ((xfs_dir2_block_tail_t *)dirbuf)
+ filepos = xfs.dirbsize - sizeof(*tail);
+ xfs_read (ffi, dirbuf, sizeof(*tail));
+ xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
+#undef tail
+ } else {
+ xfs.dablk = (1ULL << 35) >> xfs.blklog;
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+#define n ((xfs_da_intnode_t *)dirbuf)
+ for (;;) {
+ xfs_dabread (ffi);
+ if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
+ || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+ break;
+ }
+ xfs.dablk = le32 (n->btree[0].before);
+ }
+#undef n
+#undef h
+ }
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos = xfs.blkoff;
+ xfs.dirpos = 0;
+ }
+ return next_dentry (ffi, ino);
+}
+
+static int
+xfs_mount (fsi_file_t *ffi, const char *options)
+{
+ xfs_sb_t super;
+
+ if (!devread (ffi, 0, 0, sizeof(super), (char *)&super)
+ || (le32(super.sb_magicnum) != XFS_SB_MAGIC)
+ || ((le16(super.sb_versionnum)
+ & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
+ return 0;
+ }
+
+ xfs.bsize = le32 (super.sb_blocksize);
+ xfs.blklog = super.sb_blocklog;
+ xfs.bdlog = xfs.blklog - SECTOR_BITS;
+ xfs.rootino = le64 (super.sb_rootino);
+ xfs.isize = le16 (super.sb_inodesize);
+ xfs.agblocks = le32 (super.sb_agblocks);
+ xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
+
+ xfs.inopblog = super.sb_inopblog;
+ xfs.agblklog = super.sb_agblklog;
+ xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));
+
+ xfs.btnode_ptr0_off =
+ ((xfs.bsize - sizeof(xfs_btree_block_t)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
+ * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
+
+ return 1;
+}
+
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len)
+{
+ xad_t *xad;
+ xfs_fileoff_t endofprev, endofcur, offset;
+ xfs_filblks_t xadlen;
+ int toread, startpos, endpos;
+
+ if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
+ grub_memmove (buf, inode->di_u.di_c + filepos, len);
+ filepos += len;
+ return len;
+ }
+
+ startpos = filepos;
+ endpos = filepos + len;
+ endofprev = (xfs_fileoff_t)-1;
+ init_extents (ffi);
+ while (len > 0 && (xad = next_extent (ffi))) {
+ offset = xad->offset;
+ xadlen = xad->len;
+ if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
+ endofcur = (offset + xadlen) << xfs.blklog;
+ toread = (endofcur >= endpos)
+ ? len : (endofcur - filepos);
+
+ disk_read_func = disk_read_hook;
+ devread (ffi, fsb2daddr (xad->start),
+ filepos - (offset << xfs.blklog), toread, buf);
+ disk_read_func = NULL;
+
+ buf += toread;
+ len -= toread;
+ filepos += toread;
+ } else if (offset > endofprev) {
+ toread = ((offset << xfs.blklog) >= endpos)
+ ? len : ((offset - endofprev) << xfs.blklog);
+ len -= toread;
+ filepos += toread;
+ for (; toread; toread--) {
+ *buf++ = 0;
+ }
+ continue;
+ }
+ endofprev = offset + xadlen;
+ }
+
+ return filepos - startpos;
+}
+
+static int
+xfs_dir (fsi_file_t *ffi, char *dirname)
+{
+ xfs_ino_t ino, parent_ino, new_ino;
+ xfs_fsize_t di_size;
+ int di_mode;
+ int cmp, n, link_count;
+ char linkbuf[xfs.bsize];
+ char *rest, *name, ch;
+
+ parent_ino = ino = xfs.rootino;
+ link_count = 0;
+ for (;;) {
+ di_read (ffi, ino);
+ di_size = le64 (icore.di_size);
+ di_mode = le16 (icore.di_mode);
+
+ if ((di_mode & IFMT) == IFLNK) {
+ if (++link_count > MAX_LINK_COUNT) {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+ if (di_size < xfs.bsize - 1) {
+ filepos = 0;
+ filemax = di_size;
+ n = xfs_read (ffi, linkbuf, filemax);
+ } else {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
+ while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
+ linkbuf[n] = 0;
+ dirname = linkbuf;
+ continue;
+ }
+
+ if (!*dirname || isspace (*dirname)) {
+ if ((di_mode & IFMT) != IFREG) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ filepos = 0;
+ filemax = di_size;
+ return 1;
+ }
+
+ if ((di_mode & IFMT) != IFDIR) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ for (; *dirname == '/'; dirname++);
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+ name = first_dentry (ffi, &new_ino);
+ for (;;) {
+ cmp = (!*dirname) ? -1 : substring (dirname, name);
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/' && cmp <= 0) {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (name);
+ } else
+#endif
+ if (cmp == 0) {
+ parent_ino = ino;
+ if (new_ino)
+ ino = new_ino;
+ *(dirname = rest) = ch;
+ break;
+ }
+ name = next_dentry (ffi, &new_ino);
+ if (name == NULL) {
+ if (print_possibilities < 0)
+ return 1;
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+ }
+ }
+ }
+}
+
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+ static fsig_plugin_ops_t ops = {
+ FSIMAGE_PLUGIN_VERSION,
+ .fpo_mount = xfs_mount,
+ .fpo_dir = xfs_dir,
+ .fpo_read = xfs_read
+ };
+
+ *name = "xfs";
+ return (fsig_init(fp, &ops));
+}
diff -r 116a979f9d0f tools/libfsimage/xfs/xfs.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/xfs/xfs.h Wed Jan 19 13:18:16 2011 +0100
@@ -0,0 +1,544 @@
+/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2001,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+typedef signed char xfs_int8_t;
+typedef unsigned char xfs_uint8_t;
+typedef short xfs_int16_t;
+typedef unsigned short xfs_uint16_t;
+typedef int xfs_int32_t;
+typedef unsigned int xfs_uint32_t;
+typedef long long xfs_int64_t;
+typedef unsigned long long xfs_uint64_t;
+
+typedef xfs_uint64_t xfs_ino_t;
+typedef xfs_uint32_t xfs_agino_t;
+typedef xfs_int64_t xfs_daddr_t;
+typedef xfs_int64_t xfs_off_t;
+typedef xfs_uint8_t uuid_t[16];
+
+
+/* those are from xfs_types.h */
+
+typedef xfs_uint32_t xfs_agblock_t; /* blockno in alloc. group */
+typedef xfs_uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef xfs_uint32_t xfs_agnumber_t; /* allocation group number */
+typedef xfs_int32_t xfs_extnum_t; /* # of extents in a file */
+typedef xfs_int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef xfs_int64_t xfs_fsize_t; /* bytes in a file */
+
+typedef xfs_uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
+typedef xfs_uint32_t xfs_dahash_t; /* dir/attr hash value */
+
+/*
+ * Disk based types:
+ */
+typedef xfs_uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
+typedef xfs_uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
+typedef xfs_uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
+typedef xfs_uint64_t xfs_dfiloff_t; /* block number in a file */
+
+typedef xfs_uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
+typedef xfs_uint64_t xfs_fileoff_t; /* block number in a file */
+typedef xfs_uint64_t xfs_filblks_t; /* number of blocks in a file */
+
+
+/* those are from xfs_sb.h */
+
+#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/
+#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
+#define XFS_SB_VERSION_NUMBITS 0x000f
+
+typedef struct xfs_sb
+{
+ xfs_uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ xfs_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 */
+ xfs_uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
+ xfs_uint16_t sb_sectsize; /* volume sector size, bytes */
+ xfs_uint16_t sb_inodesize; /* inode size, bytes */
+ xfs_uint16_t sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ xfs_uint8_t sb_blocklog; /* log2 of sb_blocksize */
+ xfs_uint8_t sb_sectlog; /* log2 of sb_sectsize */
+ xfs_uint8_t sb_inodelog; /* log2 of sb_inodesize */
+ xfs_uint8_t sb_inopblog; /* log2 of sb_inopblock */
+ xfs_uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ xfs_uint8_t sb_rextslog; /* log2 of sb_rextents */
+ xfs_uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
+ xfs_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().
+ */
+ xfs_uint64_t sb_icount; /* allocated inodes */
+ xfs_uint64_t sb_ifree; /* free inodes */
+ xfs_uint64_t sb_fdblocks; /* free data blocks */
+ xfs_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 */
+ xfs_uint16_t sb_qflags; /* quota flags */
+ xfs_uint8_t sb_flags; /* misc. flags */
+ xfs_uint8_t sb_shared_vn; /* shared version number */
+ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ xfs_uint32_t sb_unit; /* stripe or raid unit */
+ xfs_uint32_t sb_width; /* stripe or raid width */
+ xfs_uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
+ xfs_uint8_t sb_dummy[7]; /* padding */
+} xfs_sb_t;
+
+
+/* those are from xfs_btree.h */
+
+/*
+ * Long form header: bmap btrees.
+ */
+typedef struct xfs_btree_lblock
+{
+ xfs_uint32_t bb_magic; /* magic number for block type */
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+ xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */
+ xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */
+} xfs_btree_lblock_t;
+
+/*
+ * Combined header and structure, used by common code.
+ */
+typedef struct xfs_btree_hdr
+{
+ xfs_uint32_t bb_magic; /* magic number for block type */
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+} xfs_btree_hdr_t;
+
+typedef struct xfs_btree_block
+{
+ xfs_btree_hdr_t bb_h; /* header */
+ union {
+ struct {
+ xfs_agblock_t bb_leftsib;
+ xfs_agblock_t bb_rightsib;
+ } s; /* short form pointers */
+ struct {
+ xfs_dfsbno_t bb_leftsib;
+ xfs_dfsbno_t bb_rightsib;
+ } l; /* long form pointers */
+ } bb_u; /* rest */
+} xfs_btree_block_t;
+
+/* those are from xfs_bmap_btree.h */
+
+/*
+ * Bmap root header, on-disk form only.
+ */
+typedef struct xfs_bmdr_block
+{
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+} xfs_bmdr_block_t;
+
+/*
+ * Bmap btree record and extent descriptor.
+ * For 32-bit kernels,
+ * l0:31 is an extent flag (value 1 indicates non-normal).
+ * l0:0-30 and l1:9-31 are startoff.
+ * l1:0-8, l2:0-31, and l3:21-31 are startblock.
+ * l3:0-20 are blockcount.
+ * For 64-bit kernels,
+ * l0:63 is an extent flag (value 1 indicates non-normal).
+ * l0:9-62 are startoff.
+ * l0:0-8 and l1:21-63 are startblock.
+ * l1:0-20 are blockcount.
+ */
+
+#define BMBT_USE_64 1
+
+typedef struct xfs_bmbt_rec_32
+{
+ xfs_uint32_t l0, l1, l2, l3;
+} xfs_bmbt_rec_32_t;
+typedef struct xfs_bmbt_rec_64
+{
+ xfs_uint64_t l0, l1;
+} xfs_bmbt_rec_64_t;
+
+#if BMBT_USE_64
+typedef xfs_uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#else /* !BMBT_USE_64 */
+typedef xfs_uint32_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#endif /* BMBT_USE_64 */
+
+/*
+ * Key structure for non-leaf levels of the tree.
+ */
+typedef struct xfs_bmbt_key
+{
+ xfs_dfiloff_t br_startoff; /* starting file offset */
+} xfs_bmbt_key_t, xfs_bmdr_key_t;
+
+typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
+ /* btree block header type */
+typedef struct xfs_btree_lblock xfs_bmbt_block_t;
+
+
+/* those are from xfs_dir2.h */
+/*
+ * Directory version 2.
+ * There are 4 possible formats:
+ * shortform
+ * single block - data with embedded leaf at the end
+ * multiple data blocks, single leaf+freeindex block
+ * data blocks, node&leaf blocks (btree), freeindex blocks
+ *
+ * The shortform format is in xfs_dir2_sf.h.
+ * The single block format is in xfs_dir2_block.h.
+ * The data block format is in xfs_dir2_data.h.
+ * The leaf and freeindex block formats are in xfs_dir2_leaf.h.
+ * Node blocks are the same as the other version, in xfs_da_btree.h.
+ */
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef xfs_uint16_t xfs_dir2_data_off_t;
+
+/*
+ * Byte offset in a directory.
+ */
+typedef xfs_off_t xfs_dir2_off_t;
+
+/* those are from xfs_da_btree.h */
+/*========================================================================
+ * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
+ *========================================================================*/
+
+/*
+ * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
+ *
+ * Is is used to manage a doubly linked list of all blocks at the same
+ * level in the Btree, and to identify which type of block this is.
+ */
+#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
+
+typedef struct xfs_da_blkinfo {
+ xfs_dablk_t forw; /* previous block in list */
+ xfs_dablk_t back; /* following block in list */
+ xfs_uint16_t magic; /* validity check on block */
+ xfs_uint16_t pad; /* unused */
+} xfs_da_blkinfo_t;
+
+/*
+ * This is the structure of the root and intermediate nodes in the Btree.
+ * The leaf nodes are defined above.
+ *
+ * Entries are not packed.
+ *
+ * Since we have duplicate keys, use a binary search but always follow
+ * all match in the block, not just the first match found.
+ */
+
+typedef struct xfs_da_intnode {
+ struct xfs_da_node_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ xfs_uint16_t count; /* count of active entries */
+ xfs_uint16_t level; /* level above leaves (leaf == 0) */
+ } hdr;
+ struct xfs_da_node_entry {
+ xfs_dahash_t hashval; /* hash value for this descendant */
+ xfs_dablk_t before; /* Btree block before this key */
+ } btree[1]; /* variable sized array of keys */
+} xfs_da_intnode_t;
+
+
+/* those are from xfs_dir2_data.h */
+/*
+ * Directory format 2, data block structures.
+ */
+
+/*
+ * Constants.
+ */
+#define XFS_DIR2_DATA_FREE_TAG 0xffff
+#define XFS_DIR2_DATA_FD_COUNT 3
+
+/*
+ * Structures.
+ */
+
+/*
+ * Describe a free area in the data block.
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+ xfs_dir2_data_off_t offset; /* start of freespace */
+ xfs_dir2_data_off_t length; /* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ * Always at the beginning of a directory-sized block.
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+ xfs_uint32_t magic; /* XFS_DIR2_DATA_MAGIC */
+ /* or XFS_DIR2_BLOCK_MAGIC */
+ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * Active entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_entry {
+ xfs_ino_t inumber; /* inode number */
+ xfs_uint8_t namelen; /* name length */
+ xfs_uint8_t name[1]; /* name bytes, no null */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_unused {
+ xfs_uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
+ xfs_dir2_data_off_t length; /* total free length */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+typedef union {
+ xfs_dir2_data_entry_t entry;
+ xfs_dir2_data_unused_t unused;
+} xfs_dir2_data_union_t;
+
+
+/* those are from xfs_dir2_leaf.h */
+/*
+ * Directory version 2, leaf block structures.
+ */
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+ xfs_da_blkinfo_t info; /* header for da routines */
+ xfs_uint16_t count; /* count of entries */
+ xfs_uint16_t stale; /* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+
+/* those are from xfs_dir2_block.h */
+/*
+ * xfs_dir2_block.h
+ * Directory version 2, single block format structures
+ */
+
+/*
+ * The single block format is as follows:
+ * xfs_dir2_data_hdr_t structure
+ * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
+ * xfs_dir2_leaf_entry_t structures
+ * xfs_dir2_block_tail_t structure
+ */
+
+#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
+
+typedef struct xfs_dir2_block_tail {
+ xfs_uint32_t count; /* count of leaf entries */
+ xfs_uint32_t stale; /* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+
+/* those are from xfs_dir2_sf.h */
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to
+ * fit into the literal area of the inode.
+ */
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef struct { xfs_uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { xfs_uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+ xfs_dir2_ino8_t i8;
+ xfs_dir2_ino4_t i4;
+} xfs_dir2_inou_t;
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { xfs_uint8_t i[2]; } xfs_dir2_sf_off_t;
+
+/*
+ * The parent directory has a dedicated field, and the self-pointer must
+ * be calculated on the fly.
+ *
+ * Entries are packed toward the top as tightly as possible. The header
+ * and the elements must be bcopy()'d out into a work area to get correct
+ * alignment for the inode number fields.
+ */
+typedef struct xfs_dir2_sf_hdr {
+ xfs_uint8_t count; /* count of entries */
+ xfs_uint8_t i8count; /* count of 8-byte inode #s */
+ xfs_dir2_inou_t parent; /* parent dir inode number */
+} xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+ xfs_uint8_t namelen; /* actual name length */
+ xfs_dir2_sf_off_t offset; /* saved offset */
+ xfs_uint8_t name[1]; /* name, variable size */
+ xfs_dir2_inou_t inumber; /* inode number, var. offset */
+} xfs_dir2_sf_entry_t;
+
+typedef struct xfs_dir2_sf {
+ xfs_dir2_sf_hdr_t hdr; /* shortform header */
+ xfs_dir2_sf_entry_t list[1]; /* shortform entries */
+} xfs_dir2_sf_t;
+
+/* those are from xfs_dinode.h */
+
+#define XFS_DINODE_VERSION_1 1
+#define XFS_DINODE_VERSION_2 2
+#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
+
+/*
+ * Disk inode structure.
+ * This is just the header; the inode is expanded to fill a variable size
+ * with the last field expanding. It is split into the core and "other"
+ * because we only need the core part in the in-core inode.
+ */
+typedef struct xfs_timestamp {
+ xfs_int32_t t_sec; /* timestamp seconds */
+ xfs_int32_t t_nsec; /* timestamp nanoseconds */
+} xfs_timestamp_t;
+
+/*
+ * Note: Coordinate changes to this structure with the XFS_DI_* #defines
+ * below and the offsets table in xfs_ialloc_log_di().
+ */
+typedef struct xfs_dinode_core
+{
+ xfs_uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ xfs_uint16_t di_mode; /* mode and type of file */
+ xfs_int8_t di_version; /* inode version */
+ xfs_int8_t di_format; /* format of di_c data */
+ xfs_uint16_t di_onlink; /* old number of links to file */
+ xfs_uint32_t di_uid; /* owner's user id */
+ xfs_uint32_t di_gid; /* owner's group id */
+ xfs_uint32_t di_nlink; /* number of links to file */
+ xfs_uint16_t di_projid; /* owner's project id */
+ xfs_uint8_t di_pad[10]; /* unused, zeroed space */
+ 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 */
+ xfs_fsize_t di_size; /* number of bytes in file */
+ xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
+ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
+ xfs_extnum_t di_nextents; /* number of extents in data fork */
+ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ xfs_uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
+ xfs_int8_t di_aformat; /* format of attr fork's data */
+ xfs_uint32_t di_dmevmask; /* DMIG event mask */
+ xfs_uint16_t di_dmstate; /* DMIG state info */
+ xfs_uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
+ xfs_uint32_t di_gen; /* generation number */
+} xfs_dinode_core_t;
+
+typedef struct xfs_dinode
+{
+ xfs_dinode_core_t di_core;
+ xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
+ union {
+ xfs_bmdr_block_t di_bmbt; /* btree root block */
+ xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
+ xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
+ char di_c[1]; /* local contents */
+ } di_u;
+} xfs_dinode_t;
+
+/*
+ * Values for di_format
+ */
+typedef enum xfs_dinode_fmt
+{
+ XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
+ XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
+ /* LNK: di_symlink */
+ XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
+ XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
+ XFS_DINODE_FMT_UUID /* MNT: di_uuid */
+} xfs_dinode_fmt_t;
+
+/*
+ * File types (mode field)
+ */
+#define IFMT 0170000 /* type of file */
+#define IFDIR 0040000 /* directory */
+#define IFREG 0100000 /* regular */
+#define IFLNK 0120000 /* symbolic link */
[-- Attachment #3: 0001-Original-grub-0.97-code.patch --]
[-- Type: text/x-patch, Size: 33939 bytes --]
>From d562baed1bf6fcec07375ad58f41e0a007c1ff4d Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 11:41:58 +0100
Subject: [PATCH 1/7] Original grub-0.97 code
---
fsys_xfs.c | 624 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xfs.h | 544 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1168 insertions(+), 0 deletions(-)
create mode 100644 fsys_xfs.c
create mode 100644 xfs.h
diff --git a/fsys_xfs.c b/fsys_xfs.c
new file mode 100644
index 0000000..76c4c13
--- /dev/null
+++ b/fsys_xfs.c
@@ -0,0 +1,624 @@
+/* fsys_xfs.c - an implementation for the SGI XFS file system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will 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 to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef FSYS_XFS
+
+#include "shared.h"
+#include "filesys.h"
+#include "xfs.h"
+
+#define MAX_LINK_COUNT 8
+
+typedef struct xad {
+ xfs_fileoff_t offset;
+ xfs_fsblock_t start;
+ xfs_filblks_t len;
+} xad_t;
+
+struct xfs_info {
+ int bsize;
+ int dirbsize;
+ int isize;
+ unsigned int agblocks;
+ int bdlog;
+ int blklog;
+ int inopblog;
+ int agblklog;
+ int agnolog;
+ unsigned int nextents;
+ xfs_daddr_t next;
+ xfs_daddr_t daddr;
+ xfs_dablk_t forw;
+ xfs_dablk_t dablk;
+ xfs_bmbt_rec_32_t *xt;
+ xfs_bmbt_ptr_t ptr0;
+ int btnode_ptr0_off;
+ int i8param;
+ int dirpos;
+ int dirmax;
+ int blkoff;
+ int fpos;
+ xfs_ino_t rootino;
+};
+
+static struct xfs_info xfs;
+
+#define dirbuf ((char *)FSYS_BUF)
+#define filebuf ((char *)FSYS_BUF + 4096)
+#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
+#define icore (inode->di_core)
+
+#define mask32lo(n) (((xfs_uint32_t)1 << (n)) - 1)
+
+#define XFS_INO_MASK(k) ((xfs_uint32_t)((1ULL << (k)) - 1))
+#define XFS_INO_OFFSET_BITS xfs.inopblog
+#define XFS_INO_AGBNO_BITS xfs.agblklog
+#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog)
+#define XFS_INO_AGNO_BITS xfs.agnolog
+
+static inline xfs_agblock_t
+agino2agbno (xfs_agino_t agino)
+{
+ return agino >> XFS_INO_OFFSET_BITS;
+}
+
+static inline xfs_agnumber_t
+ino2agno (xfs_ino_t ino)
+{
+ return ino >> XFS_INO_AGINO_BITS;
+}
+
+static inline xfs_agino_t
+ino2agino (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
+}
+
+static inline int
+ino2offset (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
+}
+
+static inline __const__ xfs_uint16_t
+le16 (xfs_uint16_t x)
+{
+ __asm__("xchgb %b0,%h0" \
+ : "=q" (x) \
+ : "0" (x)); \
+ return x;
+}
+
+static inline __const__ xfs_uint32_t
+le32 (xfs_uint32_t x)
+{
+#if 0
+ /* 386 doesn't have bswap. */
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+#else
+ /* This is slower but this works on all x86 architectures. */
+ __asm__("xchgb %b0, %h0" \
+ "\n\troll $16, %0" \
+ "\n\txchgb %b0, %h0" \
+ : "=q" (x) : "0" (x));
+#endif
+ return x;
+}
+
+static inline __const__ xfs_uint64_t
+le64 (xfs_uint64_t x)
+{
+ xfs_uint32_t h = x >> 32;
+ xfs_uint32_t l = x & ((1ULL<<32)-1);
+ return (((xfs_uint64_t)le32(l)) << 32) | ((xfs_uint64_t)(le32(h)));
+}
+
+
+static xfs_fsblock_t
+xt_start (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
+ (((xfs_fsblock_t)le32 (r->l2)) << 11) |
+ (((xfs_fsblock_t)le32 (r->l3)) >> 21);
+}
+
+static xfs_fileoff_t
+xt_offset (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fileoff_t)le32 (r->l0) &
+ mask32lo(31)) << 23) |
+ (((xfs_fileoff_t)le32 (r->l1)) >> 9);
+}
+
+static xfs_filblks_t
+xt_len (xfs_bmbt_rec_32_t *r)
+{
+ return le32(r->l3) & mask32lo(21);
+}
+
+static inline int
+xfs_highbit32(xfs_uint32_t v)
+{
+ int i;
+
+ if (--v) {
+ for (i = 0; i < 31; i++, v >>= 1) {
+ if (v == 0)
+ return i;
+ }
+ }
+ return 0;
+}
+
+static int
+isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
+{
+ return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
+}
+
+static xfs_daddr_t
+agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
+{
+ return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
+}
+
+static xfs_daddr_t
+fsb2daddr (xfs_fsblock_t fsbno)
+{
+ return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
+ (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
+}
+
+#undef offsetof
+#define offsetof(t,m) ((int)&(((t *)0)->m))
+
+static inline int
+btroot_maxrecs (void)
+{
+ int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
+
+ return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
+}
+
+static int
+di_read (xfs_ino_t ino)
+{
+ xfs_agino_t agino;
+ xfs_agnumber_t agno;
+ xfs_agblock_t agbno;
+ xfs_daddr_t daddr;
+ int offset;
+
+ agno = ino2agno (ino);
+ agino = ino2agino (ino);
+ agbno = agino2agbno (agino);
+ offset = ino2offset (ino);
+ daddr = agb2daddr (agno, agbno);
+
+ devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+
+ xfs.ptr0 = *(xfs_bmbt_ptr_t *)
+ (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
+ + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
+
+ return 1;
+}
+
+static void
+init_extents (void)
+{
+ xfs_bmbt_ptr_t ptr0;
+ xfs_btree_lblock_t h;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ xfs.xt = inode->di_u.di_bmx;
+ xfs.nextents = le32 (icore.di_nextents);
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ ptr0 = xfs.ptr0;
+ for (;;) {
+ xfs.daddr = fsb2daddr (le64(ptr0));
+ devread (xfs.daddr, 0,
+ sizeof(xfs_btree_lblock_t), (char *)&h);
+ if (!h.bb_level) {
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ return;
+ }
+ devread (xfs.daddr, xfs.btnode_ptr0_off,
+ sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
+ }
+ }
+}
+
+static xad_t *
+next_extent (void)
+{
+ static xad_t xad;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ if (xfs.nextents == 0)
+ return NULL;
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ if (xfs.nextents == 0) {
+ xfs_btree_lblock_t h;
+ if (xfs.next == 0)
+ return NULL;
+ xfs.daddr = xfs.next;
+ devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ }
+ /* Yeah, I know that's slow, but I really don't care */
+ devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
+ xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
+ xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
+ }
+ xad.offset = xt_offset (xfs.xt);
+ xad.start = xt_start (xfs.xt);
+ xad.len = xt_len (xfs.xt);
+ ++xfs.xt;
+ --xfs.nextents;
+
+ return &xad;
+}
+
+/*
+ * Name lies - the function reads only first 100 bytes
+ */
+static void
+xfs_dabread (void)
+{
+ xad_t *xad;
+ xfs_fileoff_t offset;;
+
+ init_extents ();
+ while ((xad = next_extent ())) {
+ offset = xad->offset;
+ if (isinxt (xfs.dablk, offset, xad->len)) {
+ devread (fsb2daddr (xad->start + xfs.dablk - offset),
+ 0, 100, dirbuf);
+ break;
+ }
+ }
+}
+
+static inline xfs_ino_t
+sf_ino (char *sfe, int namelen)
+{
+ void *p = sfe + namelen + 3;
+
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)p) : le32(*(xfs_uint32_t *)p);
+}
+
+static inline xfs_ino_t
+sf_parent_ino (void)
+{
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
+ : le32(*(xfs_uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
+}
+
+static inline int
+roundup8 (int n)
+{
+ return ((n+7)&~7);
+}
+
+static char *
+next_dentry (xfs_ino_t *ino)
+{
+ int namelen = 1;
+ int toread;
+ static char usual[2][3] = {".", ".."};
+ static xfs_dir2_sf_entry_t *sfe;
+ char *name = usual[0];
+
+ if (xfs.dirpos >= xfs.dirmax) {
+ if (xfs.forw == 0)
+ return NULL;
+ xfs.dablk = xfs.forw;
+ xfs_dabread ();
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+#undef h
+ xfs.dirpos = 0;
+ }
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ switch (xfs.dirpos) {
+ case -2:
+ *ino = 0;
+ break;
+ case -1:
+ *ino = sf_parent_ino ();
+ ++name;
+ ++namelen;
+ sfe = (xfs_dir2_sf_entry_t *)
+ (inode->di_u.di_c
+ + sizeof(xfs_dir2_sf_hdr_t)
+ - xfs.i8param);
+ break;
+ default:
+ namelen = sfe->namelen;
+ *ino = sf_ino ((char *)sfe, namelen);
+ name = sfe->name;
+ sfe = (xfs_dir2_sf_entry_t *)
+ ((char *)sfe + namelen + 11 - xfs.i8param);
+ }
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_EXTENTS:
+#define dau ((xfs_dir2_data_union_t *)dirbuf)
+ for (;;) {
+ if (xfs.blkoff >= xfs.dirbsize) {
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos &= ~(xfs.dirbsize - 1);
+ filepos |= xfs.blkoff;
+ }
+ xfs_read (dirbuf, 4);
+ xfs.blkoff += 4;
+ if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
+ toread = roundup8 (le16(dau->unused.length)) - 4;
+ xfs.blkoff += toread;
+ filepos += toread;
+ continue;
+ }
+ break;
+ }
+ xfs_read ((char *)dirbuf + 4, 5);
+ *ino = le64 (dau->entry.inumber);
+ namelen = dau->entry.namelen;
+#undef dau
+ toread = roundup8 (namelen + 11) - 9;
+ xfs_read (dirbuf, toread);
+ name = (char *)dirbuf;
+ xfs.blkoff += toread + 5;
+ }
+ ++xfs.dirpos;
+ name[namelen] = 0;
+
+ return name;
+}
+
+static char *
+first_dentry (xfs_ino_t *ino)
+{
+ xfs.forw = 0;
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
+ xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
+ xfs.dirpos = -2;
+ break;
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ filepos = 0;
+ xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
+#define tail ((xfs_dir2_block_tail_t *)dirbuf)
+ filepos = xfs.dirbsize - sizeof(*tail);
+ xfs_read (dirbuf, sizeof(*tail));
+ xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
+#undef tail
+ } else {
+ xfs.dablk = (1ULL << 35) >> xfs.blklog;
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+#define n ((xfs_da_intnode_t *)dirbuf)
+ for (;;) {
+ xfs_dabread ();
+ if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
+ || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+ break;
+ }
+ xfs.dablk = le32 (n->btree[0].before);
+ }
+#undef n
+#undef h
+ }
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos = xfs.blkoff;
+ xfs.dirpos = 0;
+ }
+ return next_dentry (ino);
+}
+
+int
+xfs_mount (void)
+{
+ xfs_sb_t super;
+
+ if (!devread (0, 0, sizeof(super), (char *)&super)
+ || (le32(super.sb_magicnum) != XFS_SB_MAGIC)
+ || ((le16(super.sb_versionnum)
+ & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
+ return 0;
+ }
+
+ xfs.bsize = le32 (super.sb_blocksize);
+ xfs.blklog = super.sb_blocklog;
+ xfs.bdlog = xfs.blklog - SECTOR_BITS;
+ xfs.rootino = le64 (super.sb_rootino);
+ xfs.isize = le16 (super.sb_inodesize);
+ xfs.agblocks = le32 (super.sb_agblocks);
+ xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
+
+ xfs.inopblog = super.sb_inopblog;
+ xfs.agblklog = super.sb_agblklog;
+ xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));
+
+ xfs.btnode_ptr0_off =
+ ((xfs.bsize - sizeof(xfs_btree_block_t)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
+ * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
+
+ return 1;
+}
+
+int
+xfs_read (char *buf, int len)
+{
+ xad_t *xad;
+ xfs_fileoff_t endofprev, endofcur, offset;
+ xfs_filblks_t xadlen;
+ int toread, startpos, endpos;
+
+ if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
+ grub_memmove (buf, inode->di_u.di_c + filepos, len);
+ filepos += len;
+ return len;
+ }
+
+ startpos = filepos;
+ endpos = filepos + len;
+ endofprev = (xfs_fileoff_t)-1;
+ init_extents ();
+ while (len > 0 && (xad = next_extent ())) {
+ offset = xad->offset;
+ xadlen = xad->len;
+ if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
+ endofcur = (offset + xadlen) << xfs.blklog;
+ toread = (endofcur >= endpos)
+ ? len : (endofcur - filepos);
+
+ disk_read_func = disk_read_hook;
+ devread (fsb2daddr (xad->start),
+ filepos - (offset << xfs.blklog), toread, buf);
+ disk_read_func = NULL;
+
+ buf += toread;
+ len -= toread;
+ filepos += toread;
+ } else if (offset > endofprev) {
+ toread = ((offset << xfs.blklog) >= endpos)
+ ? len : ((offset - endofprev) << xfs.blklog);
+ len -= toread;
+ filepos += toread;
+ for (; toread; toread--) {
+ *buf++ = 0;
+ }
+ continue;
+ }
+ endofprev = offset + xadlen;
+ }
+
+ return filepos - startpos;
+}
+
+int
+xfs_dir (char *dirname)
+{
+ xfs_ino_t ino, parent_ino, new_ino;
+ xfs_fsize_t di_size;
+ int di_mode;
+ int cmp, n, link_count;
+ char linkbuf[xfs.bsize];
+ char *rest, *name, ch;
+
+ parent_ino = ino = xfs.rootino;
+ link_count = 0;
+ for (;;) {
+ di_read (ino);
+ di_size = le64 (icore.di_size);
+ di_mode = le16 (icore.di_mode);
+
+ if ((di_mode & IFMT) == IFLNK) {
+ if (++link_count > MAX_LINK_COUNT) {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+ if (di_size < xfs.bsize - 1) {
+ filepos = 0;
+ filemax = di_size;
+ n = xfs_read (linkbuf, filemax);
+ } else {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
+ while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
+ linkbuf[n] = 0;
+ dirname = linkbuf;
+ continue;
+ }
+
+ if (!*dirname || isspace (*dirname)) {
+ if ((di_mode & IFMT) != IFREG) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ filepos = 0;
+ filemax = di_size;
+ return 1;
+ }
+
+ if ((di_mode & IFMT) != IFDIR) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ for (; *dirname == '/'; dirname++);
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+ name = first_dentry (&new_ino);
+ for (;;) {
+ cmp = (!*dirname) ? -1 : substring (dirname, name);
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/' && cmp <= 0) {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (name);
+ } else
+#endif
+ if (cmp == 0) {
+ parent_ino = ino;
+ if (new_ino)
+ ino = new_ino;
+ *(dirname = rest) = ch;
+ break;
+ }
+ name = next_dentry (&new_ino);
+ if (name == NULL) {
+ if (print_possibilities < 0)
+ return 1;
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+ }
+ }
+ }
+}
+
+#endif /* FSYS_XFS */
diff --git a/xfs.h b/xfs.h
new file mode 100644
index 0000000..02f8dcd
--- /dev/null
+++ b/xfs.h
@@ -0,0 +1,544 @@
+/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2001,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+typedef signed char xfs_int8_t;
+typedef unsigned char xfs_uint8_t;
+typedef short xfs_int16_t;
+typedef unsigned short xfs_uint16_t;
+typedef int xfs_int32_t;
+typedef unsigned int xfs_uint32_t;
+typedef long long xfs_int64_t;
+typedef unsigned long long xfs_uint64_t;
+
+typedef xfs_uint64_t xfs_ino_t;
+typedef xfs_uint32_t xfs_agino_t;
+typedef xfs_int64_t xfs_daddr_t;
+typedef xfs_int64_t xfs_off_t;
+typedef xfs_uint8_t uuid_t[16];
+
+
+/* those are from xfs_types.h */
+
+typedef xfs_uint32_t xfs_agblock_t; /* blockno in alloc. group */
+typedef xfs_uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef xfs_uint32_t xfs_agnumber_t; /* allocation group number */
+typedef xfs_int32_t xfs_extnum_t; /* # of extents in a file */
+typedef xfs_int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef xfs_int64_t xfs_fsize_t; /* bytes in a file */
+
+typedef xfs_uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
+typedef xfs_uint32_t xfs_dahash_t; /* dir/attr hash value */
+
+/*
+ * Disk based types:
+ */
+typedef xfs_uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
+typedef xfs_uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
+typedef xfs_uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
+typedef xfs_uint64_t xfs_dfiloff_t; /* block number in a file */
+
+typedef xfs_uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
+typedef xfs_uint64_t xfs_fileoff_t; /* block number in a file */
+typedef xfs_uint64_t xfs_filblks_t; /* number of blocks in a file */
+
+
+/* those are from xfs_sb.h */
+
+#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/
+#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
+#define XFS_SB_VERSION_NUMBITS 0x000f
+
+typedef struct xfs_sb
+{
+ xfs_uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ xfs_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 */
+ xfs_uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
+ xfs_uint16_t sb_sectsize; /* volume sector size, bytes */
+ xfs_uint16_t sb_inodesize; /* inode size, bytes */
+ xfs_uint16_t sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ xfs_uint8_t sb_blocklog; /* log2 of sb_blocksize */
+ xfs_uint8_t sb_sectlog; /* log2 of sb_sectsize */
+ xfs_uint8_t sb_inodelog; /* log2 of sb_inodesize */
+ xfs_uint8_t sb_inopblog; /* log2 of sb_inopblock */
+ xfs_uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ xfs_uint8_t sb_rextslog; /* log2 of sb_rextents */
+ xfs_uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
+ xfs_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().
+ */
+ xfs_uint64_t sb_icount; /* allocated inodes */
+ xfs_uint64_t sb_ifree; /* free inodes */
+ xfs_uint64_t sb_fdblocks; /* free data blocks */
+ xfs_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 */
+ xfs_uint16_t sb_qflags; /* quota flags */
+ xfs_uint8_t sb_flags; /* misc. flags */
+ xfs_uint8_t sb_shared_vn; /* shared version number */
+ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ xfs_uint32_t sb_unit; /* stripe or raid unit */
+ xfs_uint32_t sb_width; /* stripe or raid width */
+ xfs_uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
+ xfs_uint8_t sb_dummy[7]; /* padding */
+} xfs_sb_t;
+
+
+/* those are from xfs_btree.h */
+
+/*
+ * Long form header: bmap btrees.
+ */
+typedef struct xfs_btree_lblock
+{
+ xfs_uint32_t bb_magic; /* magic number for block type */
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+ xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */
+ xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */
+} xfs_btree_lblock_t;
+
+/*
+ * Combined header and structure, used by common code.
+ */
+typedef struct xfs_btree_hdr
+{
+ xfs_uint32_t bb_magic; /* magic number for block type */
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+} xfs_btree_hdr_t;
+
+typedef struct xfs_btree_block
+{
+ xfs_btree_hdr_t bb_h; /* header */
+ union {
+ struct {
+ xfs_agblock_t bb_leftsib;
+ xfs_agblock_t bb_rightsib;
+ } s; /* short form pointers */
+ struct {
+ xfs_dfsbno_t bb_leftsib;
+ xfs_dfsbno_t bb_rightsib;
+ } l; /* long form pointers */
+ } bb_u; /* rest */
+} xfs_btree_block_t;
+
+/* those are from xfs_bmap_btree.h */
+
+/*
+ * Bmap root header, on-disk form only.
+ */
+typedef struct xfs_bmdr_block
+{
+ xfs_uint16_t bb_level; /* 0 is a leaf */
+ xfs_uint16_t bb_numrecs; /* current # of data records */
+} xfs_bmdr_block_t;
+
+/*
+ * Bmap btree record and extent descriptor.
+ * For 32-bit kernels,
+ * l0:31 is an extent flag (value 1 indicates non-normal).
+ * l0:0-30 and l1:9-31 are startoff.
+ * l1:0-8, l2:0-31, and l3:21-31 are startblock.
+ * l3:0-20 are blockcount.
+ * For 64-bit kernels,
+ * l0:63 is an extent flag (value 1 indicates non-normal).
+ * l0:9-62 are startoff.
+ * l0:0-8 and l1:21-63 are startblock.
+ * l1:0-20 are blockcount.
+ */
+
+#define BMBT_USE_64 1
+
+typedef struct xfs_bmbt_rec_32
+{
+ xfs_uint32_t l0, l1, l2, l3;
+} xfs_bmbt_rec_32_t;
+typedef struct xfs_bmbt_rec_64
+{
+ xfs_uint64_t l0, l1;
+} xfs_bmbt_rec_64_t;
+
+#if BMBT_USE_64
+typedef xfs_uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#else /* !BMBT_USE_64 */
+typedef xfs_uint32_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#endif /* BMBT_USE_64 */
+
+/*
+ * Key structure for non-leaf levels of the tree.
+ */
+typedef struct xfs_bmbt_key
+{
+ xfs_dfiloff_t br_startoff; /* starting file offset */
+} xfs_bmbt_key_t, xfs_bmdr_key_t;
+
+typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
+ /* btree block header type */
+typedef struct xfs_btree_lblock xfs_bmbt_block_t;
+
+
+/* those are from xfs_dir2.h */
+/*
+ * Directory version 2.
+ * There are 4 possible formats:
+ * shortform
+ * single block - data with embedded leaf at the end
+ * multiple data blocks, single leaf+freeindex block
+ * data blocks, node&leaf blocks (btree), freeindex blocks
+ *
+ * The shortform format is in xfs_dir2_sf.h.
+ * The single block format is in xfs_dir2_block.h.
+ * The data block format is in xfs_dir2_data.h.
+ * The leaf and freeindex block formats are in xfs_dir2_leaf.h.
+ * Node blocks are the same as the other version, in xfs_da_btree.h.
+ */
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef xfs_uint16_t xfs_dir2_data_off_t;
+
+/*
+ * Byte offset in a directory.
+ */
+typedef xfs_off_t xfs_dir2_off_t;
+
+/* those are from xfs_da_btree.h */
+/*========================================================================
+ * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
+ *========================================================================*/
+
+/*
+ * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
+ *
+ * Is is used to manage a doubly linked list of all blocks at the same
+ * level in the Btree, and to identify which type of block this is.
+ */
+#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
+
+typedef struct xfs_da_blkinfo {
+ xfs_dablk_t forw; /* previous block in list */
+ xfs_dablk_t back; /* following block in list */
+ xfs_uint16_t magic; /* validity check on block */
+ xfs_uint16_t pad; /* unused */
+} xfs_da_blkinfo_t;
+
+/*
+ * This is the structure of the root and intermediate nodes in the Btree.
+ * The leaf nodes are defined above.
+ *
+ * Entries are not packed.
+ *
+ * Since we have duplicate keys, use a binary search but always follow
+ * all match in the block, not just the first match found.
+ */
+
+typedef struct xfs_da_intnode {
+ struct xfs_da_node_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ xfs_uint16_t count; /* count of active entries */
+ xfs_uint16_t level; /* level above leaves (leaf == 0) */
+ } hdr;
+ struct xfs_da_node_entry {
+ xfs_dahash_t hashval; /* hash value for this descendant */
+ xfs_dablk_t before; /* Btree block before this key */
+ } btree[1]; /* variable sized array of keys */
+} xfs_da_intnode_t;
+
+
+/* those are from xfs_dir2_data.h */
+/*
+ * Directory format 2, data block structures.
+ */
+
+/*
+ * Constants.
+ */
+#define XFS_DIR2_DATA_FREE_TAG 0xffff
+#define XFS_DIR2_DATA_FD_COUNT 3
+
+/*
+ * Structures.
+ */
+
+/*
+ * Describe a free area in the data block.
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+ xfs_dir2_data_off_t offset; /* start of freespace */
+ xfs_dir2_data_off_t length; /* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ * Always at the beginning of a directory-sized block.
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+ xfs_uint32_t magic; /* XFS_DIR2_DATA_MAGIC */
+ /* or XFS_DIR2_BLOCK_MAGIC */
+ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * Active entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_entry {
+ xfs_ino_t inumber; /* inode number */
+ xfs_uint8_t namelen; /* name length */
+ xfs_uint8_t name[1]; /* name bytes, no null */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_unused {
+ xfs_uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
+ xfs_dir2_data_off_t length; /* total free length */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+typedef union {
+ xfs_dir2_data_entry_t entry;
+ xfs_dir2_data_unused_t unused;
+} xfs_dir2_data_union_t;
+
+
+/* those are from xfs_dir2_leaf.h */
+/*
+ * Directory version 2, leaf block structures.
+ */
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+ xfs_da_blkinfo_t info; /* header for da routines */
+ xfs_uint16_t count; /* count of entries */
+ xfs_uint16_t stale; /* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+
+/* those are from xfs_dir2_block.h */
+/*
+ * xfs_dir2_block.h
+ * Directory version 2, single block format structures
+ */
+
+/*
+ * The single block format is as follows:
+ * xfs_dir2_data_hdr_t structure
+ * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
+ * xfs_dir2_leaf_entry_t structures
+ * xfs_dir2_block_tail_t structure
+ */
+
+#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
+
+typedef struct xfs_dir2_block_tail {
+ xfs_uint32_t count; /* count of leaf entries */
+ xfs_uint32_t stale; /* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+
+/* those are from xfs_dir2_sf.h */
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to
+ * fit into the literal area of the inode.
+ */
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef struct { xfs_uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { xfs_uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+ xfs_dir2_ino8_t i8;
+ xfs_dir2_ino4_t i4;
+} xfs_dir2_inou_t;
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { xfs_uint8_t i[2]; } xfs_dir2_sf_off_t;
+
+/*
+ * The parent directory has a dedicated field, and the self-pointer must
+ * be calculated on the fly.
+ *
+ * Entries are packed toward the top as tightly as possible. The header
+ * and the elements must be bcopy()'d out into a work area to get correct
+ * alignment for the inode number fields.
+ */
+typedef struct xfs_dir2_sf_hdr {
+ xfs_uint8_t count; /* count of entries */
+ xfs_uint8_t i8count; /* count of 8-byte inode #s */
+ xfs_dir2_inou_t parent; /* parent dir inode number */
+} xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+ xfs_uint8_t namelen; /* actual name length */
+ xfs_dir2_sf_off_t offset; /* saved offset */
+ xfs_uint8_t name[1]; /* name, variable size */
+ xfs_dir2_inou_t inumber; /* inode number, var. offset */
+} xfs_dir2_sf_entry_t;
+
+typedef struct xfs_dir2_sf {
+ xfs_dir2_sf_hdr_t hdr; /* shortform header */
+ xfs_dir2_sf_entry_t list[1]; /* shortform entries */
+} xfs_dir2_sf_t;
+
+/* those are from xfs_dinode.h */
+
+#define XFS_DINODE_VERSION_1 1
+#define XFS_DINODE_VERSION_2 2
+#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
+
+/*
+ * Disk inode structure.
+ * This is just the header; the inode is expanded to fill a variable size
+ * with the last field expanding. It is split into the core and "other"
+ * because we only need the core part in the in-core inode.
+ */
+typedef struct xfs_timestamp {
+ xfs_int32_t t_sec; /* timestamp seconds */
+ xfs_int32_t t_nsec; /* timestamp nanoseconds */
+} xfs_timestamp_t;
+
+/*
+ * Note: Coordinate changes to this structure with the XFS_DI_* #defines
+ * below and the offsets table in xfs_ialloc_log_di().
+ */
+typedef struct xfs_dinode_core
+{
+ xfs_uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ xfs_uint16_t di_mode; /* mode and type of file */
+ xfs_int8_t di_version; /* inode version */
+ xfs_int8_t di_format; /* format of di_c data */
+ xfs_uint16_t di_onlink; /* old number of links to file */
+ xfs_uint32_t di_uid; /* owner's user id */
+ xfs_uint32_t di_gid; /* owner's group id */
+ xfs_uint32_t di_nlink; /* number of links to file */
+ xfs_uint16_t di_projid; /* owner's project id */
+ xfs_uint8_t di_pad[10]; /* unused, zeroed space */
+ 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 */
+ xfs_fsize_t di_size; /* number of bytes in file */
+ xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
+ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
+ xfs_extnum_t di_nextents; /* number of extents in data fork */
+ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ xfs_uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
+ xfs_int8_t di_aformat; /* format of attr fork's data */
+ xfs_uint32_t di_dmevmask; /* DMIG event mask */
+ xfs_uint16_t di_dmstate; /* DMIG state info */
+ xfs_uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
+ xfs_uint32_t di_gen; /* generation number */
+} xfs_dinode_core_t;
+
+typedef struct xfs_dinode
+{
+ xfs_dinode_core_t di_core;
+ xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
+ union {
+ xfs_bmdr_block_t di_bmbt; /* btree root block */
+ xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
+ xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
+ char di_c[1]; /* local contents */
+ } di_u;
+} xfs_dinode_t;
+
+/*
+ * Values for di_format
+ */
+typedef enum xfs_dinode_fmt
+{
+ XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
+ XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
+ /* LNK: di_symlink */
+ XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
+ XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
+ XFS_DINODE_FMT_UUID /* MNT: di_uuid */
+} xfs_dinode_fmt_t;
+
+/*
+ * File types (mode field)
+ */
+#define IFMT 0170000 /* type of file */
+#define IFDIR 0040000 /* directory */
+#define IFREG 0100000 /* regular */
+#define IFLNK 0120000 /* symbolic link */
--
1.7.2.3
[-- Attachment #4: 0002-Initial-porting-to-libfsimage-s-devread.patch --]
[-- Type: text/x-patch, Size: 9667 bytes --]
>From d0c201cf35b76bbebebd96fb2de4e8f2f0dffa6f Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 12:02:29 +0100
Subject: [PATCH 2/7] Initial porting to libfsimage's devread
---
Makefile | 13 ++++++++
fsys_xfs.c | 99 ++++++++++++++++++++++++++++++++---------------------------
2 files changed, 67 insertions(+), 45 deletions(-)
create mode 100644 Makefile
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..99ed1ba
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+XEN_ROOT = ../../..
+
+LIB_SRCS-y = fsys_xfs.c
+
+FS = xfs
+
+.PHONY: all
+all: fs-all
+
+.PHONY: install
+install: fs-install
+
+include $(XEN_ROOT)/tools/libfsimage/Rules.mk
diff --git a/fsys_xfs.c b/fsys_xfs.c
index 76c4c13..043af2f 100644
--- a/fsys_xfs.c
+++ b/fsys_xfs.c
@@ -18,10 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifdef FSYS_XFS
-
-#include "shared.h"
-#include "filesys.h"
+#include <fsimage_grub.h>
#include "xfs.h"
#define MAX_LINK_COUNT 8
@@ -190,7 +187,7 @@ fsb2daddr (xfs_fsblock_t fsbno)
#define offsetof(t,m) ((int)&(((t *)0)->m))
static inline int
-btroot_maxrecs (void)
+btroot_maxrecs (fsi_file_t *ffi)
{
int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
@@ -199,7 +196,7 @@ btroot_maxrecs (void)
}
static int
-di_read (xfs_ino_t ino)
+di_read (fsi_file_t *ffi, xfs_ino_t ino)
{
xfs_agino_t agino;
xfs_agnumber_t agno;
@@ -213,17 +210,17 @@ di_read (xfs_ino_t ino)
offset = ino2offset (ino);
daddr = agb2daddr (agno, agbno);
- devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+ devread (ffi, daddr, offset*xfs.isize, xfs.isize, (char *)inode);
xfs.ptr0 = *(xfs_bmbt_ptr_t *)
(inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
- + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
+ + btroot_maxrecs (ffi)*sizeof(xfs_bmbt_key_t));
return 1;
}
static void
-init_extents (void)
+init_extents (fsi_file_t *ffi)
{
xfs_bmbt_ptr_t ptr0;
xfs_btree_lblock_t h;
@@ -237,7 +234,7 @@ init_extents (void)
ptr0 = xfs.ptr0;
for (;;) {
xfs.daddr = fsb2daddr (le64(ptr0));
- devread (xfs.daddr, 0,
+ devread (ffi, xfs.daddr, 0,
sizeof(xfs_btree_lblock_t), (char *)&h);
if (!h.bb_level) {
xfs.nextents = le16(h.bb_numrecs);
@@ -245,14 +242,14 @@ init_extents (void)
xfs.fpos = sizeof(xfs_btree_block_t);
return;
}
- devread (xfs.daddr, xfs.btnode_ptr0_off,
+ devread (ffi, xfs.daddr, xfs.btnode_ptr0_off,
sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
}
}
}
static xad_t *
-next_extent (void)
+next_extent (fsi_file_t *ffi)
{
static xad_t xad;
@@ -267,13 +264,13 @@ next_extent (void)
if (xfs.next == 0)
return NULL;
xfs.daddr = xfs.next;
- devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
+ devread (ffi, xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
xfs.nextents = le16(h.bb_numrecs);
xfs.next = fsb2daddr (le64(h.bb_rightsib));
xfs.fpos = sizeof(xfs_btree_block_t);
}
/* Yeah, I know that's slow, but I really don't care */
- devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
+ devread (ffi, xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
}
@@ -290,16 +287,16 @@ next_extent (void)
* Name lies - the function reads only first 100 bytes
*/
static void
-xfs_dabread (void)
+xfs_dabread (fsi_file_t *ffi)
{
xad_t *xad;
xfs_fileoff_t offset;;
- init_extents ();
- while ((xad = next_extent ())) {
+ init_extents (ffi);
+ while ((xad = next_extent (ffi))) {
offset = xad->offset;
if (isinxt (xfs.dablk, offset, xad->len)) {
- devread (fsb2daddr (xad->start + xfs.dablk - offset),
+ devread (ffi, fsb2daddr (xad->start + xfs.dablk - offset),
0, 100, dirbuf);
break;
}
@@ -316,7 +313,7 @@ sf_ino (char *sfe, int namelen)
}
static inline xfs_ino_t
-sf_parent_ino (void)
+sf_parent_ino (fsi_file_t *ffi)
{
return (xfs.i8param == 0)
? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
@@ -330,7 +327,7 @@ roundup8 (int n)
}
static char *
-next_dentry (xfs_ino_t *ino)
+next_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
{
int namelen = 1;
int toread;
@@ -342,7 +339,7 @@ next_dentry (xfs_ino_t *ino)
if (xfs.forw == 0)
return NULL;
xfs.dablk = xfs.forw;
- xfs_dabread ();
+ xfs_dabread (ffi);
#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
xfs.dirmax = le16 (h->count) - le16 (h->stale);
xfs.forw = le32 (h->info.forw);
@@ -357,7 +354,7 @@ next_dentry (xfs_ino_t *ino)
*ino = 0;
break;
case -1:
- *ino = sf_parent_ino ();
+ *ino = sf_parent_ino (ffi);
++name;
++namelen;
sfe = (xfs_dir2_sf_entry_t *)
@@ -382,7 +379,7 @@ next_dentry (xfs_ino_t *ino)
filepos &= ~(xfs.dirbsize - 1);
filepos |= xfs.blkoff;
}
- xfs_read (dirbuf, 4);
+ xfs_read (ffi, dirbuf, 4);
xfs.blkoff += 4;
if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
toread = roundup8 (le16(dau->unused.length)) - 4;
@@ -392,12 +389,12 @@ next_dentry (xfs_ino_t *ino)
}
break;
}
- xfs_read ((char *)dirbuf + 4, 5);
+ xfs_read (ffi, (char *)dirbuf + 4, 5);
*ino = le64 (dau->entry.inumber);
namelen = dau->entry.namelen;
#undef dau
toread = roundup8 (namelen + 11) - 9;
- xfs_read (dirbuf, toread);
+ xfs_read (ffi, dirbuf, toread);
name = (char *)dirbuf;
xfs.blkoff += toread + 5;
}
@@ -408,7 +405,7 @@ next_dentry (xfs_ino_t *ino)
}
static char *
-first_dentry (xfs_ino_t *ino)
+first_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
{
xfs.forw = 0;
switch (icore.di_format) {
@@ -420,11 +417,11 @@ first_dentry (xfs_ino_t *ino)
case XFS_DINODE_FMT_EXTENTS:
case XFS_DINODE_FMT_BTREE:
filepos = 0;
- xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ xfs_read (ffi, dirbuf, sizeof(xfs_dir2_data_hdr_t));
if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
#define tail ((xfs_dir2_block_tail_t *)dirbuf)
filepos = xfs.dirbsize - sizeof(*tail);
- xfs_read (dirbuf, sizeof(*tail));
+ xfs_read (ffi, dirbuf, sizeof(*tail));
xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
#undef tail
} else {
@@ -432,7 +429,7 @@ first_dentry (xfs_ino_t *ino)
#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
#define n ((xfs_da_intnode_t *)dirbuf)
for (;;) {
- xfs_dabread ();
+ xfs_dabread (ffi);
if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
|| (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
xfs.dirmax = le16 (h->count) - le16 (h->stale);
@@ -448,15 +445,15 @@ first_dentry (xfs_ino_t *ino)
filepos = xfs.blkoff;
xfs.dirpos = 0;
}
- return next_dentry (ino);
+ return next_dentry (ffi, ino);
}
-int
-xfs_mount (void)
+static int
+xfs_mount (fsi_file_t *ffi, const char *options)
{
xfs_sb_t super;
- if (!devread (0, 0, sizeof(super), (char *)&super)
+ if (!devread (ffi, 0, 0, sizeof(super), (char *)&super)
|| (le32(super.sb_magicnum) != XFS_SB_MAGIC)
|| ((le16(super.sb_versionnum)
& XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
@@ -483,8 +480,8 @@ xfs_mount (void)
return 1;
}
-int
-xfs_read (char *buf, int len)
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len)
{
xad_t *xad;
xfs_fileoff_t endofprev, endofcur, offset;
@@ -500,8 +497,8 @@ xfs_read (char *buf, int len)
startpos = filepos;
endpos = filepos + len;
endofprev = (xfs_fileoff_t)-1;
- init_extents ();
- while (len > 0 && (xad = next_extent ())) {
+ init_extents (ffi);
+ while (len > 0 && (xad = next_extent (ffi))) {
offset = xad->offset;
xadlen = xad->len;
if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
@@ -510,7 +507,7 @@ xfs_read (char *buf, int len)
? len : (endofcur - filepos);
disk_read_func = disk_read_hook;
- devread (fsb2daddr (xad->start),
+ devread (ffi, fsb2daddr (xad->start),
filepos - (offset << xfs.blklog), toread, buf);
disk_read_func = NULL;
@@ -533,8 +530,8 @@ xfs_read (char *buf, int len)
return filepos - startpos;
}
-int
-xfs_dir (char *dirname)
+static int
+xfs_dir (fsi_file_t *ffi, char *dirname)
{
xfs_ino_t ino, parent_ino, new_ino;
xfs_fsize_t di_size;
@@ -546,7 +543,7 @@ xfs_dir (char *dirname)
parent_ino = ino = xfs.rootino;
link_count = 0;
for (;;) {
- di_read (ino);
+ di_read (ffi, ino);
di_size = le64 (icore.di_size);
di_mode = le16 (icore.di_mode);
@@ -558,7 +555,7 @@ xfs_dir (char *dirname)
if (di_size < xfs.bsize - 1) {
filepos = 0;
filemax = di_size;
- n = xfs_read (linkbuf, filemax);
+ n = xfs_read (ffi, linkbuf, filemax);
} else {
errnum = ERR_FILELENGTH;
return 0;
@@ -591,7 +588,7 @@ xfs_dir (char *dirname)
for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
*rest = 0;
- name = first_dentry (&new_ino);
+ name = first_dentry (ffi, &new_ino);
for (;;) {
cmp = (!*dirname) ? -1 : substring (dirname, name);
#ifndef STAGE1_5
@@ -608,7 +605,7 @@ xfs_dir (char *dirname)
*(dirname = rest) = ch;
break;
}
- name = next_dentry (&new_ino);
+ name = next_dentry (ffi, &new_ino);
if (name == NULL) {
if (print_possibilities < 0)
return 1;
@@ -621,4 +618,16 @@ xfs_dir (char *dirname)
}
}
-#endif /* FSYS_XFS */
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+ static fsig_plugin_ops_t ops = {
+ FSIMAGE_PLUGIN_VERSION,
+ .fpo_mount = xfs_mount,
+ .fpo_dir = xfs_dir,
+ .fpo_read = xfs_read
+ };
+
+ *name = "xfs";
+ return (fsig_init(fp, &ops));
+}
--
1.7.2.3
[-- Attachment #5: 0003-Fix-offsetof-macro-on-64-bit-systems.patch --]
[-- Type: text/x-patch, Size: 633 bytes --]
>From 37346873ca9b221c38b22501f87bd4e75565a647 Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 12:24:27 +0100
Subject: [PATCH 3/7] Fix offsetof macro on 64 bit systems
---
fsys_xfs.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fsys_xfs.c b/fsys_xfs.c
index 043af2f..1db60ae 100644
--- a/fsys_xfs.c
+++ b/fsys_xfs.c
@@ -184,7 +184,7 @@ fsb2daddr (xfs_fsblock_t fsbno)
}
#undef offsetof
-#define offsetof(t,m) ((int)&(((t *)0)->m))
+#define offsetof(t,m) ((size_t)&(((t *)0)->m))
static inline int
btroot_maxrecs (fsi_file_t *ffi)
--
1.7.2.3
[-- Attachment #6: 0004-Add-missing-xfs_read-prototype.patch --]
[-- Type: text/x-patch, Size: 597 bytes --]
>From e437eac25b0b00071502846bd155052da94fccc1 Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 12:41:21 +0100
Subject: [PATCH 4/7] Add missing xfs_read prototype
---
fsys_xfs.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/fsys_xfs.c b/fsys_xfs.c
index 1db60ae..6527da9 100644
--- a/fsys_xfs.c
+++ b/fsys_xfs.c
@@ -326,6 +326,9 @@ roundup8 (int n)
return ((n+7)&~7);
}
+static int
+xfs_read (fsi_file_t *ffi, char *buf, int len);
+
static char *
next_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
{
--
1.7.2.3
[-- Attachment #7: 0005-Fix-assumtion-that-chars-are-unsigned.patch --]
[-- Type: text/x-patch, Size: 702 bytes --]
>From 1c3588776d4554a73caff592f163a3c2cd879fa0 Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 13:18:59 +0100
Subject: [PATCH 5/7] Fix assumtion that chars are unsigned
---
fsys_xfs.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fsys_xfs.c b/fsys_xfs.c
index 6527da9..f022040 100644
--- a/fsys_xfs.c
+++ b/fsys_xfs.c
@@ -368,7 +368,7 @@ next_dentry (fsi_file_t *ffi, xfs_ino_t *ino)
default:
namelen = sfe->namelen;
*ino = sf_ino ((char *)sfe, namelen);
- name = sfe->name;
+ name = (char *)sfe->name;
sfe = (xfs_dir2_sf_entry_t *)
((char *)sfe + namelen + 11 - xfs.i8param);
}
--
1.7.2.3
[-- Attachment #8: 0006-Fix-inline-asm-code-to-work-on-64-bit-patforms.patch --]
[-- Type: text/x-patch, Size: 794 bytes --]
>From 20e29b6137edf8afafcb2fca0b31d6783bdab53e Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 13:20:21 +0100
Subject: [PATCH 6/7] Fix inline asm code to work on 64 bit patforms
---
fsys_xfs.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fsys_xfs.c b/fsys_xfs.c
index f022040..ef558dd 100644
--- a/fsys_xfs.c
+++ b/fsys_xfs.c
@@ -98,7 +98,7 @@ static inline __const__ xfs_uint16_t
le16 (xfs_uint16_t x)
{
__asm__("xchgb %b0,%h0" \
- : "=q" (x) \
+ : "=Q" (x) \
: "0" (x)); \
return x;
}
@@ -114,7 +114,7 @@ le32 (xfs_uint32_t x)
__asm__("xchgb %b0, %h0" \
"\n\troll $16, %0" \
"\n\txchgb %b0, %h0" \
- : "=q" (x) : "0" (x));
+ : "=Q" (x) : "0" (x));
#endif
return x;
}
--
1.7.2.3
[-- Attachment #9: 0007-fix-warning-type-qualifiers-ignored-on-function-retu.patch --]
[-- Type: text/x-patch, Size: 997 bytes --]
>From b5889a4795a3bd9a424b3f506551b95206e16991 Mon Sep 17 00:00:00 2001
From: Marco Nenciarini <marco.nenciarini@devise.it>
Date: Wed, 5 Jan 2011 13:40:16 +0100
Subject: [PATCH 7/7] fix warning: type qualifiers ignored on function return type
---
fsys_xfs.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fsys_xfs.c b/fsys_xfs.c
index ef558dd..6366d16 100644
--- a/fsys_xfs.c
+++ b/fsys_xfs.c
@@ -94,7 +94,7 @@ ino2offset (xfs_ino_t ino)
return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
}
-static inline __const__ xfs_uint16_t
+static inline xfs_uint16_t
le16 (xfs_uint16_t x)
{
__asm__("xchgb %b0,%h0" \
@@ -103,7 +103,7 @@ le16 (xfs_uint16_t x)
return x;
}
-static inline __const__ xfs_uint32_t
+static inline xfs_uint32_t
le32 (xfs_uint32_t x)
{
#if 0
@@ -119,7 +119,7 @@ le32 (xfs_uint32_t x)
return x;
}
-static inline __const__ xfs_uint64_t
+static inline xfs_uint64_t
le64 (xfs_uint64_t x)
{
xfs_uint32_t h = x >> 32;
--
1.7.2.3
[-- Attachment #10: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2011-01-19 12:44 ` Marco Nenciarini
@ 2011-01-20 16:10 ` Ian Jackson
2011-01-20 16:15 ` Stefano Stabellini
0 siblings, 1 reply; 12+ messages in thread
From: Ian Jackson @ 2011-01-20 16:10 UTC (permalink / raw)
To: Marco Nenciarini; +Cc: xen-devel@lists.xensource.com, Stefano Stabellini
Marco Nenciarini writes ("Re: [Xen-devel] XFS support for pygrub patch"):
> Attached there is the version of pygrub xfs support patch.
> I've tested it against XCP, CentOS and latest Debian Unstable i386/amd64.
>
> There is also my git patch queue against original grub code to show what
> I've done.
Thanks for your contribution.
I'm afraid that the 4.1 tree is currently in feature code freeze so
normally we wouldn't accept it.
However, having said that, it does look very self-contained and it
might be appropriate to grant a freeze exception in this case.
Stefano, what do you think ?
Ian.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2011-01-20 16:10 ` Ian Jackson
@ 2011-01-20 16:15 ` Stefano Stabellini
2011-05-11 17:05 ` alxgomz
0 siblings, 1 reply; 12+ messages in thread
From: Stefano Stabellini @ 2011-01-20 16:15 UTC (permalink / raw)
To: Ian Jackson
Cc: Marco Nenciarini, xen-devel@lists.xensource.com,
Stefano Stabellini
On Thu, 20 Jan 2011, Ian Jackson wrote:
> Marco Nenciarini writes ("Re: [Xen-devel] XFS support for pygrub patch"):
> > Attached there is the version of pygrub xfs support patch.
> > I've tested it against XCP, CentOS and latest Debian Unstable i386/amd64.
> >
> > There is also my git patch queue against original grub code to show what
> > I've done.
>
> Thanks for your contribution.
>
> I'm afraid that the 4.1 tree is currently in feature code freeze so
> normally we wouldn't accept it.
>
> However, having said that, it does look very self-contained and it
> might be appropriate to grant a freeze exception in this case.
>
> Stefano, what do you think ?
It would be nice if somebody could confirm that it works properly.
If you get a couple of people confirming that it works I would consider
applying it.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
@ 2011-02-10 9:18 Adi Kriegisch
2011-02-10 11:13 ` Stefano Stabellini
0 siblings, 1 reply; 12+ messages in thread
From: Adi Kriegisch @ 2011-02-10 9:18 UTC (permalink / raw)
To: xen-devel
I tried Marco Nenciarini's patch to add xfs support to pygrub. It works
without any issues on Xen 4.0.1.
How I tested them:
On a Squeeze dom0 I did an "apt-get source xen", copied the patch in
debian/patches, updated debian/patches/series, incremented the version
number to 4.0.1-2+xen1 (with "dch -i") and ran dpkg-buildpackage.
The resulting packages just worked with all DomUs (no matter if they were
based on ext3 or xfs).
Thanks Marco for your work!
-- Adi
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2011-02-10 9:18 Adi Kriegisch
@ 2011-02-10 11:13 ` Stefano Stabellini
2011-05-03 8:53 ` Marco Nenciarini
0 siblings, 1 reply; 12+ messages in thread
From: Stefano Stabellini @ 2011-02-10 11:13 UTC (permalink / raw)
To: Adi Kriegisch; +Cc: xen-devel@lists.xensource.com
On Thu, 10 Feb 2011, Adi Kriegisch wrote:
> I tried Marco Nenciarini's patch to add xfs support to pygrub. It works
> without any issues on Xen 4.0.1.
>
> How I tested them:
> On a Squeeze dom0 I did an "apt-get source xen", copied the patch in
> debian/patches, updated debian/patches/series, incremented the version
> number to 4.0.1-2+xen1 (with "dch -i") and ran dpkg-buildpackage.
>
> The resulting packages just worked with all DomUs (no matter if they were
> based on ext3 or xfs).
>
> Thanks Marco for your work!
Thanks for helping out with the testing.
We'll apply Marco's patch after the 4.1 release.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2011-02-10 11:13 ` Stefano Stabellini
@ 2011-05-03 8:53 ` Marco Nenciarini
0 siblings, 0 replies; 12+ messages in thread
From: Marco Nenciarini @ 2011-05-03 8:53 UTC (permalink / raw)
To: xen-devel
On 10/02/2011 12:13, Stefano Stabellini wrote:
> On Thu, 10 Feb 2011, Adi Kriegisch wrote:
>> I tried Marco Nenciarini's patch to add xfs support to pygrub. It works
>> without any issues on Xen 4.0.1.
>>
>> How I tested them:
>> On a Squeeze dom0 I did an "apt-get source xen", copied the patch in
>> debian/patches, updated debian/patches/series, incremented the version
>> number to 4.0.1-2+xen1 (with "dch -i") and ran dpkg-buildpackage.
>>
>> The resulting packages just worked with all DomUs (no matter if they were
>> based on ext3 or xfs).
>>
>> Thanks Marco for your work!
>
> Thanks for helping out with the testing.
> We'll apply Marco's patch after the 4.1 release.
>
Hi,
Maybe it's time to apply the patch[1].
Regards,
Marco
[1] http://lists.xensource.com/archives/html/xen-devel/2011-01/msg01324.html
--
Marco Nenciarini - System manager @ Devise.IT
marco.nenciarini@devise.it | http://www.devise.it
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: XFS support for pygrub patch
2011-01-20 16:15 ` Stefano Stabellini
@ 2011-05-11 17:05 ` alxgomz
0 siblings, 0 replies; 12+ messages in thread
From: alxgomz @ 2011-05-11 17:05 UTC (permalink / raw)
To: xen-devel
tested on a Debian Squeeze amd64 dom0 with the xen packages as shipped by
Squeeze (Xen 4.0.1)
I just added the patch to the debian sources of Xen and rebuild a deb
packages using the debian framework.
I can now boot PVMs using pygrub even on machines with xfs boot/rootfs.
--
View this message in context: http://xen.1045712.n5.nabble.com/XFS-support-for-pygrub-patch-tp3281142p4387931.html
Sent from the Xen - Dev mailing list archive at Nabble.com.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-05-11 17:05 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-26 11:16 XFS support for pygrub patch Marco Nenciarini
2010-12-13 17:06 ` Stefano Stabellini
2010-12-14 22:23 ` Marco Nenciarini
2010-12-23 15:27 ` Marco Nenciarini
2011-01-19 12:44 ` Marco Nenciarini
2011-01-20 16:10 ` Ian Jackson
2011-01-20 16:15 ` Stefano Stabellini
2011-05-11 17:05 ` alxgomz
[not found] <22752968ADD47840A7D404102C7563B005A82DE827@vasco-be-exch2.vasco.com>
2010-12-08 22:39 ` Marco Nenciarini
-- strict thread matches above, loose matches on Subject: below --
2011-02-10 9:18 Adi Kriegisch
2011-02-10 11:13 ` Stefano Stabellini
2011-05-03 8:53 ` Marco Nenciarini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).