Skip to content

Commit a229cf6

Browse files
committed
Merge tag 'for-6.6-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more followup fixes to the directory listing. People have noticed different behaviour compared to other filesystems after changes in 6.5. This is now unified to more "logical" and expected behaviour while still within POSIX. And a few more fixes for stable. - change behaviour of readdir()/rewinddir() when new directory entries are created after opendir(), properly tracking the last entry - fix race in readdir when multiple threads can set the last entry index for a directory Additionally: - use exclusive lock when direct io might need to drop privs and call notify_change() - don't clear uptodate bit on page after an error, this may lead to a deadlock in subpage mode - fix waiting pattern when multiple readers block on Merkle tree data, switch to folios" * tag 'for-6.6-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix race between reading a directory and adding entries to it btrfs: refresh dir last index during a rewinddir(3) call btrfs: set last dir index to the current last index when opening dir btrfs: don't clear uptodate on write errors btrfs: file_remove_privs needs an exclusive lock in direct io write btrfs: convert btrfs_read_merkle_tree_page() to use a folio
2 parents 5d2f535 + 8e7f82d commit a229cf6

File tree

4 files changed

+69
-53
lines changed

4 files changed

+69
-53
lines changed

fs/btrfs/extent_io.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,8 @@ static void end_bio_extent_writepage(struct btrfs_bio *bbio)
484484
bvec->bv_offset, bvec->bv_len);
485485

486486
btrfs_finish_ordered_extent(bbio->ordered, page, start, len, !error);
487-
if (error) {
488-
btrfs_page_clear_uptodate(fs_info, page, start, len);
487+
if (error)
489488
mapping_set_error(page->mapping, error);
490-
}
491489
btrfs_page_clear_writeback(fs_info, page, start, len);
492490
}
493491

@@ -1456,8 +1454,6 @@ static int __extent_writepage(struct page *page, struct btrfs_bio_ctrl *bio_ctrl
14561454
if (ret) {
14571455
btrfs_mark_ordered_io_finished(BTRFS_I(inode), page, page_start,
14581456
PAGE_SIZE, !ret);
1459-
btrfs_page_clear_uptodate(btrfs_sb(inode->i_sb), page,
1460-
page_start, PAGE_SIZE);
14611457
mapping_set_error(page->mapping, ret);
14621458
}
14631459
unlock_page(page);
@@ -1624,8 +1620,6 @@ static void extent_buffer_write_end_io(struct btrfs_bio *bbio)
16241620
struct page *page = bvec->bv_page;
16251621
u32 len = bvec->bv_len;
16261622

1627-
if (!uptodate)
1628-
btrfs_page_clear_uptodate(fs_info, page, start, len);
16291623
btrfs_page_clear_writeback(fs_info, page, start, len);
16301624
bio_offset += len;
16311625
}
@@ -2201,7 +2195,6 @@ void extent_write_locked_range(struct inode *inode, struct page *locked_page,
22012195
if (ret) {
22022196
btrfs_mark_ordered_io_finished(BTRFS_I(inode), page,
22032197
cur, cur_len, !ret);
2204-
btrfs_page_clear_uptodate(fs_info, page, cur, cur_len);
22052198
mapping_set_error(page->mapping, ret);
22062199
}
22072200
btrfs_page_unlock_writer(fs_info, page, cur, cur_len);

fs/btrfs/file.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,15 +1451,27 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
14511451
if (iocb->ki_flags & IOCB_NOWAIT)
14521452
ilock_flags |= BTRFS_ILOCK_TRY;
14531453

1454-
/* If the write DIO is within EOF, use a shared lock */
1455-
if (iocb->ki_pos + iov_iter_count(from) <= i_size_read(inode))
1454+
/*
1455+
* If the write DIO is within EOF, use a shared lock and also only if
1456+
* security bits will likely not be dropped by file_remove_privs() called
1457+
* from btrfs_write_check(). Either will need to be rechecked after the
1458+
* lock was acquired.
1459+
*/
1460+
if (iocb->ki_pos + iov_iter_count(from) <= i_size_read(inode) && IS_NOSEC(inode))
14561461
ilock_flags |= BTRFS_ILOCK_SHARED;
14571462

14581463
relock:
14591464
err = btrfs_inode_lock(BTRFS_I(inode), ilock_flags);
14601465
if (err < 0)
14611466
return err;
14621467

1468+
/* Shared lock cannot be used with security bits set. */
1469+
if ((ilock_flags & BTRFS_ILOCK_SHARED) && !IS_NOSEC(inode)) {
1470+
btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);
1471+
ilock_flags &= ~BTRFS_ILOCK_SHARED;
1472+
goto relock;
1473+
}
1474+
14631475
err = generic_write_checks(iocb, from);
14641476
if (err <= 0) {
14651477
btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);

fs/btrfs/inode.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,9 +1085,6 @@ static void submit_uncompressed_range(struct btrfs_inode *inode,
10851085
btrfs_mark_ordered_io_finished(inode, locked_page,
10861086
page_start, PAGE_SIZE,
10871087
!ret);
1088-
btrfs_page_clear_uptodate(inode->root->fs_info,
1089-
locked_page, page_start,
1090-
PAGE_SIZE);
10911088
mapping_set_error(locked_page->mapping, ret);
10921089
unlock_page(locked_page);
10931090
}
@@ -2791,7 +2788,6 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
27912788
mapping_set_error(page->mapping, ret);
27922789
btrfs_mark_ordered_io_finished(inode, page, page_start,
27932790
PAGE_SIZE, !ret);
2794-
btrfs_page_clear_uptodate(fs_info, page, page_start, PAGE_SIZE);
27952791
clear_page_dirty_for_io(page);
27962792
}
27972793
btrfs_page_clear_checked(fs_info, page, page_start, PAGE_SIZE);
@@ -5769,20 +5765,24 @@ static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
57695765

