Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
Marek BehĂșn | 7777b1a | 2017-09-03 17:00:27 +0200 | [diff] [blame] | 2 | /* |
| 3 | * Functions to convert BTRFS structures from disk to CPU endianness and back. |
| 4 | * |
| 5 | * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz |
Marek BehĂșn | 7777b1a | 2017-09-03 17:00:27 +0200 | [diff] [blame] | 6 | */ |
| 7 | |
| 8 | #ifndef __BTRFS_CONV_FUNCS_H__ |
| 9 | #define __BTRFS_CONV_FUNCS_H__ |
| 10 | |
| 11 | #include "ctree.h" |
| 12 | #include <u-boot/variadic-macro.h> |
| 13 | #include <asm/byteorder.h> |
| 14 | |
| 15 | /* We are using variadic macros and C11 _Generic to achieve compact code. |
| 16 | |
| 17 | We want to define macro DEFINE_CONV(x, ...), where the first argument is the |
| 18 | name of the structure for which it shall define conversion functions (the |
| 19 | names of the functions shall be x_to_cpu and x_to_disk), and the other |
| 20 | arguments are names of the members on which the functions shall do |
| 21 | endianness conversion. */ |
| 22 | |
| 23 | #if defined(__LITTLE_ENDIAN) |
| 24 | |
| 25 | /* If the target machine is little endian, the conversion functions do |
| 26 | nothing, since the on disk format is little endian. */ |
| 27 | |
| 28 | # define DEFINE_CONV(n,...) \ |
| 29 | static inline struct n *n##_to_disk(struct n * r) \ |
| 30 | { \ |
| 31 | return r; \ |
| 32 | } \ |
| 33 | static inline struct n *n##_to_cpu(struct n * r) \ |
| 34 | { \ |
| 35 | return r; \ |
| 36 | } |
| 37 | |
| 38 | # define DEFINE_CONV_ALT(n,a,...) \ |
| 39 | static inline struct n *n##_to_disk_##a(struct n * r) \ |
| 40 | { \ |
| 41 | return r; \ |
| 42 | } \ |
| 43 | static inline struct n *n##_to_cpu_##a(struct n * r) \ |
| 44 | { \ |
| 45 | return r; \ |
| 46 | } |
| 47 | |
| 48 | #else /* !defined(__LITTLE_ENDIAN) */ |
| 49 | |
| 50 | /* Some structures contain not only scalar members, but compound types as well |
| 51 | (for example, struct btrfs_inode_item contains members of type struct |
| 52 | btrfs_timespec. |
| 53 | |
| 54 | For these members we want to call the conversion function recursively, so |
| 55 | first we declare the functions taking pointers to this types (these function |
| 56 | will be defined later by the DEFINE_CONV macro) and then we define |
| 57 | correspond functions taking non-pointers, so that they can be used in the |
| 58 | expansion of the _Generic. */ |
| 59 | # define DEFINE_CONV_FOR_STRUCT(n) \ |
| 60 | static inline struct n * n##_to_disk(struct n *); \ |
| 61 | static inline struct n * n##_to_cpu(struct n *); \ |
| 62 | static inline struct n n##_to_disk_v(struct n x) { \ |
| 63 | return *n##_to_disk(&x); \ |
| 64 | } \ |
| 65 | static inline struct n n##_to_cpu_v(struct n x) { \ |
| 66 | return *n##_to_cpu(&x); \ |
| 67 | } |
| 68 | |
| 69 | DEFINE_CONV_FOR_STRUCT(btrfs_key) |
| 70 | DEFINE_CONV_FOR_STRUCT(btrfs_stripe) |
| 71 | DEFINE_CONV_FOR_STRUCT(btrfs_timespec) |
| 72 | DEFINE_CONV_FOR_STRUCT(btrfs_inode_item) |
| 73 | DEFINE_CONV_FOR_STRUCT(btrfs_root_backup) |
| 74 | DEFINE_CONV_FOR_STRUCT(btrfs_dev_item) |
| 75 | |
| 76 | /* Now define the _Generic for both CPU to LE and LE to CPU */ |
| 77 | # define DEFINE_CONV_CPU_TO_LE(x) \ |
| 78 | (d->x) = _Generic((d->x), \ |
| 79 | __u16: cpu_to_le16, \ |
| 80 | __u32: cpu_to_le32, \ |
| 81 | __u64: cpu_to_le64, \ |
| 82 | struct btrfs_key: btrfs_key_to_disk_v, \ |
| 83 | struct btrfs_stripe: btrfs_stripe_to_disk_v, \ |
| 84 | struct btrfs_timespec: btrfs_timespec_to_disk_v, \ |
| 85 | struct btrfs_inode_item: btrfs_inode_item_to_disk_v, \ |
| 86 | struct btrfs_root_backup: btrfs_root_backup_to_disk_v, \ |
| 87 | struct btrfs_dev_item: btrfs_dev_item_to_disk_v \ |
| 88 | )((d->x)); |
| 89 | |
| 90 | # define DEFINE_CONV_LE_TO_CPU(x) \ |
| 91 | (d->x) = _Generic((d->x), \ |
| 92 | __u16: le16_to_cpu, \ |
| 93 | __u32: le32_to_cpu, \ |
| 94 | __u64: le64_to_cpu, \ |
| 95 | struct btrfs_key: btrfs_key_to_cpu_v, \ |
| 96 | struct btrfs_stripe: btrfs_stripe_to_cpu_v, \ |
| 97 | struct btrfs_timespec: btrfs_timespec_to_cpu_v, \ |
| 98 | struct btrfs_inode_item: btrfs_inode_item_to_cpu_v, \ |
| 99 | struct btrfs_root_backup: btrfs_root_backup_to_cpu_v, \ |
| 100 | struct btrfs_dev_item: btrfs_dev_item_to_cpu_v \ |
| 101 | )((d->x)); |
| 102 | |
| 103 | # define DEFINE_CONV_ONE(t,n,m,...) \ |
| 104 | static inline struct t * n(struct t * d) { \ |
| 105 | CALL_MACRO_FOR_EACH(m, ##__VA_ARGS__) \ |
| 106 | return d; \ |
| 107 | } |
| 108 | |
| 109 | /* Finally define the DEFINE_CONV macro */ |
| 110 | # define DEFINE_CONV(n,...) \ |
| 111 | DEFINE_CONV_ONE(n,n##_to_disk,DEFINE_CONV_CPU_TO_LE,##__VA_ARGS__) \ |
| 112 | DEFINE_CONV_ONE(n,n##_to_cpu,DEFINE_CONV_LE_TO_CPU,##__VA_ARGS__) |
| 113 | |
| 114 | # define DEFINE_CONV_ALT(n,a,...) \ |
| 115 | DEFINE_CONV_ONE(n,n##_to_disk_##a,DEFINE_CONV_CPU_TO_LE, \ |
| 116 | ##__VA_ARGS__) \ |
| 117 | DEFINE_CONV_ONE(n,n##_to_cpu_##a,DEFINE_CONV_LE_TO_CPU,##__VA_ARGS__) |
| 118 | |
| 119 | #endif /* !defined(__LITTLE_ENDIAN) */ |
| 120 | |
| 121 | DEFINE_CONV(btrfs_key, objectid, offset) |
| 122 | DEFINE_CONV(btrfs_dev_item, devid, total_bytes, bytes_used, io_align, io_width, |
| 123 | sector_size, type, generation, start_offset, dev_group) |
| 124 | DEFINE_CONV(btrfs_stripe, devid, offset) |
| 125 | DEFINE_CONV(btrfs_chunk, length, owner, stripe_len, type, io_align, io_width, |
| 126 | sector_size, num_stripes, sub_stripes) |
| 127 | DEFINE_CONV(btrfs_free_space_entry, offset, bytes) |
| 128 | DEFINE_CONV(btrfs_free_space_header, location, generation, num_entries, |
| 129 | num_bitmaps) |
| 130 | DEFINE_CONV(btrfs_extent_item, refs, generation, flags) |
| 131 | DEFINE_CONV(btrfs_tree_block_info, key) |
| 132 | DEFINE_CONV(btrfs_extent_data_ref, root, objectid, offset, count) |
| 133 | DEFINE_CONV(btrfs_shared_data_ref, count) |
| 134 | DEFINE_CONV(btrfs_extent_inline_ref, offset) |
| 135 | DEFINE_CONV(btrfs_dev_extent, chunk_tree, chunk_objectid, chunk_offset, length) |
| 136 | DEFINE_CONV(btrfs_inode_ref, index, name_len) |
| 137 | DEFINE_CONV(btrfs_inode_extref, parent_objectid, index, name_len) |
| 138 | DEFINE_CONV(btrfs_timespec, sec, nsec) |
| 139 | DEFINE_CONV(btrfs_inode_item, generation, transid, size, nbytes, block_group, |
| 140 | nlink, uid, gid, mode, rdev, flags, sequence, atime, ctime, mtime, |
| 141 | otime) |
| 142 | DEFINE_CONV(btrfs_dir_log_item, end) |
| 143 | DEFINE_CONV(btrfs_dir_item, location, transid, data_len, name_len) |
| 144 | DEFINE_CONV(btrfs_root_item, inode, generation, root_dirid, bytenr, byte_limit, |
| 145 | bytes_used, last_snapshot, flags, refs, drop_progress, |
| 146 | generation_v2, ctransid, otransid, stransid, rtransid, ctime, |
| 147 | otime, stime, rtime) |
| 148 | DEFINE_CONV(btrfs_root_ref, dirid, sequence, name_len) |
| 149 | DEFINE_CONV(btrfs_file_extent_item, generation, ram_bytes, other_encoding, |
| 150 | disk_bytenr, disk_num_bytes, offset, num_bytes) |
| 151 | DEFINE_CONV_ALT(btrfs_file_extent_item, inl, generation, ram_bytes, |
| 152 | other_encoding) |
| 153 | DEFINE_CONV(btrfs_dev_replace_item, src_devid, cursor_left, cursor_right, |
| 154 | cont_reading_from_srcdev_mode, replace_state, time_started, |
| 155 | time_stopped, num_write_errors, num_uncorrectable_read_errors) |
| 156 | DEFINE_CONV(btrfs_block_group_item, used, chunk_objectid, flags) |
| 157 | DEFINE_CONV(btrfs_free_space_info, extent_count, flags) |
| 158 | |
| 159 | DEFINE_CONV(btrfs_header, bytenr, flags, generation, owner, nritems) |
| 160 | DEFINE_CONV(btrfs_root_backup, tree_root, tree_root_gen, chunk_root, |
| 161 | chunk_root_gen, extent_root, extent_root_gen, fs_root, fs_root_gen, |
| 162 | dev_root, dev_root_gen, csum_root, csum_root_gen, total_bytes, |
| 163 | bytes_used, num_devices) |
| 164 | DEFINE_CONV(btrfs_super_block, bytenr, flags, magic, generation, root, |
| 165 | chunk_root, log_root, log_root_transid, total_bytes, bytes_used, |
| 166 | root_dir_objectid, num_devices, sectorsize, nodesize, |
| 167 | __unused_leafsize, stripesize, sys_chunk_array_size, |
| 168 | chunk_root_generation, compat_flags, compat_ro_flags, |
| 169 | incompat_flags, csum_type, dev_item, cache_generation, |
| 170 | uuid_tree_generation, super_roots[0], super_roots[1], |
| 171 | super_roots[2], super_roots[3]) |
| 172 | DEFINE_CONV(btrfs_item, key, offset, size) |
| 173 | DEFINE_CONV(btrfs_key_ptr, key, blockptr, generation) |
| 174 | |
| 175 | #endif /* __BTRFS_CONV_FUNCS_H__ */ |