[lxc-devel] [PATCH v2] Fix btrfs bus error on sparc on snapshot delete
Serge Hallyn
serge.hallyn at ubuntu.com
Fri Jan 15 00:38:19 UTC 2016
Quoting Thomas Tanaka (thomas.tanaka at oracle.com):
> 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.tanaka at oracle.com>
Thanks!
Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.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 at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
More information about the lxc-devel
mailing list