@@ -614,14 +614,56 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
614614 return ret ;
615615}
616616
617+ static bool can_cow_file_range_inline (struct btrfs_inode * inode ,
618+ u64 offset , u64 size ,
619+ size_t compressed_size )
620+ {
621+ struct btrfs_fs_info * fs_info = inode -> root -> fs_info ;
622+ u64 data_len = (compressed_size ?: size );
623+
624+ /* Inline extents must start at offset 0. */
625+ if (offset != 0 )
626+ return false;
627+
628+ /*
629+ * Due to the page size limit, for subpage we can only trigger the
630+ * writeback for the dirty sectors of page, that means data writeback
631+ * is doing more writeback than what we want.
632+ *
633+ * This is especially unexpected for some call sites like fallocate,
634+ * where we only increase i_size after everything is done.
635+ * This means we can trigger inline extent even if we didn't want to.
636+ * So here we skip inline extent creation completely.
637+ */
638+ if (fs_info -> sectorsize != PAGE_SIZE )
639+ return false;
640+
641+ /* Inline extents are limited to sectorsize. */
642+ if (size > fs_info -> sectorsize )
643+ return false;
644+
645+ /* We cannot exceed the maximum inline data size. */
646+ if (data_len > BTRFS_MAX_INLINE_DATA_SIZE (fs_info ))
647+ return false;
648+
649+ /* We cannot exceed the user specified max_inline size. */
650+ if (data_len > fs_info -> max_inline )
651+ return false;
652+
653+ /* Inline extents must be the entirety of the file. */
654+ if (size < i_size_read (& inode -> vfs_inode ))
655+ return false;
656+
657+ return true;
658+ }
617659
618660/*
619661 * conditionally insert an inline extent into the file. This
620662 * does the checks required to make sure the data is small enough
621663 * to fit as an inline extent.
622664 */
623- static noinline int cow_file_range_inline (struct btrfs_inode * inode , u64 size ,
624- size_t compressed_size ,
665+ static noinline int cow_file_range_inline (struct btrfs_inode * inode , u64 offset ,
666+ u64 size , size_t compressed_size ,
625667 int compress_type ,
626668 struct folio * compressed_folio ,
627669 bool update_i_size )
@@ -634,16 +676,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,
634676 int ret ;
635677 struct btrfs_path * path ;
636678
637- /*
638- * We can create an inline extent if it ends at or beyond the current
639- * i_size, is no larger than a sector (decompressed), and the (possibly
640- * compressed) data fits in a leaf and the configured maximum inline
641- * size.
642- */
643- if (size < i_size_read (& inode -> vfs_inode ) ||
644- size > fs_info -> sectorsize ||
645- data_len > BTRFS_MAX_INLINE_DATA_SIZE (fs_info ) ||
646- data_len > fs_info -> max_inline )
679+ if (!can_cow_file_range_inline (inode , offset , size , compressed_size ))
647680 return 1 ;
648681
649682 path = btrfs_alloc_path ();
@@ -971,43 +1004,38 @@ static void compress_file_range(struct btrfs_work *work)
9711004 * Check cow_file_range() for why we don't even try to create inline
9721005 * extent for the subpage case.
9731006 */
974- if (start == 0 && fs_info -> sectorsize == PAGE_SIZE ) {
975- if (total_in < actual_end ) {
976- ret = cow_file_range_inline (inode , actual_end , 0 ,
977- BTRFS_COMPRESS_NONE , NULL ,
978- false);
979- } else {
980- ret = cow_file_range_inline (inode , actual_end ,
981- total_compressed ,
982- compress_type , folios [0 ],
983- false);
984- }
985- if (ret <= 0 ) {
986- unsigned long clear_flags = EXTENT_DELALLOC |
987- EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
988- EXTENT_DO_ACCOUNTING ;
1007+ if (total_in < actual_end )
1008+ ret = cow_file_range_inline (inode , start , actual_end , 0 ,
1009+ BTRFS_COMPRESS_NONE , NULL , false);
1010+ else
1011+ ret = cow_file_range_inline (inode , start , actual_end ,
1012+ total_compressed , compress_type ,
1013+ folios [0 ], false);
1014+ if (ret <= 0 ) {
1015+ unsigned long clear_flags = EXTENT_DELALLOC |
1016+ EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
1017+ EXTENT_DO_ACCOUNTING ;
9891018
990- if (ret < 0 )
991- mapping_set_error (mapping , - EIO );
1019+ if (ret < 0 )
1020+ mapping_set_error (mapping , - EIO );
9921021
993- /*
994- * inline extent creation worked or returned error,
995- * we don't need to create any more async work items.
996- * Unlock and free up our temp pages.
997- *
998- * We use DO_ACCOUNTING here because we need the
999- * delalloc_release_metadata to be done _after_ we drop
1000- * our outstanding extent for clearing delalloc for this
1001- * range.
1002- */
1003- extent_clear_unlock_delalloc (inode , start , end ,
1004- NULL ,
1005- clear_flags ,
1006- PAGE_UNLOCK |
1007- PAGE_START_WRITEBACK |
1008- PAGE_END_WRITEBACK );
1009- goto free_pages ;
1010- }
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+ goto free_pages ;
10111039 }
10121040
10131041 /*
@@ -1315,22 +1343,12 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
13151343
13161344 inode_should_defrag (inode , start , end , num_bytes , SZ_64K );
13171345
1318- /*
1319- * Due to the page size limit, for subpage we can only trigger the
1320- * writeback for the dirty sectors of page, that means data writeback
1321- * is doing more writeback than what we want.
1322- *
1323- * This is especially unexpected for some call sites like fallocate,
1324- * where we only increase i_size after everything is done.
1325- * This means we can trigger inline extent even if we didn't want to.
1326- * So here we skip inline extent creation completely.
1327- */
1328- if (start == 0 && fs_info -> sectorsize == PAGE_SIZE && !no_inline ) {
1346+ if (!no_inline ) {
13291347 u64 actual_end = min_t (u64 , i_size_read (& inode -> vfs_inode ),
13301348 end + 1 );
13311349
13321350 /* lets try to make an inline extent */
1333- ret = cow_file_range_inline (inode , actual_end , 0 ,
1351+ ret = cow_file_range_inline (inode , start , actual_end , 0 ,
13341352 BTRFS_COMPRESS_NONE , NULL , false);
13351353 if (ret == 0 ) {
13361354 /*
@@ -10266,10 +10284,11 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
1026610284 goto out_qgroup_free_data ;
1026710285
1026810286 /* Try an inline extent first. */
10269- if (start == 0 && encoded -> unencoded_len == encoded -> len &&
10287+ if (encoded -> unencoded_len == encoded -> len &&
1027010288 encoded -> unencoded_offset == 0 ) {
10271- ret = cow_file_range_inline (inode , encoded -> len , orig_count ,
10272- compression , folios [0 ], true);
10289+ ret = cow_file_range_inline (inode , start , encoded -> len ,
10290+ orig_count , compression , folios [0 ],
10291+ true);
1027310292 if (ret <= 0 ) {
1027410293 if (ret == 0 )
1027510294 ret = orig_count ;
0 commit comments