From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marco Nenciarini Subject: Re: XFS support for pygrub patch Date: Wed, 19 Jan 2011 13:44:51 +0100 Message-ID: <4D36DCC3.30701@devise.it> References: <4CEF9700.4090706@devise.it> <4D07EE72.3060406@devise.it> <4D136A62.4070905@devise.it> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050509080905060707060909" Return-path: In-Reply-To: <4D136A62.4070905@devise.it> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Stefano Stabellini Cc: "xen-devel@lists.xensource.com" List-Id: xen-devel@lists.xenproject.org This is a multi-part message in MIME format. --------------050509080905060707060909 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit 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 --------------050509080905060707060909 Content-Type: text/x-patch; name="pygrub-xfs-support.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="pygrub-xfs-support.patch" 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 +#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 */ --------------050509080905060707060909 Content-Type: text/x-patch; name="0001-Original-grub-0.97-code.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0001-Original-grub-0.97-code.patch" >>From d562baed1bf6fcec07375ad58f41e0a007c1ff4d Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 --------------050509080905060707060909 Content-Type: text/x-patch; name="0002-Initial-porting-to-libfsimage-s-devread.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0002-Initial-porting-to-libfsimage-s-devread.patch" >>From d0c201cf35b76bbebebd96fb2de4e8f2f0dffa6f Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 #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 --------------050509080905060707060909 Content-Type: text/x-patch; name="0003-Fix-offsetof-macro-on-64-bit-systems.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0003-Fix-offsetof-macro-on-64-bit-systems.patch" >>From 37346873ca9b221c38b22501f87bd4e75565a647 Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 --------------050509080905060707060909 Content-Type: text/x-patch; name="0004-Add-missing-xfs_read-prototype.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0004-Add-missing-xfs_read-prototype.patch" >>From e437eac25b0b00071502846bd155052da94fccc1 Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 --------------050509080905060707060909 Content-Type: text/x-patch; name="0005-Fix-assumtion-that-chars-are-unsigned.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0005-Fix-assumtion-that-chars-are-unsigned.patch" >>From 1c3588776d4554a73caff592f163a3c2cd879fa0 Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 --------------050509080905060707060909 Content-Type: text/x-patch; name="0006-Fix-inline-asm-code-to-work-on-64-bit-patforms.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0006-Fix-inline-asm-code-to-work-on-64-bit-patforms.patch" >>From 20e29b6137edf8afafcb2fca0b31d6783bdab53e Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 --------------050509080905060707060909 Content-Type: text/x-patch; name="0007-fix-warning-type-qualifiers-ignored-on-function-retu.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0007-fix-warning-type-qualifiers-ignored-on-function-retu.pa"; filename*1="tch" >>From b5889a4795a3bd9a424b3f506551b95206e16991 Mon Sep 17 00:00:00 2001 From: Marco Nenciarini 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 --------------050509080905060707060909 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------050509080905060707060909--