@@ -662,11 +662,11 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode,
662662 * does the checks required to make sure the data is small enough
663663 * to fit as an inline extent.
664664 */
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 )
670670{
671671 struct btrfs_drop_extents_args drop_args = { 0 };
672672 struct btrfs_root * root = inode -> root ;
@@ -737,6 +737,33 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
737737 return ret ;
738738}
739739
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+
740767struct async_extent {
741768 u64 start ;
742769 u64 ram_size ;
@@ -1005,36 +1032,15 @@ static void compress_file_range(struct btrfs_work *work)
10051032 * extent for the subpage case.
10061033 */
10071034 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);
10101038 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);
10141041 if (ret <= 0 ) {
1015- unsigned long clear_flags = EXTENT_DELALLOC |
1016- EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
1017- EXTENT_DO_ACCOUNTING ;
1018-
10191042 if (ret < 0 )
10201043 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 );
10381044 goto free_pages ;
10391045 }
10401046
@@ -1344,29 +1350,21 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
13441350 inode_should_defrag (inode , start , end , num_bytes , SZ_64K );
13451351
13461352 if (!no_inline ) {
1347- u64 actual_end = min_t (u64 , i_size_read (& inode -> vfs_inode ),
1348- end + 1 );
1349-
13501353 /* 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 ) {
13541358 /*
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.
13591364 */
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 ;
13671367 goto done ;
1368- } else if (ret < 0 ) {
1369- goto out_unlock ;
13701368 }
13711369 }
13721370
@@ -10273,9 +10271,9 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
1027310271 /* Try an inline extent first. */
1027410272 if (encoded -> unencoded_len == encoded -> len &&
1027510273 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);
1027910277 if (ret <= 0 ) {
1028010278 if (ret == 0 )
1028110279 ret = orig_count ;
0 commit comments