@@ -1262,10 +1262,18 @@ static int bch2_tmpfile(struct mnt_idmap *idmap,
12621262 return finish_open_simple (file , 0 );
12631263}
12641264
1265+ struct bch_fiemap_extent {
1266+ struct bkey_buf kbuf ;
1267+ unsigned flags ;
1268+ };
1269+
12651270static int bch2_fill_extent (struct bch_fs * c ,
12661271 struct fiemap_extent_info * info ,
1267- struct bkey_s_c k , unsigned flags )
1272+ struct bch_fiemap_extent * fe )
12681273{
1274+ struct bkey_s_c k = bkey_i_to_s_c (fe -> kbuf .k );
1275+ unsigned flags = fe -> flags ;
1276+
12691277 if (bkey_extent_is_direct_data (k .k )) {
12701278 struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c (k );
12711279 const union bch_extent_entry * entry ;
@@ -1318,6 +1326,36 @@ static int bch2_fill_extent(struct bch_fs *c,
13181326 }
13191327}
13201328
1329+ static int bch2_fiemap_extent (struct btree_trans * trans ,
1330+ struct btree_iter * iter , struct bkey_s_c k ,
1331+ struct bch_fiemap_extent * cur )
1332+ {
1333+ s64 offset_into_extent = iter -> pos .offset - bkey_start_offset (k .k );
1334+ unsigned sectors = k .k -> size - offset_into_extent ;
1335+
1336+ bch2_bkey_buf_reassemble (& cur -> kbuf , trans -> c , k );
1337+
1338+ enum btree_id data_btree = BTREE_ID_extents ;
1339+ int ret = bch2_read_indirect_extent (trans , & data_btree , & offset_into_extent ,
1340+ & cur -> kbuf );
1341+ if (ret )
1342+ return ret ;
1343+
1344+ k = bkey_i_to_s_c (cur -> kbuf .k );
1345+ sectors = min_t (unsigned , sectors , k .k -> size - offset_into_extent );
1346+
1347+ bch2_cut_front (POS (k .k -> p .inode ,
1348+ bkey_start_offset (k .k ) + offset_into_extent ),
1349+ cur -> kbuf .k );
1350+ bch2_key_resize (& cur -> kbuf .k -> k , sectors );
1351+ cur -> kbuf .k -> k .p = iter -> pos ;
1352+ cur -> kbuf .k -> k .p .offset += cur -> kbuf .k -> k .size ;
1353+
1354+ cur -> flags = 0 ;
1355+
1356+ return 0 ;
1357+ }
1358+
13211359static int bch2_fiemap (struct inode * vinode , struct fiemap_extent_info * info ,
13221360 u64 start , u64 len )
13231361{
@@ -1326,7 +1364,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
13261364 struct btree_trans * trans ;
13271365 struct btree_iter iter ;
13281366 struct bkey_s_c k ;
1329- struct bkey_buf cur , prev ;
1367+ struct bch_fiemap_extent cur , prev ;
13301368 bool have_extent = false;
13311369 int ret = 0 ;
13321370
@@ -1340,15 +1378,14 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
13401378
13411379 start >>= 9 ;
13421380
1343- bch2_bkey_buf_init (& cur );
1344- bch2_bkey_buf_init (& prev );
1381+ bch2_bkey_buf_init (& cur . kbuf );
1382+ bch2_bkey_buf_init (& prev . kbuf );
13451383 trans = bch2_trans_get (c );
13461384
13471385 bch2_trans_iter_init (trans , & iter , BTREE_ID_extents ,
13481386 POS (ei -> v .i_ino , start ), 0 );
13491387
13501388 while (!ret || bch2_err_matches (ret , BCH_ERR_transaction_restart )) {
1351- enum btree_id data_btree = BTREE_ID_extents ;
13521389
13531390 bch2_trans_begin (trans );
13541391
@@ -1373,39 +1410,21 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
13731410 continue ;
13741411 }
13751412
1376- s64 offset_into_extent = iter .pos .offset - bkey_start_offset (k .k );
1377- unsigned sectors = k .k -> size - offset_into_extent ;
1378-
1379- bch2_bkey_buf_reassemble (& cur , c , k );
1380-
1381- ret = bch2_read_indirect_extent (trans , & data_btree ,
1382- & offset_into_extent , & cur );
1413+ ret = bch2_fiemap_extent (trans , & iter , k , & cur );
13831414 if (ret )
1384- continue ;
1385-
1386- k = bkey_i_to_s_c (cur .k );
1387- bch2_bkey_buf_realloc (& prev , c , k .k -> u64s );
1388-
1389- sectors = min_t (unsigned , sectors , k .k -> size - offset_into_extent );
1390- start = iter .pos .offset + sectors ;
1391-
1392- bch2_cut_front (POS (k .k -> p .inode ,
1393- bkey_start_offset (k .k ) +
1394- offset_into_extent ),
1395- cur .k );
1396- bch2_key_resize (& cur .k -> k , sectors );
1397- cur .k -> k .p = iter .pos ;
1398- cur .k -> k .p .offset += cur .k -> k .size ;
1415+ break ;
1416+ bch2_bkey_buf_realloc (& prev .kbuf , c , cur .kbuf .k -> k .u64s );
1417+ start = cur .kbuf .k -> k .p .offset ;
13991418
14001419 if (have_extent ) {
14011420 bch2_trans_unlock (trans );
1402- ret = bch2_fill_extent (c , info ,
1403- bkey_i_to_s_c (prev .k ), 0 );
1421+ ret = bch2_fill_extent (c , info , & prev );
14041422 if (ret )
14051423 break ;
14061424 }
14071425
1408- bkey_copy (prev .k , cur .k );
1426+ bkey_copy (prev .kbuf .k , cur .kbuf .k );
1427+ prev .flags = cur .flags ;
14091428 have_extent = true;
14101429
14111430 bch2_btree_iter_set_pos (trans , & iter , POS (iter .pos .inode , start ));
@@ -1414,13 +1433,13 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
14141433
14151434 if (!ret && have_extent ) {
14161435 bch2_trans_unlock (trans );
1417- ret = bch2_fill_extent ( c , info , bkey_i_to_s_c ( prev . k ),
1418- FIEMAP_EXTENT_LAST );
1436+ prev . flags |= FIEMAP_EXTENT_LAST ;
1437+ ret = bch2_fill_extent ( c , info , & prev );
14191438 }
14201439
14211440 bch2_trans_put (trans );
1422- bch2_bkey_buf_exit (& cur , c );
1423- bch2_bkey_buf_exit (& prev , c );
1441+ bch2_bkey_buf_exit (& cur . kbuf , c );
1442+ bch2_bkey_buf_exit (& prev . kbuf , c );
14241443 return ret < 0 ? ret : 0 ;
14251444}
14261445
0 commit comments