There are some unaligned accesses in progs that cause malfunction or crashes on ARM. This patch fixes the ones we stumbled upon. Signed-off-by: Arne Jansen <sensille@gmx.net> --- btrfs-list.c | 69 +++++++++++++++++++++++++++------------------------------ volumes.c | 8 ++++-- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/btrfs-list.c b/btrfs-list.c index e5f0f96..cb42fbc 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -720,7 +720,7 @@ static u64 find_root_gen(int fd) int ret; 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; unsigned long off = 0; u64 max_found = 0; int i; @@ -771,22 +771,21 @@ static u64 find_root_gen(int fd) off = 0; for (i = 0; i < sk->nr_items; i++) { struct btrfs_root_item *item; - sh = (struct btrfs_ioctl_search_header *)(args.buf + - off); - off += sizeof(*sh); + memcpy(&sh, args.buf + off, sizeof(sh)); + off += sizeof(sh); item = (struct btrfs_root_item *)(args.buf + off); - off += sh->len; + off += sh.len; - 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; - if (sh->objectid > ino_args.treeid) + if (sh.objectid > ino_args.treeid) break; - if (sh->objectid == ino_args.treeid && - sh->type == BTRFS_ROOT_ITEM_KEY) { + if (sh.objectid == ino_args.treeid && + sh.type == BTRFS_ROOT_ITEM_KEY) { max_found = max(max_found, btrfs_root_generation(item)); } @@ -1009,7 +1008,7 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup) int ret; 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 btrfs_root_item *ri; unsigned long off = 0; @@ -1064,23 +1063,22 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup) * read the root_ref item it contains */ for (i = 0; i < sk->nr_items; i++) { - sh = (struct btrfs_ioctl_search_header *)(args.buf + - off); - off += sizeof(*sh); - if (sh->type == BTRFS_ROOT_BACKREF_KEY) { + memcpy(&sh, args.buf + off, sizeof(sh)); + off += sizeof(sh); + if (sh.type == BTRFS_ROOT_BACKREF_KEY) { ref = (struct btrfs_root_ref *)(args.buf + off); name_len = btrfs_stack_root_ref_name_len(ref); name = (char *)(ref + 1); dir_id = btrfs_stack_root_ref_dirid(ref); - add_root(root_lookup, sh->objectid, sh->offset, + add_root(root_lookup, sh.objectid, sh.offset, 0, 0, dir_id, name, name_len, 0, 0, 0, NULL); - } else if (sh->type == BTRFS_ROOT_ITEM_KEY) { + } else if (sh.type == BTRFS_ROOT_ITEM_KEY) { ri = (struct btrfs_root_item *)(args.buf + off); gen = btrfs_root_generation(ri); flags = btrfs_root_flags(ri); - if(sh->len > + if(sh.len > sizeof(struct btrfs_root_item_v0)) { t = ri->otime.sec; ogen = btrfs_root_otransid(ri); @@ -1091,20 +1089,20 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup) memset(uuid, 0, BTRFS_UUID_SIZE); } - add_root(root_lookup, sh->objectid, 0, - sh->offset, flags, 0, NULL, 0, ogen, + add_root(root_lookup, sh.objectid, 0, + sh.offset, flags, 0, NULL, 0, ogen, gen, t, uuid); } - 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++; @@ -1556,7 +1554,7 @@ int btrfs_list_find_updated_files(int fd, u64 root_id, u64 oldest_gen) int ret; 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_file_extent_item *item; unsigned long off = 0; u64 found_gen; @@ -1606,35 +1604,34 @@ int btrfs_list_find_updated_files(int fd, u64 root_id, u64 oldest_gen) * read the root_ref item it contains */ 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); /* * just in case the item was too big, pass something other * than garbage */ - if (sh->len == 0) + if (sh.len == 0) item = &backup; else item = (struct btrfs_file_extent_item *)(args.buf + off); found_gen = btrfs_stack_file_extent_generation(item); - if (sh->type == BTRFS_EXTENT_DATA_KEY && + if (sh.type == BTRFS_EXTENT_DATA_KEY && found_gen >= oldest_gen) { - print_one_extent(fd, sh, item, found_gen, + print_one_extent(fd, &sh, item, found_gen, &cache_dirid, &cache_dir_name, &cache_ino, &cache_full_name); } - 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_offset = sh->offset; - sk->min_type = sh->type; + sk->min_objectid = sh.objectid; + sk->min_offset = sh.offset; + sk->min_type = sh.type; } sk->nr_items = 4096; if (sk->min_offset < (u64)-1) diff --git a/volumes.c b/volumes.c index 8dca5e1..581c298 100644 --- a/volumes.c +++ b/volumes.c @@ -652,6 +652,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, int index; int stripe_len = 64 * 1024; struct btrfs_key key; + u64 offset; if (list_empty(dev_list)) { return -ENOSPC; @@ -757,12 +758,13 @@ again: } return -ENOSPC; } - key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; - key.type = BTRFS_CHUNK_ITEM_KEY; ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID, - &key.offset); + &offset); if (ret) return ret; + key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; + key.type = BTRFS_CHUNK_ITEM_KEY; + key.offset = offset; chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); if (!chunk) -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html