mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
btrfs: open-code btrfs_copy_from_user()
The function btrfs_copy_from_user() handles the folio dirtying for
buffered write. The original design is to allow that function to handle
multiple folios, but since commit c87c299776
("btrfs: make buffered
write to copy one page a time") there is no need to support multiple
folios.
So here open-code btrfs_copy_from_user() to
copy_folio_from_iter_atomic() and flush_dcache_folio() calls.
The short-copy check and revert are still kept as-is.
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
4eca32d8d9
commit
e3d9a19756
@ -38,52 +38,6 @@
|
|||||||
#include "super.h"
|
#include "super.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper to fault in page and copy. This should go away and be replaced with
|
|
||||||
* calls into generic code.
|
|
||||||
*/
|
|
||||||
static noinline int btrfs_copy_from_user(loff_t pos, size_t write_bytes,
|
|
||||||
struct folio *folio, struct iov_iter *i)
|
|
||||||
{
|
|
||||||
size_t copied = 0;
|
|
||||||
size_t total_copied = 0;
|
|
||||||
int offset = offset_in_page(pos);
|
|
||||||
|
|
||||||
while (write_bytes > 0) {
|
|
||||||
size_t count = min_t(size_t, PAGE_SIZE - offset, write_bytes);
|
|
||||||
/*
|
|
||||||
* Copy data from userspace to the current page
|
|
||||||
*/
|
|
||||||
copied = copy_folio_from_iter_atomic(folio, offset, count, i);
|
|
||||||
|
|
||||||
/* Flush processor's dcache for this page */
|
|
||||||
flush_dcache_folio(folio);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if we get a partial write, we can end up with
|
|
||||||
* partially up to date page. These add
|
|
||||||
* a lot of complexity, so make sure they don't
|
|
||||||
* happen by forcing this copy to be retried.
|
|
||||||
*
|
|
||||||
* The rest of the btrfs_file_write code will fall
|
|
||||||
* back to page at a time copies after we return 0.
|
|
||||||
*/
|
|
||||||
if (unlikely(copied < count)) {
|
|
||||||
if (!folio_test_uptodate(folio)) {
|
|
||||||
iov_iter_revert(i, copied);
|
|
||||||
copied = 0;
|
|
||||||
}
|
|
||||||
if (!copied)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_bytes -= copied;
|
|
||||||
total_copied += copied;
|
|
||||||
offset += copied;
|
|
||||||
}
|
|
||||||
return total_copied;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unlock folio after btrfs_file_write() is done with it.
|
* Unlock folio after btrfs_file_write() is done with it.
|
||||||
*/
|
*/
|
||||||
@ -107,7 +61,7 @@ static void btrfs_drop_folio(struct btrfs_fs_info *fs_info, struct folio *folio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After btrfs_copy_from_user(), update the following things for delalloc:
|
* After copy_folio_from_iter_atomic(), update the following things for delalloc:
|
||||||
* - Mark newly dirtied folio as DELALLOC in the io tree.
|
* - Mark newly dirtied folio as DELALLOC in the io tree.
|
||||||
* Used to advise which range is to be written back.
|
* Used to advise which range is to be written back.
|
||||||
* - Mark modified folio as Uptodate/Dirty and not needing COW fixup
|
* - Mark modified folio as Uptodate/Dirty and not needing COW fixup
|
||||||
@ -1269,7 +1223,23 @@ ssize_t btrfs_buffered_write(struct kiocb *iocb, struct iov_iter *i)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
copied = btrfs_copy_from_user(pos, write_bytes, folio, i);
|
copied = copy_folio_from_iter_atomic(folio,
|
||||||
|
offset_in_folio(folio, pos), write_bytes, i);
|
||||||
|
flush_dcache_folio(folio);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we get a partial write, we can end up with partially
|
||||||
|
* uptodate page. Although if sector size < page size we can
|
||||||
|
* handle it, but if it's not sector aligned it can cause
|
||||||
|
* a lot of complexity, so make sure they don't happen by
|
||||||
|
* forcing retry this copy.
|
||||||
|
*/
|
||||||
|
if (unlikely(copied < write_bytes)) {
|
||||||
|
if (!folio_test_uptodate(folio)) {
|
||||||
|
iov_iter_revert(i, copied);
|
||||||
|
copied = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
num_sectors = BTRFS_BYTES_TO_BLKS(fs_info, reserve_bytes);
|
num_sectors = BTRFS_BYTES_TO_BLKS(fs_info, reserve_bytes);
|
||||||
dirty_sectors = round_up(copied + sector_offset,
|
dirty_sectors = round_up(copied + sector_offset,
|
||||||
|
Loading…
Reference in New Issue
Block a user