@@ -662,11 +662,11 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode,
662
662
* does the checks required to make sure the data is small enough
663
663
* to fit as an inline extent.
664
664
*/
665
- static noinline int cow_file_range_inline (struct btrfs_inode * inode , u64 offset ,
666
- u64 size , size_t compressed_size ,
667
- int compress_type ,
668
- struct folio * compressed_folio ,
669
- bool update_i_size )
665
+ static noinline int __cow_file_range_inline (struct btrfs_inode * inode , u64 offset ,
666
+ u64 size , size_t compressed_size ,
667
+ int compress_type ,
668
+ struct folio * compressed_folio ,
669
+ bool update_i_size )
670
670
{
671
671
struct btrfs_drop_extents_args drop_args = { 0 };
672
672
struct btrfs_root * root = inode -> root ;
@@ -737,6 +737,33 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
737
737
return ret ;
738
738
}
739
739
740
+ static noinline int cow_file_range_inline (struct btrfs_inode * inode , u64 offset ,
741
+ u64 end ,
742
+ size_t compressed_size ,
743
+ int compress_type ,
744
+ struct folio * compressed_folio ,
745
+ bool update_i_size , bool locked )
746
+ {
747
+ unsigned long clear_flags = EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
748
+ EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING ;
749
+ u64 size = min_t (u64 , i_size_read (& inode -> vfs_inode ), end + 1 );
750
+ int ret ;
751
+
752
+ ret = __cow_file_range_inline (inode , offset , size , compressed_size ,
753
+ compress_type , compressed_folio ,
754
+ update_i_size );
755
+ if (ret > 0 )
756
+ return ret ;
757
+
758
+ if (locked )
759
+ clear_flags |= EXTENT_LOCKED ;
760
+
761
+ extent_clear_unlock_delalloc (inode , offset , end , NULL , clear_flags ,
762
+ PAGE_UNLOCK | PAGE_START_WRITEBACK |
763
+ PAGE_END_WRITEBACK );
764
+ return ret ;
765
+ }
766
+
740
767
struct async_extent {
741
768
u64 start ;
742
769
u64 ram_size ;
@@ -1005,36 +1032,15 @@ static void compress_file_range(struct btrfs_work *work)
1005
1032
* extent for the subpage case.
1006
1033
*/
1007
1034
if (total_in < actual_end )
1008
- ret = cow_file_range_inline (inode , start , actual_end , 0 ,
1009
- BTRFS_COMPRESS_NONE , NULL , false);
1035
+ ret = cow_file_range_inline (inode , start , end , 0 ,
1036
+ BTRFS_COMPRESS_NONE , NULL , false,
1037
+ false);
1010
1038
else
1011
- ret = cow_file_range_inline (inode , start , actual_end ,
1012
- total_compressed , compress_type ,
1013
- folios [0 ], false);
1039
+ ret = cow_file_range_inline (inode , start , end , total_compressed ,
1040
+ compress_type , folios [0 ], false, false);
1014
1041
if (ret <= 0 ) {
1015
- unsigned long clear_flags = EXTENT_DELALLOC |
1016
- EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
1017
- EXTENT_DO_ACCOUNTING ;
1018
-
1019
1042
if (ret < 0 )
1020
1043
mapping_set_error (mapping , - EIO );
1021
-
1022
- /*
1023
- * inline extent creation worked or returned error,
1024
- * we don't need to create any more async work items.
1025
- * Unlock and free up our temp pages.
1026
- *
1027
- * We use DO_ACCOUNTING here because we need the
1028
- * delalloc_release_metadata to be done _after_ we drop
1029
- * our outstanding extent for clearing delalloc for this
1030
- * range.
1031
- */
1032
- extent_clear_unlock_delalloc (inode , start , end ,
1033
- NULL ,
1034
- clear_flags ,
1035
- PAGE_UNLOCK |
1036
- PAGE_START_WRITEBACK |
1037
- PAGE_END_WRITEBACK );
1038
1044
goto free_pages ;
1039
1045
}
1040
1046
@@ -1344,29 +1350,21 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
1344
1350
inode_should_defrag (inode , start , end , num_bytes , SZ_64K );
1345
1351
1346
1352
if (!no_inline ) {
1347
- u64 actual_end = min_t (u64 , i_size_read (& inode -> vfs_inode ),
1348
- end + 1 );
1349
-
1350
1353
/* lets try to make an inline extent */
1351
- ret = cow_file_range_inline (inode , start , actual_end , 0 ,
1352
- BTRFS_COMPRESS_NONE , NULL , false);
1353
- if (ret == 0 ) {
1354
+ ret = cow_file_range_inline (inode , start , end , 0 ,
1355
+ BTRFS_COMPRESS_NONE , NULL , false,
1356
+ true);
1357
+ if (ret <= 0 ) {
1354
1358
/*
1355
- * We use DO_ACCOUNTING here because we need the
1356
- * delalloc_release_metadata to be run _after_ we drop
1357
- * our outstanding extent for clearing delalloc for this
1358
- * range.
1359
+ * We succeeded, return 1 so the caller knows we're done
1360
+ * with this page and already handled the IO.
1361
+ *
1362
+ * If there was an error then cow_file_range_inline() has
1363
+ * already done the cleanup.
1359
1364
*/
1360
- extent_clear_unlock_delalloc (inode , start , end ,
1361
- NULL ,
1362
- EXTENT_LOCKED | EXTENT_DELALLOC |
1363
- EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
1364
- EXTENT_DO_ACCOUNTING , PAGE_UNLOCK |
1365
- PAGE_START_WRITEBACK | PAGE_END_WRITEBACK );
1366
- ret = 1 ;
1365
+ if (ret == 0 )
1366
+ ret = 1 ;
1367
1367
goto done ;
1368
- } else if (ret < 0 ) {
1369
- goto out_unlock ;
1370
1368
}
1371
1369
}
1372
1370
@@ -10273,9 +10271,9 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
10273
10271
/* Try an inline extent first. */
10274
10272
if (encoded -> unencoded_len == encoded -> len &&
10275
10273
encoded -> unencoded_offset == 0 ) {
10276
- ret = cow_file_range_inline (inode , start , encoded -> len ,
10277
- orig_count , compression , folios [0 ],
10278
- true);
10274
+ ret = __cow_file_range_inline (inode , start , encoded -> len ,
10275
+ orig_count , compression , folios [0 ],
10276
+ true);
10279
10277
if (ret <= 0 ) {
10280
10278
if (ret == 0 )
10281
10279
ret = orig_count ;
0 commit comments