summaryrefslogtreecommitdiff
path: root/extlinux
diff options
context:
space:
mode:
Diffstat (limited to 'extlinux')
-rw-r--r--extlinux/Makefile1
-rw-r--r--extlinux/main.c313
-rw-r--r--extlinux/misc.h50
-rw-r--r--extlinux/xfs.h25
-rw-r--r--extlinux/xfs_fs.h501
-rw-r--r--extlinux/xfs_sb.h476
-rw-r--r--extlinux/xfs_types.h135
7 files changed, 1463 insertions, 38 deletions
diff --git a/extlinux/Makefile b/extlinux/Makefile
index 6cde574e..f20a71db 100644
--- a/extlinux/Makefile
+++ b/extlinux/Makefile
@@ -32,6 +32,7 @@ SRCS = main.c \
../libinstaller/setadv.c \
../libinstaller/advio.c \
../libinstaller/bootsect_bin.c \
+ ../libinstaller/ldlinuxc32_bin.c \
../libinstaller/ldlinux_bin.c
OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
diff --git a/extlinux/main.c b/extlinux/main.c
index dbf538a1..aa20e1bd 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -14,7 +14,8 @@
/*
* extlinux.c
*
- * Install the syslinux boot block on an fat, ntfs, ext2/3/4 and btrfs filesystem
+ * Install the syslinux boot block on an fat, ntfs, ext2/3/4, btrfs and xfs
+ * filesystem.
*/
#define _GNU_SOURCE /* Enable everything */
@@ -46,6 +47,10 @@
#include "btrfs.h"
#include "fat.h"
#include "ntfs.h"
+#include "xfs.h"
+#include "xfs_types.h"
+#include "xfs_sb.h"
+#include "misc.h"
#include "../version.h"
#include "syslxint.h"
#include "syslxcom.h" /* common functions shared with extlinux and syslinux */
@@ -64,6 +69,13 @@
#define EXT2_SUPER_OFFSET 1024
#endif
+/* Since we have unused 2048 bytes in the primary AG of an XFS partition,
+ * we will use the first 0~512 bytes starting from 2048 for the Syslinux
+ * boot sector.
+ */
+#define XFS_BOOTSECT_OFFSET (4 << SECTOR_SHIFT)
+#define XFS_SUPPORTED_BLOCKSIZE 4096 /* 4 KiB filesystem block size */
+
/* the btrfs partition first 64K blank area is used to store boot sector and
boot image, the boot sector is from 0~512, the boot image starts after */
#define BTRFS_BOOTSECT_AREA 65536
@@ -295,7 +307,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
nsect += 2; /* Two sectors for the ADV */
sectp = alloca(sizeof(sector_t) * nsect);
- if (fs_type == EXT2 || fs_type == VFAT || fs_type == NTFS) {
+ if (fs_type == EXT2 || fs_type == VFAT || fs_type == NTFS ||
+ fs_type == XFS) {
if (sectmap(fd, sectp, nsect)) {
perror("bmap");
exit(1);
@@ -328,6 +341,7 @@ int install_bootblock(int fd, const char *device)
struct btrfs_super_block sb2;
struct fat_boot_sector sb3;
struct ntfs_boot_sector sb4;
+ xfs_sb_t sb5;
bool ok = false;
if (fs_type == EXT2) {
@@ -335,6 +349,7 @@ int install_bootblock(int fd, const char *device)
perror("reading superblock");
return 1;
}
+
if (sb.s_magic == EXT2_SUPER_MAGIC)
ok = true;
} else if (fs_type == BTRFS) {
@@ -350,6 +365,7 @@ int install_bootblock(int fd, const char *device)
perror("reading fat superblock");
return 1;
}
+
if (fat_check_sb_fields(&sb3))
ok = true;
} else if (fs_type == NTFS) {
@@ -360,12 +376,34 @@ int install_bootblock(int fd, const char *device)
if (ntfs_check_sb_fields(&sb4))
ok = true;
+ } else if (fs_type == XFS) {
+ if (xpread(fd, &sb5, sizeof sb5, 0) != sizeof sb5) {
+ perror("reading xfs superblock");
+ return 1;
+ }
+
+ if (sb5.sb_magicnum == *(u32 *)XFS_SB_MAGIC) {
+ if (be32_to_cpu(sb5.sb_blocksize) != XFS_SUPPORTED_BLOCKSIZE) {
+ fprintf(stderr,
+ "You need to have 4 KiB filesystem block size for "
+ " being able to install Syslinux in your XFS "
+ "partition (because there is no enough space in MBR to "
+ "determine where Syslinux bootsector can be installed "
+ "regardless the filesystem block size)\n");
+ return 1;
+ }
+
+ ok = true;
+ }
}
+
if (!ok) {
- fprintf(stderr, "no fat, ntfs, ext2/3/4 or btrfs superblock found on %s\n",
- device);
+ fprintf(stderr,
+ "no fat, ntfs, ext2/3/4, btrfs or xfs superblock found on %s\n",
+ device);
return 1;
}
+
if (fs_type == VFAT) {
struct fat_boot_sector *sbs = (struct fat_boot_sector *)syslinux_bootsect;
if (xpwrite(fd, &sbs->FAT_bsHead, FAT_bsHeadLen, 0) != FAT_bsHeadLen ||
@@ -385,6 +423,12 @@ int install_bootblock(int fd, const char *device)
perror("writing ntfs bootblock");
return 1;
}
+ } else if (fs_type == XFS) {
+ if (xpwrite(fd, syslinux_bootsect, syslinux_bootsect_len,
+ XFS_BOOTSECT_OFFSET) != syslinux_bootsect_len) {
+ perror("writing xfs bootblock");
+ return 1;
+ }
} else {
if (xpwrite(fd, syslinux_bootsect, syslinux_bootsect_len, 0)
!= syslinux_bootsect_len) {
@@ -396,18 +440,66 @@ int install_bootblock(int fd, const char *device)
return 0;
}
+static int rewrite_boot_image(int devfd, const char *path, const char *filename)
+{
+ int fd;
+ int ret;
+ int modbytes;
+
+ /* Let's create LDLINUX.SYS file again (if it already exists, of course) */
+ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+ S_IRUSR | S_IRGRP | S_IROTH);
+ if (fd < 0) {
+ perror(filename);
+ return -1;
+ }
+
+ /* Write boot image data into LDLINUX.SYS file */
+ ret = xpwrite(fd, boot_image, boot_image_len, 0);
+ if (ret != boot_image_len) {
+ perror("writing bootblock");
+ goto error;
+ }
+
+ /* Write ADV */
+ ret = xpwrite(fd, syslinux_adv, 2 * ADV_SIZE, boot_image_len);
+ if (ret != 2 * ADV_SIZE) {
+ fprintf(stderr, "%s: write failure on %s\n", program, filename);
+ goto error;
+ }
+
+ /* Map the file, and patch the initial sector accordingly */
+ modbytes = patch_file_and_bootblock(fd, path, devfd);
+
+ /* Write the patch area again - this relies on the file being overwritten
+ * in place! */
+ ret = xpwrite(fd, boot_image, modbytes, 0);
+ if (ret != modbytes) {
+ fprintf(stderr, "%s: write failure on %s\n", program, filename);
+ goto error;
+ }
+
+ return fd;
+
+error:
+ close(fd);
+
+ return -1;
+}
+
int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
{
- char *file, *oldfile;
+ char *file, *oldfile, *c32file;
int fd = -1, dirfd = -1;
- int modbytes;
- int r1, r2;
+ int r1, r2, r3;
r1 = asprintf(&file, "%s%sldlinux.sys",
path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
r2 = asprintf(&oldfile, "%s%sextlinux.sys",
path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
- if (r1 < 0 || !file || r2 < 0 || !oldfile) {
+ r3 = asprintf(&c32file, "%s%sldlinux.c32",
+ path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+ if (r1 < 0 || !file || r2 < 0 || !oldfile || r3 < 0 || !c32file) {
perror(program);
return 1;
}
@@ -429,30 +521,9 @@ int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
}
close(fd);
- fd = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
- S_IRUSR | S_IRGRP | S_IROTH);
- if (fd < 0) {
- perror(file);
+ fd = rewrite_boot_image(devfd, path, file);
+ if (fd < 0)
goto bail;
- }
-
- /* Write it the first time */
- if (xpwrite(fd, boot_image, boot_image_len, 0) != boot_image_len ||
- xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
- boot_image_len) != 2 * ADV_SIZE) {
- fprintf(stderr, "%s: write failure on %s\n", program, file);
- goto bail;
- }
-
- /* Map the file, and patch the initial sector accordingly */
- modbytes = patch_file_and_bootblock(fd, path, devfd);
-
- /* Write the patch area again - this relies on the file being
- overwritten in place! */
- if (xpwrite(fd, boot_image, modbytes, 0) != modbytes) {
- fprintf(stderr, "%s: write failure on %s\n", program, file);
- goto bail;
- }
/* Attempt to set immutable flag and remove all write access */
/* Only set immutable flag if file is owned by root */
@@ -474,8 +545,22 @@ int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
unlink(oldfile);
}
+ fd = open(c32file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+ S_IRUSR | S_IRGRP | S_IROTH);
+ if (fd < 0) {
+ perror(c32file);
+ goto bail;
+ }
+
+ r3 = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+ if (r3 != syslinux_ldlinuxc32_len) {
+ fprintf(stderr, "%s: write failure on %s\n", program, c32file);
+ goto bail;
+ }
+
free(file);
free(oldfile);
+ free(c32file);
return 0;
bail:
@@ -486,6 +571,7 @@ bail:
free(file);
free(oldfile);
+ free(c32file);
return 1;
}
@@ -494,6 +580,9 @@ bail:
since the cow feature of btrfs will move the ldlinux.sys every where */
int btrfs_install_file(const char *path, int devfd, struct stat *rst)
{
+ char *file;
+ int fd, rv;
+
patch_file_and_bootblock(-1, path, devfd);
if (xpwrite(devfd, boot_image, boot_image_len, BTRFS_EXTLINUX_OFFSET)
!= boot_image_len) {
@@ -511,7 +600,125 @@ int btrfs_install_file(const char *path, int devfd, struct stat *rst)
perror(path);
return 1;
}
+
+ /*
+ * Note that we *can* install ldinux.c32 as a regular file because
+ * it doesn't need to be within the first 64K. The Syslinux core
+ * has enough smarts to search the btrfs dirs and find this file.
+ */
+ rv = asprintf(&file, "%s%sldlinux.c32",
+ path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+ if (rv < 0 || !file) {
+ perror(program);
+ return 1;
+ }
+
+ fd = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+ S_IRUSR | S_IRGRP | S_IROTH);
+ if (fd < 0) {
+ perror(file);
+ free(file);
+ return 1;
+ }
+
+ rv = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+ if (rv != (int)syslinux_ldlinuxc32_len) {
+ fprintf(stderr, "%s: write failure on %s\n", program, file);
+ rv = 1;
+ } else
+ rv = 0;
+
+ close(fd);
+ free(file);
+ return rv;
+}
+
+/*
+ * Due to historical reasons (SGI IRIX's design of disk layouts), the first
+ * sector in the primary AG on XFS filesystems contains the superblock, which is
+ * a problem with bootloaders that rely on BIOSes (that load VBRs which are
+ * (located in the first sector of the partition).
+ *
+ * Thus, we need to handle this issue, otherwise Syslinux will damage the XFS's
+ * superblock.
+ */
+static int xfs_install_file(const char *path, int devfd, struct stat *rst)
+{
+ static char file[PATH_MAX + 1];
+ static char c32file[PATH_MAX + 1];
+ int dirfd = -1;
+ int fd = -1;
+ int retval;
+
+ snprintf(file, PATH_MAX + 1, "%s%sldlinux.sys", path,
+ path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+ snprintf(c32file, PATH_MAX + 1, "%s%sldlinux.c32", path,
+ path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+
+ dirfd = open(path, O_RDONLY | O_DIRECTORY);
+ if (dirfd < 0) {
+ perror(path);
+ goto bail;
+ }
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ if (errno != ENOENT) {
+ perror(file);
+ goto bail;
+ }
+ } else {
+ clear_attributes(fd);
+ }
+
+ close(fd);
+
+ fd = rewrite_boot_image(devfd, path, file);
+ if (fd < 0)
+ goto bail;
+
+ /* Attempt to set immutable flag and remove all write access */
+ /* Only set immutable flag if file is owned by root */
+ set_attributes(fd);
+
+ if (fstat(fd, rst)) {
+ perror(file);
+ goto bail;
+ }
+
+ close(dirfd);
+ close(fd);
+
+ dirfd = -1;
+ fd = -1;
+
+ fd = open(c32file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+ S_IRUSR | S_IRGRP | S_IROTH);
+ if (fd < 0) {
+ perror(c32file);
+ goto bail;
+ }
+
+ retval = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+ if (retval != (int)syslinux_ldlinuxc32_len) {
+ fprintf(stderr, "%s: write failure on %s\n", program, file);
+ goto bail;
+ }
+
+ close(fd);
+
+ sync();
+
return 0;
+
+bail:
+ if (dirfd >= 0)
+ close(dirfd);
+
+ if (fd >= 0)
+ close(fd);
+
+ return 1;
}
/*
@@ -748,11 +955,14 @@ static char * get_default_subvol(char * rootdir, char * subvol)
static int install_file(const char *path, int devfd, struct stat *rst)
{
- if (fs_type == EXT2 || fs_type == VFAT || fs_type == NTFS)
- return ext2_fat_install_file(path, devfd, rst);
- else if (fs_type == BTRFS)
- return btrfs_install_file(path, devfd, rst);
- return 1;
+ if (fs_type == EXT2 || fs_type == VFAT || fs_type == NTFS)
+ return ext2_fat_install_file(path, devfd, rst);
+ else if (fs_type == BTRFS)
+ return btrfs_install_file(path, devfd, rst);
+ else if (fs_type == XFS)
+ return xfs_install_file(path, devfd, rst);
+
+ return 1;
}
#ifdef __KLIBC__
@@ -847,14 +1057,22 @@ static const char *find_device(const char *mtab_file, dev_t dev)
}
break;
+ case XFS:
+ if (!strcmp(mnt->mnt_type, "xfs") && !stat(mnt->mnt_fsname, &dst) &&
+ dst.st_rdev == dev) {
+ done = true;
+ break;
+ }
case NONE:
break;
}
+
if (done) {
devname = strdup(mnt->mnt_fsname);
break;
}
}
+
endmntent(mtab);
return devname;
@@ -915,6 +1133,8 @@ static const char *find_device_mountinfo(const char *path, dev_t dev)
struct stat st;
m = find_mount(path, NULL);
+ if (!m)
+ return NULL;
if (m->devpath[0] == '/' && m->dev == dev &&
!stat(m->devpath, &st) && S_ISBLK(st.st_mode) && st.st_rdev == dev)
@@ -1098,6 +1318,7 @@ static int open_device(const char *path, struct stat *st, const char **_devname)
fprintf(stderr, "%s: statfs %s: %s\n", program, path, strerror(errno));
return -1;
}
+
if (sfs.f_type == EXT2_SUPER_MAGIC)
fs_type = EXT2;
else if (sfs.f_type == BTRFS_SUPER_MAGIC)
@@ -1106,10 +1327,13 @@ static int open_device(const char *path, struct stat *st, const char **_devname)
fs_type = VFAT;
else if (sfs.f_type == NTFS_SB_MAGIC ||
sfs.f_type == FUSE_SUPER_MAGIC /* ntfs-3g */)
- fs_type = NTFS;
+ fs_type = NTFS;
+ else if (sfs.f_type == XFS_SUPER_MAGIC)
+ fs_type = XFS;
if (!fs_type) {
- fprintf(stderr, "%s: not a fat, ntfs, ext2/3/4 or btrfs filesystem: %s\n",
+ fprintf(stderr,
+ "%s: not a fat, ntfs, ext2/3/4, btrfs or xfs filesystem: %s\n",
program, path);
return -1;
}
@@ -1143,6 +1367,16 @@ static int btrfs_read_adv(int devfd)
return syslinux_validate_adv(syslinux_adv) ? 1 : 0;
}
+static inline int xfs_read_adv(int devfd)
+{
+ const size_t adv_size = 2 * ADV_SIZE;
+
+ if (xpread(devfd, syslinux_adv, adv_size, boot_image_len) != adv_size)
+ return -1;
+
+ return syslinux_validate_adv(syslinux_adv) ? 1 : 0;
+}
+
static int ext_read_adv(const char *path, int devfd, const char **namep)
{
int err;
@@ -1151,6 +1385,9 @@ static int ext_read_adv(const char *path, int devfd, const char **namep)
if (fs_type == BTRFS) {
/* btrfs "ldlinux.sys" is in 64k blank area */
return btrfs_read_adv(devfd);
+ } else if (fs_type == XFS) {
+ /* XFS "ldlinux.sys" is in the first 2048 bytes of the primary AG */
+ return xfs_read_adv(devfd);
} else {
err = read_adv(path, name = "ldlinux.sys");
if (err == 2) /* ldlinux.sys does not exist */
diff --git a/extlinux/misc.h b/extlinux/misc.h
new file mode 100644
index 00000000..7f2f1b33
--- /dev/null
+++ b/extlinux/misc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MISC_H_
+#define MISC_H_
+
+/* Return a 64-bit litte-endian value from a given 64-bit big-endian one */
+static inline uint64_t be64_to_cpu(uint64_t val)
+{
+ return (uint64_t)((((uint64_t)val & (uint64_t)0x00000000000000ffULL) << 56) |
+ (((uint64_t)val & (uint64_t)0x000000000000ff00ULL) << 40) |
+ (((uint64_t)val & (uint64_t)0x0000000000ff0000ULL) << 24) |
+ (((uint64_t)val & (uint64_t)0x00000000ff000000ULL) << 8) |
+ (((uint64_t)val & (uint64_t)0x000000ff00000000ULL) >> 8) |
+ (((uint64_t)val & (uint64_t)0x0000ff0000000000ULL) >> 24) |
+ (((uint64_t)val & (uint64_t)0x00ff000000000000ULL) >> 40) |
+ (((uint64_t)val & (uint64_t)0xff00000000000000ULL) >> 56));
+}
+
+/* Return a 32-bit litte-endian value from a given 32-bit big-endian one */
+static inline uint32_t be32_to_cpu(uint32_t val)
+{
+ return (uint32_t)((((uint32_t)val & (uint32_t)0x000000ffUL) << 24) |
+ (((uint32_t)val & (uint32_t)0x0000ff00UL) << 8) |
+ (((uint32_t)val & (uint32_t)0x00ff0000UL) >> 8) |
+ (((uint32_t)val & (uint32_t)0xff000000UL) >> 24));
+}
+
+/* Return a 16-bit litte-endian value from a given 16-bit big-endian one */
+static inline uint16_t be16_to_cpu(uint16_t val)
+{
+ return (uint16_t)((((uint16_t)val & (uint16_t)0x00ffU) << 8) |
+ (((uint16_t)val & (uint16_t)0xff00U) >> 8));
+}
+
+#endif /* MISC_H_ */
diff --git a/extlinux/xfs.h b/extlinux/xfs.h
new file mode 100644
index 00000000..412c2662
--- /dev/null
+++ b/extlinux/xfs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef XFS_H_
+#define XFS_H_
+
+#define XFS_SUPER_MAGIC 0x58465342
+
+#endif /* XFS_H_ */
diff --git a/extlinux/xfs_fs.h b/extlinux/xfs_fs.h
new file mode 100644
index 00000000..587820ec
--- /dev/null
+++ b/extlinux/xfs_fs.h
@@ -0,0 +1,501 @@
+/*
+ * Taken from Linux kernel tree (linux/fs/xfs)
+ *
+ * Copyright (c) 1995-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef XFS_FS_H_
+#define XFS_FS_H_
+
+/*
+ * SGI's XFS filesystem's major stuff (constants, structures)
+ */
+
+/*
+ * Direct I/O attribute record used with XFS_IOC_DIOINFO
+ * d_miniosz is the min xfer size, xfer size multiple and file seek offset
+ * alignment.
+ */
+struct dioattr {
+ uint32_t d_mem; /* data buffer memory alignment */
+ uint32_t d_miniosz; /* min xfer size */
+ uint32_t d_maxiosz; /* max xfer size */
+};
+
+/*
+ * Structure for XFS_IOC_FSGETXATTR[A] and XFS_IOC_FSSETXATTR.
+ */
+struct fsxattr {
+ uint32_t fsx_xflags; /* xflags field value (get/set) */
+ uint32_t fsx_extsize; /* extsize field value (get/set)*/
+ uint32_t fsx_nextents; /* nextents field value (get) */
+ uint32_t fsx_projid; /* project identifier (get/set) */
+ unsigned char fsx_pad[12];
+};
+
+/*
+ * Flags for the bs_xflags/fsx_xflags field
+ * There should be a one-to-one correspondence between these flags and the
+ * XFS_DIFLAG_s.
+ */
+#define XFS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */
+#define XFS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */
+#define XFS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */
+#define XFS_XFLAG_APPEND 0x00000010 /* all writes append */
+#define XFS_XFLAG_SYNC 0x00000020 /* all writes synchronous */
+#define XFS_XFLAG_NOATIME 0x00000040 /* do not update access time */
+#define XFS_XFLAG_NODUMP 0x00000080 /* do not include in backups */
+#define XFS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */
+#define XFS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */
+#define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */
+#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
+#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
+#define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
+#define XFS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
+#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
+
+/*
+ * Structure for XFS_IOC_GETBMAP.
+ * On input, fill in bmv_offset and bmv_length of the first structure
+ * to indicate the area of interest in the file, and bmv_entries with
+ * the number of array elements given back. The first structure is
+ * updated on return to give the offset and length for the next call.
+ */
+struct getbmap {
+ int64_t bmv_offset; /* file offset of segment in blocks */
+ int64_t bmv_block; /* starting block (64-bit daddr_t) */
+ int64_t bmv_length; /* length of segment, blocks */
+ int32_t bmv_count; /* # of entries in array incl. 1st */
+ int32_t bmv_entries; /* # of entries filled in (output) */
+};
+
+/*
+ * Structure for XFS_IOC_GETBMAPX. Fields bmv_offset through bmv_entries
+ * are used exactly as in the getbmap structure. The getbmapx structure
+ * has additional bmv_iflags and bmv_oflags fields. The bmv_iflags field
+ * is only used for the first structure. It contains input flags
+ * specifying XFS_IOC_GETBMAPX actions. The bmv_oflags field is filled
+ * in by the XFS_IOC_GETBMAPX command for each returned structure after
+ * the first.
+ */
+struct getbmapx {
+ int64_t bmv_offset; /* file offset of segment in blocks */
+ int64_t bmv_block; /* starting block (64-bit daddr_t) */
+ int64_t bmv_length; /* length of segment, blocks */
+ int32_t bmv_count; /* # of entries in array incl. 1st */
+ int32_t bmv_entries; /* # of entries filled in (output). */
+ int32_t bmv_iflags; /* input flags (1st structure) */
+ int32_t bmv_oflags; /* output flags (after 1st structure)*/
+ int32_t bmv_unused1; /* future use */
+ int32_t bmv_unused2; /* future use */
+};
+
+/* bmv_iflags values - set by XFS_IOC_GETBMAPX caller. */
+#define BMV_IF_ATTRFORK 0x1 /* return attr fork rather than data */
+#define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */
+#define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */
+#define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */
+#define BMV_IF_NO_HOLES 0x10 /* Do not return holes */
+#define BMV_IF_VALID \
+ (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC| \
+ BMV_IF_DELALLOC|BMV_IF_NO_HOLES)
+
+/* bmv_oflags values - returned for each non-header segment */
+#define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */
+#define BMV_OF_DELALLOC 0x2 /* segment = delayed allocation */
+#define BMV_OF_LAST 0x4 /* segment is the last in the file */
+
+/*
+ * Structure for XFS_IOC_FSSETDM.
+ * For use by backup and restore programs to set the XFS on-disk inode
+ * fields di_dmevmask and di_dmstate. These must be set to exactly and
+ * only values previously obtained via xfs_bulkstat! (Specifically the
+ * xfs_bstat_t fields bs_dmevmask and bs_dmstate.)
+ */
+struct fsdmidata {
+ uint32_t fsd_dmevmask; /* corresponds to di_dmevmask */
+ __u16 fsd_padding;
+ __u16 fsd_dmstate; /* corresponds to di_dmstate */
+};
+
+/*
+ * File segment locking set data type for 64 bit access.
+ * Also used for all the RESV/FREE interfaces.
+ */
+typedef struct xfs_flock64 {
+ __s16 l_type;
+ __s16 l_whence;
+ int64_t l_start;
+ int64_t l_len; /* len == 0 means until end of file */
+ int32_t l_sysid;
+ uint32_t l_pid;
+ int32_t l_pad[4]; /* reserve area */
+} xfs_flock64_t;
+
+/*
+ * Output for XFS_IOC_FSGEOMETRY_V1
+ */
+typedef struct xfs_fsop_geom_v1 {
+ uint32_t blocksize; /* filesystem (data) block size */
+ uint32_t rtextsize; /* realtime extent size */
+ uint32_t agblocks; /* fsblocks in an AG */
+ uint32_t agcount; /* number of allocation groups */
+ uint32_t logblocks; /* fsblocks in the log */
+ uint32_t sectsize; /* (data) sector size, bytes */
+ uint32_t inodesize; /* inode size in bytes */
+ uint32_t imaxpct; /* max allowed inode space(%) */
+ uint64_t datablocks; /* fsblocks in data subvolume */
+ uint64_t rtblocks; /* fsblocks in realtime subvol */
+ uint64_t rtextents; /* rt extents in realtime subvol*/
+ uint64_t logstart; /* starting fsblock of the log */
+ unsigned char uuid[16]; /* unique id of the filesystem */
+ uint32_t sunit; /* stripe unit, fsblocks */
+ uint32_t swidth; /* stripe width, fsblocks */
+ int32_t version; /* structure version */
+ uint32_t flags; /* superblock version flags */
+ uint32_t logsectsize; /* log sector size, bytes */
+ uint32_t rtsectsize; /* realtime sector size, bytes */
+ uint32_t dirblocksize; /* directory block size, bytes */
+} xfs_fsop_geom_v1_t;
+
+/*
+ * Output for XFS_IOC_FSGEOMETRY
+ */
+typedef struct xfs_fsop_geom {
+ uint32_t blocksize; /* filesystem (data) block size */
+ uint32_t rtextsize; /* realtime extent size */
+ uint32_t agblocks; /* fsblocks in an AG */
+ uint32_t agcount; /* number of allocation groups */
+ uint32_t logblocks; /* fsblocks in the log */
+ uint32_t sectsize; /* (data) sector size, bytes */
+ uint32_t inodesize; /* inode size in bytes */
+ uint32_t imaxpct; /* max allowed inode space(%) */
+ uint64_t datablocks; /* fsblocks in data subvolume */
+ uint64_t rtblocks; /* fsblocks in realtime subvol */
+ uint64_t rtextents; /* rt extents in realtime subvol*/
+ uint64_t logstart; /* starting fsblock of the log */
+ unsigned char uuid[16]; /* unique id of the filesystem */
+ uint32_t sunit; /* stripe unit, fsblocks */
+ uint32_t swidth; /* stripe width, fsblocks */
+ int32_t version; /* structure version */
+ uint32_t flags; /* superblock version flags */
+ uint32_t logsectsize; /* log sector size, bytes */
+ uint32_t rtsectsize; /* realtime sector size, bytes */
+ uint32_t dirblocksize; /* directory block size, bytes */
+ uint32_t logsunit; /* log stripe unit, bytes */
+} xfs_fsop_geom_t;
+
+/* Output for XFS_FS_COUNTS */
+typedef struct xfs_fsop_counts {
+ uint64_t freedata; /* free data section blocks */
+ uint64_t freertx; /* free rt extents */
+ uint64_t freeino; /* free inodes */
+ uint64_t allocino; /* total allocated inodes */
+} xfs_fsop_counts_t;
+
+/* Input/Output for XFS_GET_RESBLKS and XFS_SET_RESBLKS */
+typedef struct xfs_fsop_resblks {
+ uint64_t resblks;
+ uint64_t resblks_avail;
+} xfs_fsop_resblks_t;
+
+#define XFS_FSOP_GEOM_VERSION 0
+
+#define XFS_FSOP_GEOM_FLAGS_ATTR 0x0001 /* attributes in use */
+#define XFS_FSOP_GEOM_FLAGS_NLINK 0x0002 /* 32-bit nlink values */
+#define XFS_FSOP_GEOM_FLAGS_QUOTA 0x0004 /* quotas enabled */
+#define XFS_FSOP_GEOM_FLAGS_IALIGN 0x0008 /* inode alignment */
+#define XFS_FSOP_GEOM_FLAGS_DALIGN 0x0010 /* large data alignment */
+#define XFS_FSOP_GEOM_FLAGS_SHARED 0x0020 /* read-only shared */
+#define XFS_FSOP_GEOM_FLAGS_EXTFLG 0x0040 /* special extent flag */
+#define XFS_FSOP_GEOM_FLAGS_DIRV2 0x0080 /* directory version 2 */
+#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */
+#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */
+#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */
+#define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */
+#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */
+
+
+/*
+ * Minimum and maximum sizes need for growth checks
+ */
+#define XFS_MIN_AG_BLOCKS 64
+#define XFS_MIN_LOG_BLOCKS 512ULL
+#define XFS_MAX_LOG_BLOCKS (1024 * 1024ULL)
+#define XFS_MIN_LOG_BYTES (10 * 1024 * 1024ULL)
+
+/* keep the maximum size under 2^31 by a small amount */
+#define XFS_MAX_LOG_BYTES \
+ ((2 * 1024 * 1024 * 1024ULL) - XFS_MIN_LOG_BYTES)
+
+/* Used for sanity checks on superblock */
+#define XFS_MAX_DBLOCKS(s) ((xfs_drfsbno_t)(s)->sb_agcount * (s)->sb_agblocks)
+#define XFS_MIN_DBLOCKS(s) ((xfs_drfsbno_t)((s)->sb_agcount - 1) * \
+ (s)->sb_agblocks + XFS_MIN_AG_BLOCKS)
+
+/*
+ * Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT
+ */
+typedef struct xfs_growfs_data {
+ uint64_t newblocks; /* new data subvol size, fsblocks */
+ uint32_t imaxpct; /* new inode space percentage limit */
+} xfs_growfs_data_t;
+
+typedef struct xfs_growfs_log {
+ uint32_t newblocks; /* new log size, fsblocks */
+ uint32_t isint; /* 1 if new log is internal */
+} xfs_growfs_log_t;
+
+typedef struct xfs_growfs_rt {
+ uint64_t newblocks; /* new realtime size, fsblocks */
+ uint32_t extsize; /* new realtime extent size, fsblocks */
+} xfs_growfs_rt_t;
+
+
+/*
+ * Structures returned from ioctl XFS_IOC_FSBULKSTAT & XFS_IOC_FSBULKSTAT_SINGLE
+ */
+typedef struct xfs_bstime {
+ time_t tv_sec; /* seconds */
+ int32_t tv_nsec; /* and nanoseconds */
+} xfs_bstime_t;
+
+typedef struct xfs_bstat {
+ uint64_t bs_ino; /* inode number */
+ __u16 bs_mode; /* type and mode */
+ __u16 bs_nlink; /* number of links */
+ uint32_t bs_uid; /* user id */
+ uint32_t bs_gid; /* group id */
+ uint32_t bs_rdev; /* device value */
+ int32_t bs_blksize; /* block size */
+ int64_t bs_size; /* file size */
+ xfs_bstime_t bs_atime; /* access time */
+ xfs_bstime_t bs_mtime; /* modify time */
+ xfs_bstime_t bs_ctime; /* inode change time */
+ int64_t bs_blocks; /* number of blocks */
+ uint32_t bs_xflags; /* extended flags */
+ int32_t bs_extsize; /* extent size */
+ int32_t bs_extents; /* number of extents */
+ uint32_t bs_gen; /* generation count */
+ __u16 bs_projid_lo; /* lower part of project id */
+#define bs_projid bs_projid_lo /* (previously just bs_projid) */
+ __u16 bs_forkoff; /* inode fork offset in bytes */
+ __u16 bs_projid_hi; /* higher part of project id */
+ unsigned char bs_pad[10]; /* pad space, unused */
+ uint32_t bs_dmevmask; /* DMIG event mask */
+ __u16 bs_dmstate; /* DMIG state info */
+ __u16 bs_aextents; /* attribute number of extents */
+} xfs_bstat_t;
+
+/*
+ * The user-level BulkStat Request interface structure.
+ */
+typedef struct xfs_fsop_bulkreq {
+ uint64_t __user *lastip; /* last inode # pointer */
+ int32_t icount; /* count of entries in buffer */
+ void __user *ubuffer;/* user buffer for inode desc. */
+ int32_t __user *ocount; /* output count pointer */
+} xfs_fsop_bulkreq_t;
+
+
+/*
+ * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS).
+ */
+typedef struct xfs_inogrp {
+ uint64_t xi_startino; /* starting inode number */
+ int32_t xi_alloccount; /* # bits set in allocmask */
+ uint64_t xi_allocmask; /* mask of allocated inodes */
+} xfs_inogrp_t;
+
+
+/*
+ * Error injection.
+ */
+typedef struct xfs_error_injection {
+ int32_t fd;
+ int32_t errtag;
+} xfs_error_injection_t;
+
+
+/*
+ * The user-level Handle Request interface structure.
+ */
+typedef struct xfs_fsop_handlereq {
+ uint32_t fd; /* fd for FD_TO_HANDLE */
+ void __user *path; /* user pathname */
+ uint32_t oflags; /* open flags */
+ void __user *ihandle;/* user supplied handle */
+ uint32_t ihandlen; /* user supplied length */
+ void __user *ohandle;/* user buffer for handle */
+ uint32_t __user *ohandlen;/* user buffer length */
+} xfs_fsop_handlereq_t;
+
+/*
+ * Compound structures for passing args through Handle Request interfaces
+ * xfs_fssetdm_by_handle, xfs_attrlist_by_handle, xfs_attrmulti_by_handle
+ * - ioctls: XFS_IOC_FSSETDM_BY_HANDLE, XFS_IOC_ATTRLIST_BY_HANDLE, and
+ * XFS_IOC_ATTRMULTI_BY_HANDLE
+ */
+
+typedef struct xfs_fsop_setdm_handlereq {
+ struct xfs_fsop_handlereq hreq; /* handle information */
+ struct fsdmidata __user *data; /* DMAPI data */
+} xfs_fsop_setdm_handlereq_t;
+
+typedef struct xfs_attrlist_cursor {
+ uint32_t opaque[4];
+} xfs_attrlist_cursor_t;
+
+typedef struct xfs_fsop_attrlist_handlereq {
+ struct xfs_fsop_handlereq hreq; /* handle interface structure */
+ struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */
+ uint32_t flags; /* which namespace to use */
+ uint32_t buflen; /* length of buffer supplied */
+ void __user *buffer; /* returned names */
+} xfs_fsop_attrlist_handlereq_t;
+
+typedef struct xfs_attr_multiop {
+ uint32_t am_opcode;
+#define ATTR_OP_GET 1 /* return the indicated attr's value */
+#define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */
+#define ATTR_OP_REMOVE 3 /* remove the indicated attr */
+ int32_t am_error;
+ void __user *am_attrname;
+ void __user *am_attrvalue;
+ uint32_t am_length;
+ uint32_t am_flags;
+} xfs_attr_multiop_t;
+
+typedef struct xfs_fsop_attrmulti_handlereq {
+ struct xfs_fsop_handlereq hreq; /* handle interface structure */
+ uint32_t opcount;/* count of following multiop */
+ struct xfs_attr_multiop __user *ops; /* attr_multi data */
+} xfs_fsop_attrmulti_handlereq_t;
+
+/*
+ * per machine unique filesystem identifier types.
+ */
+typedef struct { uint32_t val[2]; } xfs_fsid_t; /* file system id type */
+
+typedef struct xfs_fid {
+ __u16 fid_len; /* length of remainder */
+ __u16 fid_pad;
+ uint32_t fid_gen; /* generation number */
+ uint64_t fid_ino; /* 64 bits inode number */
+} xfs_fid_t;
+
+typedef struct xfs_handle {
+ union {
+ int64_t align; /* force alignment of ha_fid */
+ xfs_fsid_t _ha_fsid; /* unique file system identifier */
+ } ha_u;
+ xfs_fid_t ha_fid; /* file system specific file ID */
+} xfs_handle_t;
+#define ha_fsid ha_u._ha_fsid
+
+#define XFS_HSIZE(handle) (((char *) &(handle).ha_fid.fid_pad \
+ - (char *) &(handle)) \
+ + (handle).ha_fid.fid_len)
+
+/*
+ * Flags for going down operation
+ */
+#define XFS_FSOP_GOING_FLAGS_DEFAULT 0x0 /* going down */
+#define XFS_FSOP_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
+#define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
+
+/*
+ * ioctl commands that are used by Linux filesystems
+ */
+#define XFS_IOC_GETXFLAGS FS_IOC_GETFLAGS
+#define XFS_IOC_SETXFLAGS FS_IOC_SETFLAGS
+#define XFS_IOC_GETVERSION FS_IOC_GETVERSION
+
+/*
+ * ioctl commands that replace IRIX fcntl()'s
+ * For 'documentation' purposed more than anything else,
+ * the "cmd #" field reflects the IRIX fcntl number.
+ */
+#define XFS_IOC_ALLOCSP _IOW ('X', 10, struct xfs_flock64)
+#define XFS_IOC_FREESP _IOW ('X', 11, struct xfs_flock64)
+#define XFS_IOC_DIOINFO _IOR ('X', 30, struct dioattr)
+#define XFS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr)
+#define XFS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr)
+#define XFS_IOC_ALLOCSP64 _IOW ('X', 36, struct xfs_flock64)
+#define XFS_IOC_FREESP64 _IOW ('X', 37, struct xfs_flock64)
+#define XFS_IOC_GETBMAP _IOWR('X', 38, struct getbmap)
+#define XFS_IOC_FSSETDM _IOW ('X', 39, struct fsdmidata)
+#define XFS_IOC_RESVSP _IOW ('X', 40, struct xfs_flock64)
+#define XFS_IOC_UNRESVSP _IOW ('X', 41, struct xfs_flock64)
+#define XFS_IOC_RESVSP64 _IOW ('X', 42, struct xfs_flock64)
+#define XFS_IOC_UNRESVSP64 _IOW ('X', 43, struct xfs_flock64)
+#define XFS_IOC_GETBMAPA _IOWR('X', 44, struct getbmap)
+#define XFS_IOC_FSGETXATTRA _IOR ('X', 45, struct fsxattr)
+/* XFS_IOC_SETBIOSIZE ---- deprecated 46 */
+/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
+#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
+#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
+
+/*
+ * ioctl commands that replace IRIX syssgi()'s
+ */
+#define XFS_IOC_FSGEOMETRY_V1 _IOR ('X', 100, struct xfs_fsop_geom_v1)
+#define XFS_IOC_FSBULKSTAT _IOWR('X', 101, struct xfs_fsop_bulkreq)
+#define XFS_IOC_FSBULKSTAT_SINGLE _IOWR('X', 102, struct xfs_fsop_bulkreq)
+#define XFS_IOC_FSINUMBERS _IOWR('X', 103, struct xfs_fsop_bulkreq)
+#define XFS_IOC_PATH_TO_FSHANDLE _IOWR('X', 104, struct xfs_fsop_handlereq)
+#define XFS_IOC_PATH_TO_HANDLE _IOWR('X', 105, struct xfs_fsop_handlereq)
+#define XFS_IOC_FD_TO_HANDLE _IOWR('X', 106, struct xfs_fsop_handlereq)
+#define XFS_IOC_OPEN_BY_HANDLE _IOWR('X', 107, struct xfs_fsop_handlereq)
+#define XFS_IOC_READLINK_BY_HANDLE _IOWR('X', 108, struct xfs_fsop_handlereq)
+#define XFS_IOC_SWAPEXT _IOWR('X', 109, struct xfs_swapext)
+#define XFS_IOC_FSGROWFSDATA _IOW ('X', 110, struct xfs_growfs_data)
+#define XFS_IOC_FSGROWFSLOG _IOW ('X', 111, struct xfs_growfs_log)
+#define XFS_IOC_FSGROWFSRT _IOW ('X', 112, struct xfs_growfs_rt)
+#define XFS_IOC_FSCOUNTS _IOR ('X', 113, struct xfs_fsop_counts)
+#define XFS_IOC_SET_RESBLKS _IOWR('X', 114, struct xfs_fsop_resblks)
+#define XFS_IOC_GET_RESBLKS _IOR ('X', 115, struct xfs_fsop_resblks)
+#define XFS_IOC_ERROR_INJECTION _IOW ('X', 116, struct xfs_error_injection)
+#define XFS_IOC_ERROR_CLEARALL _IOW ('X', 117, struct xfs_error_injection)
+/* XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 118 */
+/* XFS_IOC_FREEZE -- FIFREEZE 119 */
+/* XFS_IOC_THAW -- FITHAW 120 */
+#define XFS_IOC_FSSETDM_BY_HANDLE _IOW ('X', 121, struct xfs_fsop_setdm_handlereq)
+#define XFS_IOC_ATTRLIST_BY_HANDLE _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
+#define XFS_IOC_ATTRMULTI_BY_HANDLE _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
+#define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom)
+#define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t)
+/* XFS_IOC_GETFSUUID ---------- deprecated 140 */
+
+
+#ifndef HAVE_BBMACROS
+/*
+ * Block I/O parameterization. A basic block (BB) is the lowest size of
+ * filesystem allocation, and must equal 512. Length units given to bio
+ * routines are in BB's.
+ */
+#define BBSHIFT 9
+#define BBSIZE (1<<BBSHIFT)
+#define BBMASK (BBSIZE-1)
+#define BTOBB(bytes) (((uint64_t)(bytes) + BBSIZE - 1) >> BBSHIFT)
+#define BTOBBT(bytes) ((uint64_t)(bytes) >> BBSHIFT)
+#define BBTOB(bbs) ((bbs) << BBSHIFT)
+#endif
+
+#endif /* XFS_FS_H_ */
diff --git a/extlinux/xfs_sb.h b/extlinux/xfs_sb.h
new file mode 100644
index 00000000..8f72d6ad
--- /dev/null
+++ b/extlinux/xfs_sb.h
@@ -0,0 +1,476 @@
+/*
+ * Taken from Linux kernel tree (linux/fs/xfs)
+ *
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef XFS_SB_H_
+#define XFS_SB_H__
+
+#include <stddef.h>
+
+#include <sys/types.h>
+#include <uuid/uuid.h>
+
+/*
+ * Super block
+ * Fits into a sector-sized buffer at address 0 of each allocation group.
+ * Only the first of these is ever updated except during growfs.
+ */
+
+struct xfs_buf;
+struct xfs_mount;
+
+#define XFS_SB_MAGIC "XFSB" /* 'XFSB' */
+#define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */
+#define XFS_SB_VERSION_2 2 /* 6.2 - attributes */
+#define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */
+#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
+#define XFS_SB_VERSION_NUMBITS 0x000f
+#define XFS_SB_VERSION_ALLFBITS 0xfff0
+#define XFS_SB_VERSION_SASHFBITS 0xf000
+#define XFS_SB_VERSION_REALFBITS 0x0ff0
+#define XFS_SB_VERSION_ATTRBIT 0x0010
+#define XFS_SB_VERSION_NLINKBIT 0x0020
+#define XFS_SB_VERSION_QUOTABIT 0x0040
+#define XFS_SB_VERSION_ALIGNBIT 0x0080
+#define XFS_SB_VERSION_DALIGNBIT 0x0100
+#define XFS_SB_VERSION_SHAREDBIT 0x0200
+#define XFS_SB_VERSION_LOGV2BIT 0x0400
+#define XFS_SB_VERSION_SECTORBIT 0x0800
+#define XFS_SB_VERSION_EXTFLGBIT 0x1000
+#define XFS_SB_VERSION_DIRV2BIT 0x2000
+#define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */
+#define XFS_SB_VERSION_MOREBITSBIT 0x8000
+#define XFS_SB_VERSION_OKSASHFBITS \
+ (XFS_SB_VERSION_EXTFLGBIT | \
+ XFS_SB_VERSION_DIRV2BIT | \
+ XFS_SB_VERSION_BORGBIT)
+#define XFS_SB_VERSION_OKREALFBITS \
+ (XFS_SB_VERSION_ATTRBIT | \
+ XFS_SB_VERSION_NLINKBIT | \
+ XFS_SB_VERSION_QUOTABIT | \
+ XFS_SB_VERSION_ALIGNBIT | \
+ XFS_SB_VERSION_DALIGNBIT | \
+ XFS_SB_VERSION_SHAREDBIT | \
+ XFS_SB_VERSION_LOGV2BIT | \
+ XFS_SB_VERSION_SECTORBIT | \
+ XFS_SB_VERSION_MOREBITSBIT)
+#define XFS_SB_VERSION_OKREALBITS \
+ (XFS_SB_VERSION_NUMBITS | \
+ XFS_SB_VERSION_OKREALFBITS | \
+ XFS_SB_VERSION_OKSASHFBITS)
+
+/*
+ * There are two words to hold XFS "feature" bits: the original
+ * word, sb_versionnum, and sb_features2. Whenever a bit is set in
+ * sb_features2, the feature bit XFS_SB_VERSION_MOREBITSBIT must be set.
+ *
+ * These defines represent bits in sb_features2.
+ */
+#define XFS_SB_VERSION2_REALFBITS 0x00ffffff /* Mask: features */
+#define XFS_SB_VERSION2_RESERVED1BIT 0x00000001
+#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */
+#define XFS_SB_VERSION2_RESERVED4BIT 0x00000004
+#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
+#define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */
+#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32 bit project id */
+
+#define XFS_SB_VERSION2_OKREALFBITS \
+ (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
+ XFS_SB_VERSION2_ATTR2BIT | \
+ XFS_SB_VERSION2_PROJID32BIT)
+#define XFS_SB_VERSION2_OKSASHFBITS \
+ (0)
+#define XFS_SB_VERSION2_OKREALBITS \
+ (XFS_SB_VERSION2_OKREALFBITS | \
+ XFS_SB_VERSION2_OKSASHFBITS )
+
+/*
+ * Superblock - in core version. Must match the ondisk version below.
+ * Must be padded to 64 bit alignment.
+ */
+typedef struct xfs_sb {
+ uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ uint32_t sb_blocksize; /* logical block size, bytes */
+ xfs_drfsbno_t sb_dblocks; /* number of data blocks */
+ xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */
+ xfs_drtbno_t sb_rextents; /* number of realtime extents */
+ uuid_t sb_uuid; /* file system unique id */
+ xfs_dfsbno_t sb_logstart; /* starting block of log if internal */
+ xfs_ino_t sb_rootino; /* root inode number */
+ xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */
+ xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */
+ xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */
+ xfs_agblock_t sb_agblocks; /* size of an allocation group */
+ xfs_agnumber_t sb_agcount; /* number of allocation groups */
+ xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */
+ xfs_extlen_t sb_logblocks; /* number of log blocks */
+ uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
+ uint16_t sb_sectsize; /* volume sector size, bytes */
+ uint16_t sb_inodesize; /* inode size, bytes */
+ uint16_t sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ uint8_t sb_blocklog; /* log2 of sb_blocksize */
+ uint8_t sb_sectlog; /* log2 of sb_sectsize */
+ uint8_t sb_inodelog; /* log2 of sb_inodesize */
+ uint8_t sb_inopblog; /* log2 of sb_inopblock */
+ uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ uint8_t sb_rextslog; /* log2 of sb_rextents */
+ uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
+ uint8_t sb_imax_pct; /* max % of fs for inode space */
+ /* statistics */
+ /*
+ * These fields must remain contiguous. If you really
+ * want to change their layout, make sure you fix the
+ * code in xfs_trans_apply_sb_deltas().
+ */
+ uint64_t sb_icount; /* allocated inodes */
+ uint64_t sb_ifree; /* free inodes */
+ uint64_t sb_fdblocks; /* free data blocks */
+ uint64_t sb_frextents; /* free realtime extents */
+ /*
+ * End contiguous fields.
+ */
+ xfs_ino_t sb_uquotino; /* user quota inode */
+ xfs_ino_t sb_gquotino; /* group quota inode */
+ uint16_t sb_qflags; /* quota flags */
+ uint8_t sb_flags; /* misc. flags */
+ uint8_t sb_shared_vn; /* shared version number */
+ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ uint32_t sb_unit; /* stripe or raid unit */
+ uint32_t sb_width; /* stripe or raid width */
+ uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
+ uint8_t sb_logsectlog; /* log2 of the log sector size */
+ uint16_t sb_logsectsize; /* sector size for the log, bytes */
+ uint32_t sb_logsunit; /* stripe unit size for the log */
+ uint32_t sb_features2; /* additional feature bits */
+
+ /*
+ * bad features2 field as a result of failing to pad the sb
+ * structure to 64 bits. Some machines will be using this field
+ * for features2 bits. Easiest just to mark it bad and not use
+ * it for anything else.
+ */
+ uint32_t sb_bad_features2;
+
+ /* must be padded to 64 bit alignment */
+} xfs_sb_t;
+
+/*
+ * Sequence number values for the fields.
+ */
+typedef enum {
+ XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS,
+ XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO,
+ XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS,
+ XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS,
+ XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE,
+ XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG,
+ XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG,
+ XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT,
+ XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
+ XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
+ XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
+ XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
+ XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2,
+ XFS_SBS_FIELDCOUNT
+} xfs_sb_field_t;
+
+/*
+ * Mask values, defined based on the xfs_sb_field_t values.
+ * Only define the ones we're using.
+ */
+#define XFS_SB_MVAL(x) (1LL << XFS_SBS_ ## x)
+#define XFS_SB_UUID XFS_SB_MVAL(UUID)
+#define XFS_SB_FNAME XFS_SB_MVAL(FNAME)
+#define XFS_SB_ROOTINO XFS_SB_MVAL(ROOTINO)
+#define XFS_SB_RBMINO XFS_SB_MVAL(RBMINO)
+#define XFS_SB_RSUMINO XFS_SB_MVAL(RSUMINO)
+#define XFS_SB_VERSIONNUM XFS_SB_MVAL(VERSIONNUM)
+#define XFS_SB_UQUOTINO XFS_SB_MVAL(UQUOTINO)
+#define XFS_SB_GQUOTINO XFS_SB_MVAL(GQUOTINO)
+#define XFS_SB_QFLAGS XFS_SB_MVAL(QFLAGS)
+#define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN)
+#define XFS_SB_UNIT XFS_SB_MVAL(UNIT)
+#define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH)
+#define XFS_SB_ICOUNT XFS_SB_MVAL(ICOUNT)
+#define XFS_SB_IFREE XFS_SB_MVAL(IFREE)
+#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
+#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)
+#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2)
+#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
+#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)
+#define XFS_SB_MOD_BITS \
+ (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
+ XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
+ XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
+ XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
+ XFS_SB_BAD_FEATURES2)
+
+
+/*
+ * Misc. Flags - warning - these will be cleared by xfs_repair unless
+ * a feature bit is set when the flag is used.
+ */
+#define XFS_SBF_NOFLAGS 0x00 /* no flags set */
+#define XFS_SBF_READONLY 0x01 /* only read-only mounts allowed */
+
+/*
+ * define max. shared version we can interoperate with
+ */
+#define XFS_SB_MAX_SHARED_VN 0
+
+#define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS)
+
+static inline int xfs_sb_good_version(xfs_sb_t *sbp)
+{
+ /* We always support version 1-3 */
+ if (sbp->sb_versionnum >= XFS_SB_VERSION_1 &&
+ sbp->sb_versionnum <= XFS_SB_VERSION_3)
+ return 1;
+
+ /* We support version 4 if all feature bits are supported */
+ if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) {
+ if ((sbp->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) ||
+ ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) &&
+ (sbp->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
+ return 0;
+
+ if ((sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) &&
+ sbp->sb_shared_vn > XFS_SB_MAX_SHARED_VN)
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Detect a mismatched features2 field. Older kernels read/wrote
+ * this into the wrong slot, so to be safe we keep them in sync.
+ */
+static inline int xfs_sb_has_mismatched_features2(xfs_sb_t *sbp)
+{
+ return (sbp->sb_bad_features2 != sbp->sb_features2);
+}
+
+static inline unsigned xfs_sb_version_tonew(unsigned v)
+{
+ if (v == XFS_SB_VERSION_1)
+ return XFS_SB_VERSION_4;
+
+ if (v == XFS_SB_VERSION_2)
+ return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT;
+
+ return XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT |
+ XFS_SB_VERSION_NLINKBIT;
+}
+
+static inline unsigned xfs_sb_version_toold(unsigned v)
+{
+ if (v & (XFS_SB_VERSION_QUOTABIT | XFS_SB_VERSION_ALIGNBIT))
+ return 0;
+ if (v & XFS_SB_VERSION_NLINKBIT)
+ return XFS_SB_VERSION_3;
+ if (v & XFS_SB_VERSION_ATTRBIT)
+ return XFS_SB_VERSION_2;
+ return XFS_SB_VERSION_1;
+}
+
+static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp)
+{
+ return sbp->sb_versionnum == XFS_SB_VERSION_2 ||
+ sbp->sb_versionnum == XFS_SB_VERSION_3 ||
+ (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT));
+}
+
+static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)
+{
+ if (sbp->sb_versionnum == XFS_SB_VERSION_1)
+ sbp->sb_versionnum = XFS_SB_VERSION_2;
+ else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
+ sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
+ else
+ sbp->sb_versionnum = XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT;
+}
+
+static inline int xfs_sb_version_hasnlink(xfs_sb_t *sbp)
+{
+ return sbp->sb_versionnum == XFS_SB_VERSION_3 ||
+ (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT));
+}
+
+static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)
+{
+ if (sbp->sb_versionnum <= XFS_SB_VERSION_2)
+ sbp->sb_versionnum = XFS_SB_VERSION_3;
+ else
+ sbp->sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
+}
+
+static inline int xfs_sb_version_hasquota(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT);
+}
+
+static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)
+{
+ if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
+ sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT;
+ else
+ sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) |
+ XFS_SB_VERSION_QUOTABIT;
+}
+
+static inline int xfs_sb_version_hasalign(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT);
+}
+
+static inline int xfs_sb_version_hasdalign(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT);
+}
+
+static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT);
+}
+
+static inline int xfs_sb_version_hasdirv2(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
+}
+
+static inline int xfs_sb_version_haslogv2(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT);
+}
+
+static inline int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT);
+}
+
+static inline int xfs_sb_version_hassector(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
+}
+
+static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
+}
+
+static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
+ (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT);
+}
+
+/*
+ * sb_features2 bit version macros.
+ *
+ * For example, for a bit defined as XFS_SB_VERSION2_FUNBIT, has a macro:
+ *
+ * SB_VERSION_HASFUNBIT(xfs_sb_t *sbp)
+ * ((xfs_sb_version_hasmorebits(sbp) &&
+ * ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
+ */
+
+static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp)
+{
+ return xfs_sb_version_hasmorebits(sbp) &&
+ (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT);
+}
+
+static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
+{
+ return xfs_sb_version_hasmorebits(sbp) &&
+ (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT);
+}
+
+static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
+{
+ sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
+ sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
+}
+
+static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)
+{
+ sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
+ if (!sbp->sb_features2)
+ sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
+}
+
+static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
+{
+ return xfs_sb_version_hasmorebits(sbp) &&
+ (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
+}
+
+/*
+ * end of superblock version macros
+ */
+
+#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */
+#define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
+#define XFS_BUF_TO_SBP(bp) ((xfs_dsb_t *)((bp)->b_addr))
+
+#define XFS_HDR_BLOCK(mp,d) ((xfs_agblock_t)XFS_BB_TO_FSBT(mp,d))
+#define XFS_DADDR_TO_FSB(mp,d) XFS_AGB_TO_FSB(mp, \
+ xfs_daddr_to_agno(mp,d), xfs_daddr_to_agbno(mp,d))
+#define XFS_FSB_TO_DADDR(mp,fsbno) XFS_AGB_TO_DADDR(mp, \
+ XFS_FSB_TO_AGNO(mp,fsbno), XFS_FSB_TO_AGBNO(mp,fsbno))
+
+/*
+ * File system sector to basic block conversions.
+ */
+#define XFS_FSS_TO_BB(mp,sec) ((sec) << (mp)->m_sectbb_log)
+
+/*
+ * File system block to basic block conversions.
+ */
+#define XFS_FSB_TO_BB(mp,fsbno) ((fsbno) << (mp)->m_blkbb_log)
+#define XFS_BB_TO_FSB(mp,bb) \
+ (((bb) + (XFS_FSB_TO_BB(mp,1) - 1)) >> (mp)->m_blkbb_log)
+#define XFS_BB_TO_FSBT(mp,bb) ((bb) >> (mp)->m_blkbb_log)
+
+/*
+ * File system block to byte conversions.
+ */
+#define XFS_FSB_TO_B(mp,fsbno) ((xfs_fsize_t)(fsbno) << (mp)->m_sb.sb_blocklog)
+#define XFS_B_TO_FSB(mp,b) \
+ ((((uint64_t)(b)) + (mp)->m_blockmask) >> (mp)->m_sb.sb_blocklog)
+#define XFS_B_TO_FSBT(mp,b) (((uint64_t)(b)) >> (mp)->m_sb.sb_blocklog)
+#define XFS_B_FSB_OFFSET(mp,b) ((b) & (mp)->m_blockmask)
+
+#endif /* XFS_SB_H_ */
diff --git a/extlinux/xfs_types.h b/extlinux/xfs_types.h
new file mode 100644
index 00000000..92808865
--- /dev/null
+++ b/extlinux/xfs_types.h
@@ -0,0 +1,135 @@
+/*
+ * Taken from Linux kernel tree (linux/fs/xfs)
+ *
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef XFS_TYPES_H_
+#define XFS_TYPES_H_
+
+#include <stddef.h>
+
+#include <sys/types.h>
+
+typedef enum { B_FALSE,B_TRUE } boolean_t;
+typedef uint32_t prid_t; /* project ID */
+typedef uint32_t inst_t; /* an instruction */
+
+typedef int64_t xfs_off_t; /* <file offset> type */
+typedef unsigned long long xfs_ino_t; /* <inode> type */
+typedef int64_t xfs_daddr_t; /* <disk address> type */
+typedef char * xfs_caddr_t; /* <core address> type */
+typedef uint32_t xfs_dev_t;
+typedef uint32_t xfs_nlink_t;
+
+/* __psint_t is the same size as a pointer */
+typedef int32_t __psint_t;
+typedef uint32_t __psunsigned_t;
+
+typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */
+typedef uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef uint32_t xfs_agnumber_t; /* allocation group number */
+typedef int32_t xfs_extnum_t; /* # of extents in a file */
+typedef int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef int64_t xfs_fsize_t; /* bytes in a file */
+typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */
+
+typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */
+typedef int32_t xfs_rtword_t; /* word type for bitmap manipulations */
+
+typedef int64_t xfs_lsn_t; /* log sequence number */
+typedef int32_t xfs_tid_t; /* transaction identifier */
+
+typedef uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
+typedef uint32_t xfs_dahash_t; /* dir/attr hash value */
+
+/*
+ * These types are 64 bits on disk but are either 32 or 64 bits in memory.
+ * Disk based types:
+ */
+typedef uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
+typedef uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
+typedef uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
+typedef uint64_t xfs_dfiloff_t; /* block number in a file */
+typedef uint64_t xfs_dfilblks_t; /* number of blocks in a file */
+
+/*
+ * Memory based types are conditional.
+ */
+typedef uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
+typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */
+typedef uint64_t xfs_rtblock_t; /* extent (block) in realtime area */
+typedef int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */
+
+typedef uint64_t xfs_fileoff_t; /* block number in a file */
+typedef int64_t xfs_sfiloff_t; /* signed block number in a file */
+typedef uint64_t xfs_filblks_t; /* number of blocks in a file */
+
+/*
+ * Null values for the types.
+ */
+#define NULLDFSBNO ((xfs_dfsbno_t)-1)
+#define NULLDRFSBNO ((xfs_drfsbno_t)-1)
+#define NULLDRTBNO ((xfs_drtbno_t)-1)
+#define NULLDFILOFF ((xfs_dfiloff_t)-1)
+
+#define NULLFSBLOCK ((xfs_fsblock_t)-1)
+#define NULLRFSBLOCK ((xfs_rfsblock_t)-1)
+#define NULLRTBLOCK ((xfs_rtblock_t)-1)
+#define NULLFILEOFF ((xfs_fileoff_t)-1)
+
+#define NULLAGBLOCK ((xfs_agblock_t)-1)
+#define NULLAGNUMBER ((xfs_agnumber_t)-1)
+#define NULLEXTNUM ((xfs_extnum_t)-1)
+
+#define NULLCOMMITLSN ((xfs_lsn_t)-1)
+
+/*
+ * Max values for extlen, extnum, aextnum.
+ */
+#define MAXEXTLEN ((xfs_extlen_t)0x001fffff) /* 21 bits */
+#define MAXEXTNUM ((xfs_extnum_t)0x7fffffff) /* signed int */
+#define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */
+
+/*
+ * Min numbers of data/attr fork btree root pointers.
+ */
+#define MINDBTPTRS 3
+#define MINABTPTRS 2
+
+/*
+ * MAXNAMELEN is the length (including the terminating null) of
+ * the longest permissible file (component) name.
+ */
+#define MAXNAMELEN 256
+
+typedef enum {
+ XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
+} xfs_lookup_t;
+
+typedef enum {
+ XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi,
+ XFS_BTNUM_MAX
+} xfs_btnum_t;
+
+struct xfs_name {
+ const unsigned char *name;
+ int len;
+};
+
+#endif /* XFS_TYPES_H_ */