The following patch fixes memory alignment and endianness issue while doing a snapshot deletion with btrfs as a backing store on platform such as sparc.
The implementation is taken from btrfs-progs. Changes since v1: - include <byteswap.h> for bswap definition - include defined function name as a comment above BTRFS_SETGET_STACK_FUNCS Signed-off-by: Thomas Tanaka <thomas.tan...@oracle.com> --- src/lxc/bdev/lxcbtrfs.c | 28 +++++++++++++++------------- src/lxc/bdev/lxcbtrfs.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c index 2db7c87..0f8c1fc 100644 --- a/src/lxc/bdev/lxcbtrfs.c +++ b/src/lxc/bdev/lxcbtrfs.c @@ -565,7 +565,7 @@ static int btrfs_recursive_destroy(const char *path) int fd; struct btrfs_ioctl_search_args args; struct btrfs_ioctl_search_key *sk = &args.key; - struct btrfs_ioctl_search_header *sh; + struct btrfs_ioctl_search_header sh; struct btrfs_root_ref *ref; struct my_btrfs_tree *tree; int ret, i; @@ -573,6 +573,7 @@ static int btrfs_recursive_destroy(const char *path) int name_len; char *name; char *tmppath; + u64 dir_id; fd = open(path, O_RDONLY); if (fd < 0) { @@ -624,21 +625,22 @@ static int btrfs_recursive_destroy(const char *path) off = 0; for (i = 0; i < sk->nr_items; i++) { - sh = (struct btrfs_ioctl_search_header *)(args.buf + off); - off += sizeof(*sh); + memcpy(&sh, args.buf + off, sizeof(sh)); + off += sizeof(sh); /* * A backref key with the name and dirid of the parent * comes followed by the reoot ref key which has the * name of the child subvol in question. */ - if (sh->objectid != root_id && sh->type == BTRFS_ROOT_BACKREF_KEY) { + if (sh.objectid != root_id && sh.type == BTRFS_ROOT_BACKREF_KEY) { ref = (struct btrfs_root_ref *)(args.buf + off); - name_len = ref->name_len; + name_len = btrfs_stack_root_ref_name_len(ref); name = (char *)(ref + 1); - tmppath = get_btrfs_subvol_path(fd, sh->offset, - ref->dirid, name, name_len); - if (!add_btrfs_tree_node(tree, sh->objectid, - sh->offset, name, + dir_id = btrfs_stack_root_ref_dirid(ref); + tmppath = get_btrfs_subvol_path(fd, sh.offset, + dir_id, name, name_len); + if (!add_btrfs_tree_node(tree, sh.objectid, + sh.offset, name, name_len, tmppath)) { ERROR("Out of memory"); free_btrfs_tree(tree); @@ -648,15 +650,15 @@ static int btrfs_recursive_destroy(const char *path) } free(tmppath); } - off += sh->len; + off += sh.len; /* * record the mins in sk so we can make sure the * next search doesn't repeat this root */ - sk->min_objectid = sh->objectid; - sk->min_type = sh->type; - sk->min_offset = sh->offset; + sk->min_objectid = sh.objectid; + sk->min_type = sh.type; + sk->min_offset = sh.offset; } sk->nr_items = 4096; sk->min_offset++; diff --git a/src/lxc/bdev/lxcbtrfs.h b/src/lxc/bdev/lxcbtrfs.h index e0adb7a..3b2742f 100644 --- a/src/lxc/bdev/lxcbtrfs.h +++ b/src/lxc/bdev/lxcbtrfs.h @@ -28,6 +28,7 @@ #include <linux/types.h> /* __le64, __l32 ... */ #include <stdbool.h> #include <stdint.h> +#include <byteswap.h> typedef uint8_t u8; typedef uint16_t u16; @@ -317,6 +318,50 @@ struct btrfs_ioctl_ino_lookup_args { #define BTRFS_LAST_FREE_OBJECTID -256ULL #define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL +/* + * The followings are macro for correctly getting member of + * structures in both low and big endian platforms as per + * btrfs-progs + */ +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#else +#define __force +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_le64(x) ((__force __le64)(u64)(bswap_64(x))) +#define le64_to_cpu(x) ((__force u64)(__le64)(bswap_64(x))) +#define cpu_to_le32(x) ((__force __le32)(u32)(bswap_32(x))) +#define le32_to_cpu(x) ((__force u32)(__le32)(bswap_32(x))) +#define cpu_to_le16(x) ((__force __le16)(u16)(bswap_16(x))) +#define le16_to_cpu(x) ((__force u16)(__le16)(bswap_16(x))) +#else +#define cpu_to_le64(x) ((__force __le64)(u64)(x)) +#define le64_to_cpu(x) ((__force u64)(__le64)(x)) +#define cpu_to_le32(x) ((__force __le32)(u32)(x)) +#define le32_to_cpu(x) ((__force u32)(__le32)(x)) +#define cpu_to_le16(x) ((__force __le16)(u16)(x)) +#define le16_to_cpu(x) ((__force u16)(__le16)(x)) +#endif + +#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ +static inline u##bits btrfs_##name(type *s) \ +{ \ + return le##bits##_to_cpu(s->member); \ +} \ +static inline void btrfs_set_##name(type *s, u##bits val) \ +{ \ + s->member = cpu_to_le##bits(val); \ +} + +/* defined as btrfs_stack_root_ref_dirid */ +BTRFS_SETGET_STACK_FUNCS(stack_root_ref_dirid, struct btrfs_root_ref, dirid, 64); +/* defined as btrfs_stack_root_ref_sequence */ +BTRFS_SETGET_STACK_FUNCS(stack_root_ref_sequence, struct btrfs_root_ref, sequence, 64); +/* defined as btrfs_stack_root_ref_name_len */ +BTRFS_SETGET_STACK_FUNCS(stack_root_ref_name_len, struct btrfs_root_ref, name_len, 16); + /* defined in bdev.h */ struct bdev; -- 1.7.1 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel