This series extents the fsinfo ioctl by adding two new often requested
members, the filesystem generation and the metadata UUID. Both can be
retrieved from the kernel by setting the appropriate flag in the ioctl
structure.
The last patch adds a compile time assertion on the structure sizes, so we're
not accidentally breaking size assumptions.
The series was tested using the following test tool, strace support will be
written once the kernel side is accepted.
--- 8< ---
#include <linux/types.h>
#include <linux/btrfs.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
struct btrfs_ioctl_fs_info_args_new {
__u64 max_id; /* out */
__u64 num_devices; /* out */
__u8 fsid[BTRFS_FSID_SIZE]; /* out */
__u32 nodesize; /* out */
__u32 sectorsize; /* out */
__u32 clone_alignment; /* out */
__u32 flags; /* out */
__u16 csum_type;
__u16 csum_size;
__u32 generation;
__u8 metadata_uuid[BTRFS_FSID_SIZE];
__u8 reserved[952]; /* pad to 1k */
};
#define BTRFS_FS_INFO_FLAG_CSUM_TYPE_SIZE (1 << 0)
#define BTRFS_FS_INFO_FLAG_GENERATION (1 << 1)
#define BTRFS_FS_INFO_FLAG_METADATA_UUID (1 << 2)
static const char hex_chars[16] = "0123456789abcdef";
# define BYTE_HEX_CHARS(b_) \
hex_chars[((uint8_t) (b_)) >> 4], hex_chars[((uint8_t) (b_)) & 0xf]
void format_uuid(const unsigned char *uuid, char *buf)
{
const char str[] = {
BYTE_HEX_CHARS(uuid[0]),
BYTE_HEX_CHARS(uuid[1]),
BYTE_HEX_CHARS(uuid[2]),
BYTE_HEX_CHARS(uuid[3]),
'-',
BYTE_HEX_CHARS(uuid[4]),
BYTE_HEX_CHARS(uuid[5]),
'-',
BYTE_HEX_CHARS(uuid[6]),
BYTE_HEX_CHARS(uuid[7]),
'-',
BYTE_HEX_CHARS(uuid[8]),
BYTE_HEX_CHARS(uuid[9]),
'-',
BYTE_HEX_CHARS(uuid[10]),
BYTE_HEX_CHARS(uuid[11]),
BYTE_HEX_CHARS(uuid[12]),
BYTE_HEX_CHARS(uuid[13]),
BYTE_HEX_CHARS(uuid[14]),
BYTE_HEX_CHARS(uuid[15]),
'\0'
};
sprintf(buf, "%s", str);
}
int call_ioctl(int fd, bool csum, bool gen, bool meta)
{
struct btrfs_ioctl_fs_info_args_new args = { 0 };
char fsid[37], meta_uuid[37];
int ret;
if (csum)
args.flags |= BTRFS_FS_INFO_FLAG_CSUM_TYPE_SIZE;
if (gen)
args.flags |= BTRFS_FS_INFO_FLAG_GENERATION;
if (meta)
args.flags |= BTRFS_FS_INFO_FLAG_METADATA_UUID;
ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args);
if (ret < 0) {
perror("ioctl");
return ret;
}
format_uuid(args.fsid, fsid);
format_uuid(args.metadata_uuid, meta_uuid);
printf("\tfsid: %s\n", fsid);
printf("\tmax_id: %llu\n", args.max_id);
printf("\tnum_devices: %llu\n", args.num_devices);
printf("\tnodesize: %u\n", args.nodesize);
printf("\tsectorsize: %u\n", args.sectorsize);
printf("\tclone_alignment: %u\n", args.clone_alignment);
printf("\tflags: 0x%x\n", args.flags);
if (args.flags & BTRFS_FS_INFO_FLAG_CSUM_TYPE_SIZE) {
printf("\tcsum_type: %u\n", args.csum_type);
printf("\tcsum_size: %u\n", args.csum_size);
}
if (args.flags & BTRFS_FS_INFO_FLAG_GENERATION)
printf("\tgeneration: %u\n", args.generation);
if (args.flags & BTRFS_FS_INFO_FLAG_METADATA_UUID)
printf("\tmetadata UUID: %s\n", meta_uuid);
return 0;
}
int main(int argc, char **argv)
{
int fd, ret;
if (argc != 2) {
printf("Usage: %s file\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDWR);
if (fd == -1) {
perror("open");
exit(1);
}
printf("%s: (old)\n", argv[1]);
ret = call_ioctl(fd, false, false, false);
if (ret)
goto close_fd;
printf("%s: (new)\n", argv[1]);
ret = call_ioctl(fd, true, true, true);
close_fd:
close(fd);
exit(EXIT_SUCCESS);
}
--- >8 ---
Johannes Thumshirn (3):
btrfs: add filesystem generation to fsinfo ioctl
btrfs: add metadata_uuid to fsinfo ioctl
btrfs: assert sizes of ioctl structures
fs/btrfs/ioctl.c | 11 +++++++++++
include/uapi/linux/btrfs.h | 19 +++++++++++++++++--
2 files changed, 28 insertions(+), 2 deletions(-)
--
2.26.2
