mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-12-11 00:00:12 +03:00
Update bcachefs sources to 6c3c2a24c61d bcachefs: Fix possible corruption on repeated mmap writes
This commit is contained in:
parent
800949c1ce
commit
858e41a71d
@ -1 +1 @@
|
||||
682cbaf658f5fde86172e02ffdac0f65650f9fa1
|
||||
6c3c2a24c61ddc23a6bbdf604b88262da0cd2d9c
|
||||
|
||||
@ -598,6 +598,7 @@ static int __bch2_writepage(struct folio *folio,
|
||||
do_io:
|
||||
f_sectors = folio_sectors(folio);
|
||||
s = bch2_folio(folio);
|
||||
BUG_ON(!s);
|
||||
|
||||
if (f_sectors > w->tmp_sectors) {
|
||||
kfree(w->tmp);
|
||||
@ -829,7 +830,7 @@ int bch2_write_end(
|
||||
struct bch_inode_info *inode = to_bch_ei(mapping->host);
|
||||
struct bch_fs *c = inode->v.i_sb->s_fs_info;
|
||||
struct bch2_folio_reservation *res = fsdata;
|
||||
unsigned offset = pos - folio_pos(folio);
|
||||
size_t offset = pos - folio_pos(folio);
|
||||
|
||||
BUG_ON(offset + copied > folio_size(folio));
|
||||
|
||||
@ -886,8 +887,9 @@ static int __bch2_buffered_write(struct bch_fs *c,
|
||||
struct bch2_folio_reservation res;
|
||||
folios fs;
|
||||
struct folio *f;
|
||||
unsigned copied = 0, f_offset, f_copied;
|
||||
u64 end = pos + len, f_pos, f_len;
|
||||
unsigned copied = 0, f_copied;
|
||||
size_t f_offset, f_len;
|
||||
u64 end = pos + len, f_pos;
|
||||
loff_t last_folio_pos = inode->v.i_size;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
@ -1498,7 +1498,7 @@ static const struct address_space_operations bch_address_space_operations = {
|
||||
.read_folio = bch2_read_folio,
|
||||
.writepages = bch2_writepages,
|
||||
.readahead = bch2_readahead,
|
||||
.dirty_folio = filemap_dirty_folio,
|
||||
.dirty_folio = bch2_vfs_dirty_folio,
|
||||
.write_begin = bch2_write_begin,
|
||||
.write_end = bch2_write_end,
|
||||
.invalidate_folio = bch2_invalidate_folio,
|
||||
|
||||
@ -361,14 +361,14 @@ int bch2_get_folio_disk_reservation(struct bch_fs *c,
|
||||
struct bch_inode_info *inode,
|
||||
struct folio *folio, bool check_enospc)
|
||||
{
|
||||
struct bch_folio *s = bch2_folio_create(folio, 0);
|
||||
struct bch_folio *s = bch2_folio(folio);
|
||||
unsigned nr_replicas = inode_nr_replicas(c, inode);
|
||||
struct disk_reservation disk_res = { 0 };
|
||||
unsigned i, sectors = folio_sectors(folio), disk_res_sectors = 0;
|
||||
int ret;
|
||||
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
BUG_ON(!s);
|
||||
EBUG_ON(!s->uptodate);
|
||||
|
||||
for (i = 0; i < sectors; i++)
|
||||
disk_res_sectors += sectors_to_reserve(&s->s[i], nr_replicas);
|
||||
@ -399,21 +399,19 @@ void bch2_folio_reservation_put(struct bch_fs *c,
|
||||
bch2_quota_reservation_put(c, inode, &res->quota);
|
||||
}
|
||||
|
||||
static int __bch2_folio_reservation_get(struct bch_fs *c,
|
||||
static ssize_t __bch2_folio_reservation_get(struct bch_fs *c,
|
||||
struct bch_inode_info *inode,
|
||||
struct folio *folio,
|
||||
struct bch2_folio_reservation *res,
|
||||
size_t offset, size_t len,
|
||||
bool partial)
|
||||
{
|
||||
struct bch_folio *s = bch2_folio_create(folio, 0);
|
||||
struct bch_folio *s = bch2_folio(folio);
|
||||
unsigned i, disk_sectors = 0, quota_sectors = 0;
|
||||
size_t reserved = len;
|
||||
int ret;
|
||||
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
BUG_ON(!s);
|
||||
BUG_ON(!s->uptodate);
|
||||
|
||||
for (i = round_down(offset, block_bytes(c)) >> 9;
|
||||
@ -462,13 +460,54 @@ static int __bch2_folio_reservation_get(struct bch_fs *c,
|
||||
return partial ? reserved : 0;
|
||||
}
|
||||
|
||||
static int bch2_folio_reservation_get_nofail(struct bch_fs *c,
|
||||
struct bch_inode_info *inode,
|
||||
struct folio *folio,
|
||||
struct bch2_folio_reservation *res,
|
||||
size_t offset, size_t len)
|
||||
{
|
||||
struct bch_folio *s = bch2_folio(folio);
|
||||
unsigned i, disk_sectors = 0, quota_sectors = 0;
|
||||
struct disk_reservation disk_res = {};
|
||||
int ret;
|
||||
|
||||
BUG_ON(!s);
|
||||
BUG_ON(!s->uptodate);
|
||||
|
||||
for (i = round_down(offset, block_bytes(c)) >> 9;
|
||||
i < round_up(offset + len, block_bytes(c)) >> 9;
|
||||
i++) {
|
||||
disk_sectors += sectors_to_reserve(&s->s[i], res->disk.nr_replicas);
|
||||
quota_sectors += s->s[i].state == SECTOR_unallocated;
|
||||
}
|
||||
|
||||
if (disk_sectors) {
|
||||
ret = bch2_disk_reservation_add(c, &disk_res, disk_sectors,
|
||||
BCH_DISK_RESERVATION_NOFAIL);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (quota_sectors) {
|
||||
/* FIXME: we'll need to make sure this won't fail with -ENOMEM */
|
||||
ret = bch2_quota_reservation_add(c, inode, &res->quota, quota_sectors, false);
|
||||
if (unlikely(ret)) {
|
||||
bch2_disk_reservation_put(c, &disk_res);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
res->disk.sectors += disk_res.sectors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bch2_folio_reservation_get(struct bch_fs *c,
|
||||
struct bch_inode_info *inode,
|
||||
struct folio *folio,
|
||||
struct bch2_folio_reservation *res,
|
||||
size_t offset, size_t len)
|
||||
{
|
||||
return __bch2_folio_reservation_get(c, inode, folio, res, offset, len, false);
|
||||
return (int)__bch2_folio_reservation_get(c, inode, folio, res, offset, len, false);
|
||||
}
|
||||
|
||||
ssize_t bch2_folio_reservation_get_partial(struct bch_fs *c,
|
||||
@ -508,11 +547,26 @@ static void bch2_clear_folio_bits(struct folio *folio)
|
||||
bch2_folio_release(folio);
|
||||
}
|
||||
|
||||
void bch2_set_folio_dirty(struct bch_fs *c,
|
||||
bool bch2_vfs_dirty_folio(struct address_space *mapping, struct folio *folio)
|
||||
{
|
||||
struct bch_inode_info *inode = to_bch_ei(mapping->host);
|
||||
struct bch_fs *c = inode->v.i_sb->s_fs_info;
|
||||
struct bch2_folio_reservation res;
|
||||
|
||||
loff_t file_size = i_size_read(&inode->v);
|
||||
size_t dirty_bytes = min_t(size_t, folio_size(folio),
|
||||
round_up(file_size, block_bytes(c)) - folio_pos(folio));
|
||||
|
||||
bch2_folio_reservation_init(c, inode, &res);
|
||||
BUG_ON(bch2_folio_reservation_get_nofail(c, inode, folio, &res, 0, dirty_bytes));
|
||||
return bch2_set_folio_dirty(c, inode, folio, &res, 0, dirty_bytes);
|
||||
}
|
||||
|
||||
bool bch2_set_folio_dirty(struct bch_fs *c,
|
||||
struct bch_inode_info *inode,
|
||||
struct folio *folio,
|
||||
struct bch2_folio_reservation *res,
|
||||
unsigned offset, unsigned len)
|
||||
size_t offset, size_t len)
|
||||
{
|
||||
struct bch_folio *s = bch2_folio(folio);
|
||||
unsigned i, dirty_sectors = 0;
|
||||
@ -520,7 +574,9 @@ void bch2_set_folio_dirty(struct bch_fs *c,
|
||||
WARN_ON((u64) folio_pos(folio) + offset + len >
|
||||
round_up((u64) i_size_read(&inode->v), block_bytes(c)));
|
||||
|
||||
BUG_ON(!s);
|
||||
BUG_ON(!s->uptodate);
|
||||
EBUG_ON(round_up(offset + len, block_bytes(c)) >> 9 > UINT_MAX);
|
||||
|
||||
scoped_guard(spinlock, &s->lock)
|
||||
for (i = round_down(offset, block_bytes(c)) >> 9;
|
||||
@ -546,7 +602,8 @@ void bch2_set_folio_dirty(struct bch_fs *c,
|
||||
bch2_i_sectors_acct(c, inode, &res->quota, dirty_sectors);
|
||||
|
||||
if (!folio_test_dirty(folio))
|
||||
filemap_dirty_folio(inode->v.i_mapping, folio);
|
||||
return filemap_dirty_folio(inode->v.i_mapping, folio);
|
||||
return false;
|
||||
}
|
||||
|
||||
vm_fault_t bch2_page_fault(struct vm_fault *vmf)
|
||||
@ -598,7 +655,7 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
|
||||
vm_fault_t ret;
|
||||
|
||||
loff_t file_offset = round_down(vmf->pgoff << PAGE_SHIFT, block_bytes(c));
|
||||
unsigned offset = file_offset - folio_pos(folio);
|
||||
size_t offset = file_offset - folio_pos(folio);
|
||||
unsigned len = max(PAGE_SIZE, block_bytes(c));
|
||||
|
||||
BUG_ON(offset + len > folio_size(folio));
|
||||
|
||||
@ -153,11 +153,12 @@ ssize_t bch2_folio_reservation_get_partial(struct bch_fs *,
|
||||
struct bch2_folio_reservation *,
|
||||
size_t, size_t);
|
||||
|
||||
void bch2_set_folio_dirty(struct bch_fs *,
|
||||
bool bch2_vfs_dirty_folio(struct address_space *mapping, struct folio *folio);
|
||||
bool bch2_set_folio_dirty(struct bch_fs *,
|
||||
struct bch_inode_info *,
|
||||
struct folio *,
|
||||
struct bch2_folio_reservation *,
|
||||
unsigned, unsigned);
|
||||
size_t, size_t);
|
||||
|
||||
vm_fault_t bch2_page_fault(struct vm_fault *);
|
||||
vm_fault_t bch2_page_mkwrite(struct vm_fault *);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user