57705766
static int btrfs_get_dir_last_index(struct btrfs_inode *dir, u64 *index)
57715767
{
5772-
if (dir->index_cnt == (u64)-1) {
5773-
int ret;
5768+
int ret = 0;
57745769

5770+
btrfs_inode_lock(dir, 0);
5771+
if (dir->index_cnt == (u64)-1) {
57755772
ret = btrfs_inode_delayed_dir_index_count(dir);
57765773
if (ret) {
57775774
ret = btrfs_set_inode_index_count(dir);
57785775
if (ret)
5779-
return ret;
5776+
goto out;
57805777
}
57815778
}
57825779

5783-
*index = dir->index_cnt;
5780+
/* index_cnt is the index number of next new entry, so decrement it. */
5781+
*index = dir->index_cnt - 1;
5782+
out:
5783+
btrfs_inode_unlock(dir, 0);
57845784

5785-
return 0;
5785+
return ret;
57865786
}
57875787

57885788
/*
@@ -5817,6 +5817,19 @@ static int btrfs_opendir(struct inode *inode, struct file *file)
58175817
return 0;
58185818
}
58195819

5820+
static loff_t btrfs_dir_llseek(struct file *file, loff_t offset, int whence)
5821+
{
5822+
struct btrfs_file_private *private = file->private_data;
5823+
int ret;
5824+
5825+
ret = btrfs_get_dir_last_index(BTRFS_I(file_inode(file)),
5826+
&private->last_index);
5827+
if (ret)
5828+
return ret;
5829+
5830+
return generic_file_llseek(file, offset, whence);
5831+
}
5832+
58205833
struct dir_entry {
58215834
u64 ino;
58225835
u64 offset;
@@ -10868,7 +10881,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
1086810881
};
1086910882

1087010883
static const struct file_operations btrfs_dir_file_operations = {
10871-
.llseek = generic_file_llseek,
10884+
.llseek = btrfs_dir_llseek,
1087210885
.read = generic_read_dir,
1087310886
.iterate_shared = btrfs_real_readdir,
1087410887
.open = btrfs_opendir,

fs/btrfs/verity.c

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode,
715715
pgoff_t index,
716716
unsigned long num_ra_pages)
717717
{
718-
struct page *page;
718+
struct folio *folio;
719719
u64 off = (u64)index << PAGE_SHIFT;
720720
loff_t merkle_pos = merkle_file_pos(inode);
721721
int ret;
@@ -726,58 +726,56 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode,
726726
return ERR_PTR(-EFBIG);
727727
index += merkle_pos >> PAGE_SHIFT;
728728
again:
729-
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
730-
if (page) {
731-
if (PageUptodate(page))
732-
return page;
729+
folio = __filemap_get_folio(inode->i_mapping, index, FGP_ACCESSED, 0);
730+
if (!IS_ERR(folio)) {
731+
if (folio_test_uptodate(folio))
732+
goto out;
733733

734-
lock_page(page);
735-
/*
736-
* We only insert uptodate pages, so !Uptodate has to be
737-
* an error
738-
*/
739-
if (!PageUptodate(page)) {
740-
unlock_page(page);
741-
put_page(page);
734+
folio_lock(folio);
735+
/* If it's not uptodate after we have the lock, we got a read error. */
736+
if (!folio_test_uptodate(folio)) {
737+
folio_unlock(folio);
738+
folio_put(folio);
742739
return ERR_PTR(-EIO);
743740
}
744-
unlock_page(page);
745-
return page;
741+
folio_unlock(folio);
742+
goto out;
746743
}
747744

748-
page = __page_cache_alloc(mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS));
749-
if (!page)
745+
folio = filemap_alloc_folio(mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS),
746+
0);
747+
if (!folio)
750748
return ERR_PTR(-ENOMEM);
751749

750+
ret = filemap_add_folio(inode->i_mapping, folio, index, GFP_NOFS);
751+
if (ret) {
752+
folio_put(folio);
753+
/* Did someone else insert a folio here? */
754+
if (ret == -EEXIST)
755+
goto again;
756+
return ERR_PTR(ret);
757+
}
758+
752759
/*
753760
* Merkle item keys are indexed from byte 0 in the merkle tree.
754761
* They have the form:
755762
*
756763
* [ inode objectid, BTRFS_MERKLE_ITEM_KEY, offset in bytes ]
757764
*/
758765
ret = read_key_bytes(BTRFS_I(inode), BTRFS_VERITY_MERKLE_ITEM_KEY, off,
759-
page_address(page), PAGE_SIZE, page);
766+
folio_address(folio), PAGE_SIZE, &folio->page);
760767
if (ret < 0) {
761-
put_page(page);
768+
folio_put(folio);
762769
return ERR_PTR(ret);
763770
}
764771
if (ret < PAGE_SIZE)
765-
memzero_page(page, ret, PAGE_SIZE - ret);
772+
folio_zero_segment(folio, ret, PAGE_SIZE);
766773

767-
SetPageUptodate(page);
768-
ret = add_to_page_cache_lru(page, inode->i_mapping, index, GFP_NOFS);
774+
folio_mark_uptodate(folio);
775+
folio_unlock(folio);
769776

770-
if (!ret) {
771-
/* Inserted and ready for fsverity */
772-
unlock_page(page);
773-
} else {
774-
put_page(page);
775-
/* Did someone race us into inserting this page? */
776-
if (ret == -EEXIST)
777-
goto again;
778-
page = ERR_PTR(ret);
779-
}
780-
return page;
777+
out:
778+
return folio_file_page(folio, index);
781779
}
782780

783781
/*

0 commit comments

Comments
 (0)