@@ -31,6 +31,188 @@ static struct btrfs_device *btrfs_device_by_devid(struct btrfs_fs_devices *fs_de
31
31
return NULL ;
32
32
}
33
33
34
+ /*
35
+ * Test creating a range of three extents and then punch a hole in the middle,
36
+ * deleting all of the middle extents and partially deleting the "book ends".
37
+ */
38
+ static int test_punch_hole_3extents (struct btrfs_trans_handle * trans )
39
+ {
40
+ struct btrfs_fs_info * fs_info = trans -> fs_info ;
41
+ struct btrfs_io_context * bioc ;
42
+ struct btrfs_io_stripe io_stripe = { 0 };
43
+ u64 map_type = RST_TEST_RAID1_TYPE ;
44
+ u64 logical1 = SZ_1M ;
45
+ u64 len1 = SZ_1M ;
46
+ u64 logical2 = logical1 + len1 ;
47
+ u64 len2 = SZ_1M ;
48
+ u64 logical3 = logical2 + len2 ;
49
+ u64 len3 = SZ_1M ;
50
+ u64 hole_start = logical1 + SZ_256K ;
51
+ u64 hole_len = SZ_2M ;
52
+ int ret ;
53
+
54
+ bioc = alloc_btrfs_io_context (fs_info , logical1 , RST_TEST_NUM_DEVICES );
55
+ if (!bioc ) {
56
+ test_std_err (TEST_ALLOC_IO_CONTEXT );
57
+ ret = - ENOMEM ;
58
+ goto out ;
59
+ }
60
+
61
+ io_stripe .dev = btrfs_device_by_devid (fs_info -> fs_devices , 0 );
62
+
63
+ /* Prepare for the test, 1st create 3 x 1M extents. */
64
+ bioc -> map_type = map_type ;
65
+ bioc -> size = len1 ;
66
+
67
+ for (int i = 0 ; i < RST_TEST_NUM_DEVICES ; i ++ ) {
68
+ struct btrfs_io_stripe * stripe = & bioc -> stripes [i ];
69
+
70
+ stripe -> dev = btrfs_device_by_devid (fs_info -> fs_devices , i );
71
+ if (!stripe -> dev ) {
72
+ test_err ("cannot find device with devid %d" , i );
73
+ ret = - EINVAL ;
74
+ goto out ;
75
+ }
76
+
77
+ stripe -> physical = logical1 + i * SZ_1G ;
78
+ }
79
+
80
+ ret = btrfs_insert_one_raid_extent (trans , bioc );
81
+ if (ret ) {
82
+ test_err ("inserting RAID extent failed: %d" , ret );
83
+ goto out ;
84
+ }
85
+
86
+ bioc -> logical = logical2 ;
87
+ bioc -> size = len2 ;
88
+ for (int i = 0 ; i < RST_TEST_NUM_DEVICES ; i ++ ) {
89
+ struct btrfs_io_stripe * stripe = & bioc -> stripes [i ];
90
+
91
+ stripe -> dev = btrfs_device_by_devid (fs_info -> fs_devices , i );
92
+ if (!stripe -> dev ) {
93
+ test_err ("cannot find device with devid %d" , i );
94
+ ret = - EINVAL ;
95
+ goto out ;
96
+ }
97
+
98
+ stripe -> physical = logical2 + i * SZ_1G ;
99
+ }
100
+
101
+ ret = btrfs_insert_one_raid_extent (trans , bioc );
102
+ if (ret ) {
103
+ test_err ("inserting RAID extent failed: %d" , ret );
104
+ goto out ;
105
+ }
106
+
107
+ bioc -> logical = logical3 ;
108
+ bioc -> size = len3 ;
109
+ for (int i = 0 ; i < RST_TEST_NUM_DEVICES ; i ++ ) {
110
+ struct btrfs_io_stripe * stripe = & bioc -> stripes [i ];
111
+
112
+ stripe -> dev = btrfs_device_by_devid (fs_info -> fs_devices , i );
113
+ if (!stripe -> dev ) {
114
+ test_err ("cannot find device with devid %d" , i );
115
+ ret = - EINVAL ;
116
+ goto out ;
117
+ }
118
+
119
+ stripe -> physical = logical3 + i * SZ_1G ;
120
+ }
121
+
122
+ ret = btrfs_insert_one_raid_extent (trans , bioc );
123
+ if (ret ) {
124
+ test_err ("inserting RAID extent failed: %d" , ret );
125
+ goto out ;
126
+ }
127
+
128
+ /*
129
+ * Delete a range starting at logical1 + 256K and 2M in length. Extent
130
+ * 1 is truncated to 256k length, extent 2 is completely dropped and
131
+ * extent 3 is moved 256K to the right.
132
+ */
133
+ ret = btrfs_delete_raid_extent (trans , hole_start , hole_len );
134
+ if (ret ) {
135
+ test_err ("deleting RAID extent [%llu, %llu] failed" ,
136
+ hole_start , hole_start + hole_len );
137
+ goto out ;
138
+ }
139
+
140
+ /* Get the first extent and check its size. */
141
+ ret = btrfs_get_raid_extent_offset (fs_info , logical1 , & len1 , map_type ,
142
+ 0 , & io_stripe );
143
+ if (ret ) {
144
+ test_err ("lookup of RAID extent [%llu, %llu] failed" ,
145
+ logical1 , logical1 + len1 );
146
+ goto out ;
147
+ }
148
+
149
+ if (io_stripe .physical != logical1 ) {
150
+ test_err ("invalid physical address, expected %llu, got %llu" ,
151
+ logical1 , io_stripe .physical );
152
+ ret = - EINVAL ;
153
+ goto out ;
154
+ }
155
+
156
+ if (len1 != SZ_256K ) {
157
+ test_err ("invalid stripe length, expected %llu, got %llu" ,
158
+ (u64 )SZ_256K , len1 );
159
+ ret = - EINVAL ;
160
+ goto out ;
161
+ }
162
+
163
+ /* Get the second extent and check it's absent. */
164
+ ret = btrfs_get_raid_extent_offset (fs_info , logical2 , & len2 , map_type ,
165
+ 0 , & io_stripe );
166
+ if (ret != - ENODATA ) {
167
+ test_err ("lookup of RAID extent [%llu, %llu] succeeded should fail" ,
168
+ logical2 , logical2 + len2 );
169
+ ret = - EINVAL ;
170
+ goto out ;
171
+ }
172
+
173
+ /* Get the third extent and check its size. */
174
+ logical3 += SZ_256K ;
175
+ ret = btrfs_get_raid_extent_offset (fs_info , logical3 , & len3 , map_type ,
176
+ 0 , & io_stripe );
177
+ if (ret ) {
178
+ test_err ("lookup of RAID extent [%llu, %llu] failed" ,
179
+ logical3 , logical3 + len3 );
180
+ goto out ;
181
+ }
182
+
183
+ if (io_stripe .physical != logical3 ) {
184
+ test_err ("invalid physical address, expected %llu, got %llu" ,
185
+ logical3 + SZ_256K , io_stripe .physical );
186
+ ret = - EINVAL ;
187
+ goto out ;
188
+ }
189
+
190
+ if (len3 != SZ_1M - SZ_256K ) {
191
+ test_err ("invalid stripe length, expected %llu, got %llu" ,
192
+ (u64 )SZ_1M - SZ_256K , len3 );
193
+ ret = - EINVAL ;
194
+ goto out ;
195
+ }
196
+
197
+ ret = btrfs_delete_raid_extent (trans , logical1 , len1 );
198
+ if (ret ) {
199
+ test_err ("deleting RAID extent [%llu, %llu] failed" ,
200
+ logical1 , logical1 + len1 );
201
+ goto out ;
202
+ }
203
+
204
+ ret = btrfs_delete_raid_extent (trans , logical3 , len3 );
205
+ if (ret ) {
206
+ test_err ("deleting RAID extent [%llu, %llu] failed" ,
207
+ logical1 , logical1 + len1 );
208
+ goto out ;
209
+ }
210
+
211
+ out :
212
+ btrfs_put_bioc (bioc );
213
+ return ret ;
214
+ }
215
+
34
216
/* Test punching a hole into a single RAID stripe-extent. */
35
217
static int test_punch_hole (struct btrfs_trans_handle * trans )
36
218
{
@@ -752,6 +934,7 @@ static const test_func_t tests[] = {
752
934
test_front_delete ,
753
935
test_front_delete_prev_item ,
754
936
test_punch_hole ,
937
+ test_punch_hole_3extents ,
755
938
};
756
939
757
940
static int run_test (test_func_t test , u32 sectorsize , u32 nodesize )
0 commit comments