1 /*
2  * Copyright (C) 2007 Oracle.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18 
19 /// D translation of extent_io.h from btrfs-progs (v5.9)
20 module btrfs.c.kernel_shared.extent_io;
21 
22 import core.stdc.config;
23 
24 import btrfs.c.kerncompat;
25 import btrfs.c.kernel_lib.list;
26 import btrfs.c.common.extent_cache;
27 
28 import btrfs.c.kernel_shared.ctree : btrfs_fs_info;
29 
30 enum EXTENT_DIRTY		= 1U << 0;
31 enum EXTENT_WRITEBACK	= 1U << 1;
32 enum EXTENT_UPTODATE		= 1U << 2;
33 enum EXTENT_LOCKED		= 1U << 3;
34 enum EXTENT_NEW		= 1U << 4;
35 enum EXTENT_DELALLOC		= 1U << 5;
36 enum EXTENT_DEFRAG		= 1U << 6;
37 enum EXTENT_DEFRAG_DONE	= 1U << 7;
38 enum EXTENT_BUFFER_FILLED	= 1U << 8;
39 enum EXTENT_CSUM		= 1U << 9;
40 enum EXTENT_BAD_TRANSID	= 1U << 10;
41 enum EXTENT_BUFFER_DUMMY	= 1U << 11;
42 enum EXTENT_IOBITS = EXTENT_LOCKED | EXTENT_WRITEBACK;
43 
44 enum BLOCK_GROUP_DATA	= 1U << 1;
45 enum BLOCK_GROUP_METADATA	= 1U << 2;
46 enum BLOCK_GROUP_SYSTEM	= 1U << 4;
47 
48 /*
49  * The extent buffer bitmap operations are done with byte granularity instead of
50  * word granularity for two reasons:
51  * 1. The bitmaps must be little-endian on disk.
52  * 2. Bitmap items are not guaranteed to be aligned to a word and therefore a
53  *    single word in a bitmap may straddle two pages in the extent buffer.
54  */
55 auto BIT_BYTE(T)(T nr) { return nr / BITS_PER_BYTE; }
56 enum BYTE_MASK = (1 << BITS_PER_BYTE) - 1;
57 auto BITMAP_FIRST_BYTE_MASK(T)(T start) { return
58 	((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK); }
59 auto BITMAP_LAST_BYTE_MASK(T)(T nbits) { return 
60 	(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1))); }
61 
62 int le_test_bit(int nr, const u8 *addr)
63 {
64 	return 1U & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE-1)));
65 }
66 
67 struct extent_io_tree {
68 	cache_tree state;
69 	cache_tree cache;
70 	list_head lru;
71 	u64 cache_size;
72 	u64 max_cache_size;
73 }
74 
75 struct extent_state {
76 	cache_extent cache_node;
77 	u64 start;
78 	u64 end;
79 	int refs;
80 	c_ulong state;
81 	u64 xprivate;
82 }
83 
84 struct extent_buffer {
85 	cache_extent cache_node;
86 	u64 start;
87 	u64 dev_bytenr;
88 	list_head lru;
89 	list_head recow;
90 	u32 len;
91 	int refs;
92 	u32 flags;
93 	int fd;
94 	btrfs_fs_info *fs_info;
95 	align(8) char[0] data;
96 }
97 
98 void extent_buffer_get()(extent_buffer *eb)
99 {
100 	eb.refs++;
101 }
102 
103 void extent_io_tree_init(extent_io_tree *tree);
104 void extent_io_tree_init_cache_max(extent_io_tree *tree,
105 				   u64 max_cache_size);
106 void extent_io_tree_cleanup(extent_io_tree *tree);
107 int set_extent_bits(extent_io_tree *tree, u64 start, u64 end, int bits);
108 int clear_extent_bits(extent_io_tree *tree, u64 start, u64 end, int bits);
109 int find_first_extent_bit(extent_io_tree *tree, u64 start,
110 			  u64 *start_ret, u64 *end_ret, int bits);
111 int test_range_bit(extent_io_tree *tree, u64 start, u64 end,
112 		   int bits, int filled);
113 int set_extent_dirty(extent_io_tree *tree, u64 start, u64 end);
114 int clear_extent_dirty(extent_io_tree *tree, u64 start, u64 end);
115 int set_extent_buffer_uptodate(extent_buffer *eb)
116 {
117 	eb.flags |= EXTENT_UPTODATE;
118 	return 0;
119 }
120 
121 int clear_extent_buffer_uptodate(extent_buffer *eb)
122 {
123 	eb.flags &= ~EXTENT_UPTODATE;
124 	return 0;
125 }
126 
127 int extent_buffer_uptodate(extent_buffer *eb)
128 {
129 	if (!eb || IS_ERR(eb))
130 		return 0;
131 	if (eb.flags & EXTENT_UPTODATE)
132 		return 1;
133 	return 0;
134 }
135 
136 int set_state_private(extent_io_tree *tree, u64 start, u64 xprivate);
137 int get_state_private(extent_io_tree *tree, u64 start, u64 *xprivate);
138 extent_buffer *find_extent_buffer(extent_io_tree *tree,
139 					 u64 bytenr, u32 blocksize);
140 extent_buffer *find_first_extent_buffer(extent_io_tree *tree,
141 					       u64 start);
142 extent_buffer *alloc_extent_buffer(btrfs_fs_info *fs_info,
143 					  u64 bytenr, u32 blocksize);
144 extent_buffer *btrfs_clone_extent_buffer(extent_buffer *src);
145 extent_buffer *alloc_dummy_extent_buffer(btrfs_fs_info *fs_info,
146 						u64 bytenr, u32 blocksize);
147 void free_extent_buffer(extent_buffer *eb);
148 void free_extent_buffer_nocache(extent_buffer *eb);
149 int read_extent_from_disk(extent_buffer *eb,
150 			  c_ulong offset, ulong len);
151 int write_extent_to_disk(extent_buffer *eb);
152 int memcmp_extent_buffer(const extent_buffer *eb, const void *ptrv,
153 			 c_ulong start, c_ulong len);
154 void read_extent_buffer(const extent_buffer *eb, void *dst,
155 			c_ulong start, c_ulong len);
156 void write_extent_buffer(extent_buffer *eb, const void *src,
157 			 c_ulong start, c_ulong len);
158 void copy_extent_buffer(extent_buffer *dst, extent_buffer *src,
159 			c_ulong dst_offset, c_ulong src_offset,
160 			c_ulong len);
161 void memmove_extent_buffer(extent_buffer *dst, c_ulong dst_offset,
162 			   c_ulong src_offset, c_ulong len);
163 void memset_extent_buffer(extent_buffer *eb, char c,
164 			  c_ulong start, c_ulong len);
165 int extent_buffer_test_bit(extent_buffer *eb, c_ulong start,
166 			   c_ulong nr);
167 int set_extent_buffer_dirty(extent_buffer *eb);
168 int clear_extent_buffer_dirty(extent_buffer *eb);
169 int read_data_from_disk(btrfs_fs_info *info, void *buf, u64 offset,
170 			u64 bytes, int mirror);
171 int write_data_to_disk(btrfs_fs_info *info, void *buf, u64 offset,
172 		       u64 bytes, int mirror);
173 void extent_buffer_bitmap_clear(extent_buffer *eb, c_ulong start,
174                                 c_ulong pos, c_ulong len);
175 void extent_buffer_bitmap_set(extent_buffer *eb, c_ulong start,
176                               c_ulong pos, c_ulong len);