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