@@ -31,6 +31,188 @@ static struct btrfs_device *btrfs_device_by_devid(struct btrfs_fs_devices *fs_de
3131 return NULL ;
3232}
3333
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+
34216/* Test punching a hole into a single RAID stripe-extent. */
35217static int test_punch_hole (struct btrfs_trans_handle * trans )
36218{
@@ -752,6 +934,7 @@ static const test_func_t tests[] = {
752934 test_front_delete ,
753935 test_front_delete_prev_item ,
754936 test_punch_hole ,
937+ test_punch_hole_3extents ,
755938};
756939
757940static int run_test (test_func_t test , u32 sectorsize , u32 nodesize )
0 commit comments