diff -up util-linux-2.23.2/libblkid/src/superblocks/superblocks.c.kzak util-linux-2.23.2/libblkid/src/superblocks/superblocks.c --- util-linux-2.23.2/libblkid/src/superblocks/superblocks.c.kzak 2015-06-24 12:58:20.790115492 +0200 +++ util-linux-2.23.2/libblkid/src/superblocks/superblocks.c 2015-06-24 12:57:57.961286166 +0200 @@ -49,6 +49,8 @@ * * @UUID_SUB: subvolume uuid (e.g. btrfs) * + * @LOGUUID: external log UUID (e.g. xfs) + * * @UUID_RAW: raw UUID from FS superblock * * @EXT_JOURNAL: external journal UUID @@ -113,6 +115,7 @@ static const struct blkid_idinfo *idinfo &swsuspend_idinfo, &swap_idinfo, &xfs_idinfo, + &xfs_log_idinfo, &ext4dev_idinfo, &ext4_idinfo, &ext3_idinfo, diff -up util-linux-2.23.2/libblkid/src/superblocks/superblocks.h.kzak util-linux-2.23.2/libblkid/src/superblocks/superblocks.h --- util-linux-2.23.2/libblkid/src/superblocks/superblocks.h.kzak 2015-06-24 12:58:48.533908071 +0200 +++ util-linux-2.23.2/libblkid/src/superblocks/superblocks.h 2015-06-24 12:59:00.098821476 +0200 @@ -29,6 +29,7 @@ extern const struct blkid_idinfo ext2_id extern const struct blkid_idinfo jbd_idinfo; extern const struct blkid_idinfo jfs_idinfo; extern const struct blkid_idinfo xfs_idinfo; +extern const struct blkid_idinfo xfs_log_idinfo; extern const struct blkid_idinfo gfs_idinfo; extern const struct blkid_idinfo gfs2_idinfo; extern const struct blkid_idinfo romfs_idinfo; diff -up util-linux-2.23.2/libblkid/src/superblocks/xfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/xfs.c --- util-linux-2.23.2/libblkid/src/superblocks/xfs.c.kzak 2015-06-24 12:39:34.300507071 +0200 +++ util-linux-2.23.2/libblkid/src/superblocks/xfs.c 2015-06-24 12:39:45.389427015 +0200 @@ -4,6 +4,7 @@ * Copyright (C) 2001 by Andreas Dilger * Copyright (C) 2004 Kay Sievers * Copyright (C) 2008 Karel Zak + * Copyright (C) 2013 Eric Sandeen * * This file may be redistributed under the terms of the * GNU Lesser General Public License. @@ -187,3 +188,90 @@ const struct blkid_idinfo xfs_idinfo = } }; +struct xlog_rec_header { + uint32_t h_magicno; + uint32_t h_dummy1[1]; + uint32_t h_version; + uint32_t h_len; + uint32_t h_dummy2[71]; + uint32_t h_fmt; + unsigned char h_uuid[16]; +} __attribute__((packed)); + +#define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe + +/* + * For very small filesystems, the minimum log size + * can be smaller, but that seems vanishingly unlikely + * when used with an external log (which is used for + * performance reasons; tiny conflicts with that goal). + */ +#define XFS_MIN_LOG_BYTES (10 * 1024 * 1024) + +#define XLOG_FMT_LINUX_LE 1 +#define XLOG_FMT_LINUX_BE 2 +#define XLOG_FMT_IRIX_BE 3 + +#define XLOG_VERSION_1 1 +#define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */ +#define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2) + +static int xlog_valid_rec_header(struct xlog_rec_header *rhead) +{ + uint32_t hlen; + + if (rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) + return 0; + + if (!rhead->h_version || + (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))) + return 0; + + /* LR body must have data or it wouldn't have been written */ + hlen = be32_to_cpu(rhead->h_len); + if (hlen <= 0 || hlen > INT_MAX) + return 0; + + if (rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_LE) && + rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_BE) && + rhead->h_fmt != cpu_to_be32(XLOG_FMT_IRIX_BE)) + return 0; + + return 1; +} + +/* xlog record header will be in some sector in the first 256k */ +static int probe_xfs_log(blkid_probe pr, const struct blkid_idmag *mag) +{ + int i; + struct xlog_rec_header *rhead; + unsigned char *buf; + + buf = blkid_probe_get_buffer(pr, 0, 256*1024); + if (!buf) + return errno ? -errno : 1; + + if (memcmp(buf, "XFSB", 4) == 0) + return 1; /* this is regular XFS, ignore */ + + /* check the first 512 512-byte sectors */ + for (i = 0; i < 512; i++) { + rhead = (struct xlog_rec_header *)&buf[i*512]; + + if (xlog_valid_rec_header(rhead)) { + blkid_probe_set_uuid_as(pr, rhead->h_uuid, "LOGUUID"); + return 0; + } + } + + return 1; +} + +const struct blkid_idinfo xfs_log_idinfo = +{ + .name = "xfs_external_log", + .usage = BLKID_USAGE_OTHER, + .probefunc = probe_xfs_log, + .magics = BLKID_NONE_MAGIC, + .minsz = XFS_MIN_LOG_BYTES, +};