mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-09 00:00:04 +03:00
Update bcachefs sources to 14f68409be bcachefs: Optimize fiemap
This commit is contained in:
parent
8b02f791c3
commit
cc41f52bcc
@ -1 +1 @@
|
|||||||
ece184f718c2b678738bc2c42906e90eeb8ba7dc
|
14f68409bec43faff9d7480632488def385e0638
|
||||||
|
@ -20,6 +20,11 @@ static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
|
|||||||
pthread_mutex_lock(&sem->lock);
|
pthread_mutex_lock(&sem->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
|
||||||
|
{
|
||||||
|
return !pthread_mutex_trylock(&sem->lock);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void percpu_up_read_preempt_enable(struct percpu_rw_semaphore *sem)
|
static inline void percpu_up_read_preempt_enable(struct percpu_rw_semaphore *sem)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&sem->lock);
|
pthread_mutex_unlock(&sem->lock);
|
||||||
|
@ -741,6 +741,7 @@ struct bch_fs {
|
|||||||
/* ERASURE CODING */
|
/* ERASURE CODING */
|
||||||
struct list_head ec_new_stripe_list;
|
struct list_head ec_new_stripe_list;
|
||||||
struct mutex ec_new_stripe_lock;
|
struct mutex ec_new_stripe_lock;
|
||||||
|
u64 ec_stripe_hint;
|
||||||
|
|
||||||
struct bio_set ec_bioset;
|
struct bio_set ec_bioset;
|
||||||
|
|
||||||
|
@ -415,25 +415,22 @@ bch2_sort_repack_merge(struct bch_fs *c,
|
|||||||
struct bkey_format *out_f,
|
struct bkey_format *out_f,
|
||||||
bool filter_whiteouts)
|
bool filter_whiteouts)
|
||||||
{
|
{
|
||||||
struct bkey_packed *prev = NULL, *k_packed, *next;
|
struct bkey_packed *prev = NULL, *k_packed;
|
||||||
struct bkey k_unpacked;
|
|
||||||
struct bkey_s k;
|
struct bkey_s k;
|
||||||
struct btree_nr_keys nr;
|
struct btree_nr_keys nr;
|
||||||
|
BKEY_PADDED(k) tmp;
|
||||||
|
|
||||||
memset(&nr, 0, sizeof(nr));
|
memset(&nr, 0, sizeof(nr));
|
||||||
|
|
||||||
next = bch2_btree_node_iter_next_all(iter, src);
|
while ((k_packed = bch2_btree_node_iter_next_all(iter, src))) {
|
||||||
while ((k_packed = next)) {
|
|
||||||
/*
|
|
||||||
* The filter might modify the size of @k's value, so advance
|
|
||||||
* the iterator first:
|
|
||||||
*/
|
|
||||||
next = bch2_btree_node_iter_next_all(iter, src);
|
|
||||||
|
|
||||||
if (filter_whiteouts && bkey_whiteout(k_packed))
|
if (filter_whiteouts && bkey_whiteout(k_packed))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
k = __bkey_disassemble(src, k_packed, &k_unpacked);
|
EBUG_ON(bkeyp_val_u64s(&src->format, k_packed) >
|
||||||
|
BKEY_EXTENT_VAL_U64s_MAX);
|
||||||
|
|
||||||
|
bch2_bkey_unpack(src, &tmp.k, k_packed);
|
||||||
|
k = bkey_i_to_s(&tmp.k);
|
||||||
|
|
||||||
if (filter_whiteouts &&
|
if (filter_whiteouts &&
|
||||||
bch2_bkey_normalize(c, k))
|
bch2_bkey_normalize(c, k))
|
||||||
|
@ -575,6 +575,10 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
|
|||||||
}
|
}
|
||||||
} while (saw_non_marked);
|
} while (saw_non_marked);
|
||||||
|
|
||||||
|
trans_for_each_update(trans, i)
|
||||||
|
btree_insert_entry_checks(trans, i);
|
||||||
|
bch2_btree_trans_verify_locks(trans);
|
||||||
|
|
||||||
btree_trans_lock_write(c, trans);
|
btree_trans_lock_write(c, trans);
|
||||||
|
|
||||||
if (race_fault()) {
|
if (race_fault()) {
|
||||||
@ -853,7 +857,7 @@ int bch2_trans_commit(struct btree_trans *trans,
|
|||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct btree_insert_entry *i;
|
struct btree_insert_entry *i = NULL;
|
||||||
unsigned orig_mem_top = trans->mem_top;
|
unsigned orig_mem_top = trans->mem_top;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -875,10 +879,6 @@ int bch2_trans_commit(struct btree_trans *trans,
|
|||||||
trans->journal_seq = journal_seq;
|
trans->journal_seq = journal_seq;
|
||||||
trans->flags = flags;
|
trans->flags = flags;
|
||||||
|
|
||||||
trans_for_each_update(trans, i)
|
|
||||||
btree_insert_entry_checks(trans, i);
|
|
||||||
bch2_btree_trans_verify_locks(trans);
|
|
||||||
|
|
||||||
if (unlikely(!(trans->flags & BTREE_INSERT_NOCHECK_RW) &&
|
if (unlikely(!(trans->flags & BTREE_INSERT_NOCHECK_RW) &&
|
||||||
!percpu_ref_tryget(&c->writes))) {
|
!percpu_ref_tryget(&c->writes))) {
|
||||||
if (likely(!(trans->flags & BTREE_INSERT_LAZY_RW)))
|
if (likely(!(trans->flags & BTREE_INSERT_LAZY_RW)))
|
||||||
|
@ -1483,8 +1483,6 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
|
|||||||
s64 parity_sectors;
|
s64 parity_sectors;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
BUG_ON(!sectors);
|
|
||||||
|
|
||||||
ret = trans_get_key(trans, BTREE_ID_EC, POS(0, p.idx), &iter, &k);
|
ret = trans_get_key(trans, BTREE_ID_EC, POS(0, p.idx), &iter, &k);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1549,6 +1547,12 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
|
|||||||
? sectors
|
? sectors
|
||||||
: ptr_disk_sectors_delta(p, offset, sectors, flags);
|
: ptr_disk_sectors_delta(p, offset, sectors, flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* can happen due to rounding with compressed extents:
|
||||||
|
*/
|
||||||
|
if (!disk_sectors)
|
||||||
|
continue;
|
||||||
|
|
||||||
ret = bch2_trans_mark_pointer(trans, p, disk_sectors,
|
ret = bch2_trans_mark_pointer(trans, p, disk_sectors,
|
||||||
data_type);
|
data_type);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -704,26 +704,34 @@ static int ec_stripe_bkey_insert(struct bch_fs *c,
|
|||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
struct btree_iter *iter;
|
struct btree_iter *iter;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
|
struct bpos start_pos = POS(0, c->ec_stripe_hint);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bch2_trans_init(&trans, c, 0, 0);
|
bch2_trans_init(&trans, c, 0, 0);
|
||||||
retry:
|
retry:
|
||||||
bch2_trans_begin(&trans);
|
bch2_trans_begin(&trans);
|
||||||
|
|
||||||
/* XXX: start pos hint */
|
for_each_btree_key(&trans, iter, BTREE_ID_EC, start_pos,
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN,
|
|
||||||
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
|
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
|
||||||
if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0)
|
if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0) {
|
||||||
|
if (start_pos.offset) {
|
||||||
|
start_pos = POS_MIN;
|
||||||
|
bch2_btree_iter_set_pos(iter, start_pos);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = -ENOSPC;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (bkey_deleted(k.k))
|
if (bkey_deleted(k.k))
|
||||||
goto found_slot;
|
goto found_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
ret = -ENOSPC;
|
|
||||||
goto err;
|
goto err;
|
||||||
found_slot:
|
found_slot:
|
||||||
|
start_pos = iter->pos;
|
||||||
|
|
||||||
ret = ec_stripe_mem_alloc(c, iter);
|
ret = ec_stripe_mem_alloc(c, iter);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
@ -738,6 +746,8 @@ found_slot:
|
|||||||
err:
|
err:
|
||||||
if (ret == -EINTR)
|
if (ret == -EINTR)
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
||||||
|
c->ec_stripe_hint = ret ? start_pos.offset : start_pos.offset + 1;
|
||||||
bch2_trans_exit(&trans);
|
bch2_trans_exit(&trans);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -46,7 +46,8 @@ unsigned bch2_bkey_nr_dirty_ptrs(struct bkey_s_c k)
|
|||||||
|
|
||||||
switch (k.k->type) {
|
switch (k.k->type) {
|
||||||
case KEY_TYPE_btree_ptr:
|
case KEY_TYPE_btree_ptr:
|
||||||
case KEY_TYPE_extent: {
|
case KEY_TYPE_extent:
|
||||||
|
case KEY_TYPE_reflink_v: {
|
||||||
struct bkey_ptrs_c p = bch2_bkey_ptrs_c(k);
|
struct bkey_ptrs_c p = bch2_bkey_ptrs_c(k);
|
||||||
const struct bch_extent_ptr *ptr;
|
const struct bch_extent_ptr *ptr;
|
||||||
|
|
||||||
@ -309,20 +310,15 @@ bch2_extent_has_group(struct bch_fs *c, struct bkey_s_c_extent e, unsigned group
|
|||||||
|
|
||||||
unsigned bch2_extent_is_compressed(struct bkey_s_c k)
|
unsigned bch2_extent_is_compressed(struct bkey_s_c k)
|
||||||
{
|
{
|
||||||
|
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
||||||
|
const union bch_extent_entry *entry;
|
||||||
|
struct extent_ptr_decoded p;
|
||||||
unsigned ret = 0;
|
unsigned ret = 0;
|
||||||
|
|
||||||
switch (k.k->type) {
|
bkey_for_each_ptr_decode(k.k, ptrs, p, entry)
|
||||||
case KEY_TYPE_extent: {
|
if (!p.ptr.cached &&
|
||||||
struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
|
p.crc.compression_type != BCH_COMPRESSION_NONE)
|
||||||
const union bch_extent_entry *entry;
|
ret += p.crc.compressed_size;
|
||||||
struct extent_ptr_decoded p;
|
|
||||||
|
|
||||||
extent_for_each_ptr_decode(e, p, entry)
|
|
||||||
if (!p.ptr.cached &&
|
|
||||||
p.crc.compression_type != BCH_COMPRESSION_NONE)
|
|
||||||
ret += p.crc.compressed_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -455,6 +451,8 @@ found:
|
|||||||
BUG_ON(n.live_size != k->k.size);
|
BUG_ON(n.live_size != k->k.size);
|
||||||
|
|
||||||
restart_narrow_pointers:
|
restart_narrow_pointers:
|
||||||
|
ptrs = bch2_bkey_ptrs(bkey_i_to_s(k));
|
||||||
|
|
||||||
bkey_for_each_ptr_decode(&k->k, ptrs, p, i)
|
bkey_for_each_ptr_decode(&k->k, ptrs, p, i)
|
||||||
if (can_narrow_crc(p.crc, n)) {
|
if (can_narrow_crc(p.crc, n)) {
|
||||||
bch2_bkey_drop_ptr(bkey_i_to_s(k), &i->ptr);
|
bch2_bkey_drop_ptr(bkey_i_to_s(k), &i->ptr);
|
||||||
@ -809,19 +807,6 @@ bool bch2_cut_back(struct bpos where, struct bkey *k)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* bch_key_resize - adjust size of @k
|
|
||||||
*
|
|
||||||
* bkey_start_offset(k) will be preserved, modifies where the extent ends
|
|
||||||
*/
|
|
||||||
void bch2_key_resize(struct bkey *k,
|
|
||||||
unsigned new_size)
|
|
||||||
{
|
|
||||||
k->p.offset -= k->size;
|
|
||||||
k->p.offset += new_size;
|
|
||||||
k->size = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool extent_i_save(struct btree *b, struct bkey_packed *dst,
|
static bool extent_i_save(struct btree *b, struct bkey_packed *dst,
|
||||||
struct bkey_i *src)
|
struct bkey_i *src)
|
||||||
{
|
{
|
||||||
@ -968,6 +953,7 @@ static int __bch2_extent_atomic_end(struct btree_trans *trans,
|
|||||||
|
|
||||||
switch (k.k->type) {
|
switch (k.k->type) {
|
||||||
case KEY_TYPE_extent:
|
case KEY_TYPE_extent:
|
||||||
|
case KEY_TYPE_reflink_v:
|
||||||
*nr_iters += bch2_bkey_nr_alloc_ptrs(k);
|
*nr_iters += bch2_bkey_nr_alloc_ptrs(k);
|
||||||
|
|
||||||
if (*nr_iters >= max_iters) {
|
if (*nr_iters >= max_iters) {
|
||||||
@ -1372,12 +1358,11 @@ void bch2_insert_fixup_extent(struct btree_trans *trans,
|
|||||||
|
|
||||||
if (s.deleting)
|
if (s.deleting)
|
||||||
tmp.k.k.type = KEY_TYPE_discard;
|
tmp.k.k.type = KEY_TYPE_discard;
|
||||||
#if 0
|
|
||||||
/* disabled due to lock recursion - mark_lock: */
|
|
||||||
if (debug_check_bkeys(c))
|
if (debug_check_bkeys(c))
|
||||||
bch2_bkey_debugcheck(c, iter->l[0].b,
|
bch2_bkey_debugcheck(c, iter->l[0].b,
|
||||||
bkey_i_to_s_c(&tmp.k));
|
bkey_i_to_s_c(&tmp.k));
|
||||||
#endif
|
|
||||||
EBUG_ON(bkey_deleted(&tmp.k.k) || !tmp.k.k.size);
|
EBUG_ON(bkey_deleted(&tmp.k.k) || !tmp.k.k.size);
|
||||||
|
|
||||||
extent_bset_insert(c, iter, &tmp.k);
|
extent_bset_insert(c, iter, &tmp.k);
|
||||||
@ -1419,11 +1404,13 @@ void bch2_extent_debugcheck(struct bch_fs *c, struct btree *b,
|
|||||||
* going to get overwritten during replay)
|
* going to get overwritten during replay)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bch2_fs_bug_on(!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
|
if (percpu_down_read_trylock(&c->mark_lock)) {
|
||||||
!bch2_bkey_replicas_marked(c, e.s_c, false), c,
|
bch2_fs_bug_on(!test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) &&
|
||||||
"extent key bad (replicas not marked in superblock):\n%s",
|
!bch2_bkey_replicas_marked_locked(c, e.s_c, false), c,
|
||||||
(bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c), buf));
|
"extent key bad (replicas not marked in superblock):\n%s",
|
||||||
|
(bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c), buf));
|
||||||
|
percpu_up_read(&c->mark_lock);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* If journal replay hasn't finished, we might be seeing keys
|
* If journal replay hasn't finished, we might be seeing keys
|
||||||
* that will be overwritten by the time journal replay is done:
|
* that will be overwritten by the time journal replay is done:
|
||||||
@ -1591,9 +1578,9 @@ bool bch2_extent_normalize(struct bch_fs *c, struct bkey_s k)
|
|||||||
|
|
||||||
/* will only happen if all pointers were cached: */
|
/* will only happen if all pointers were cached: */
|
||||||
if (!bkey_val_u64s(k.k))
|
if (!bkey_val_u64s(k.k))
|
||||||
k.k->type = KEY_TYPE_deleted;
|
k.k->type = KEY_TYPE_discard;
|
||||||
|
|
||||||
return false;
|
return bkey_whiteout(k.k);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_bkey_mark_replicas_cached(struct bch_fs *c, struct bkey_s k,
|
void bch2_bkey_mark_replicas_cached(struct bch_fs *c, struct bkey_s k,
|
||||||
|
@ -538,7 +538,18 @@ static inline void bch2_cut_front(struct bpos where, struct bkey_i *k)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool bch2_cut_back(struct bpos, struct bkey *);
|
bool bch2_cut_back(struct bpos, struct bkey *);
|
||||||
void bch2_key_resize(struct bkey *, unsigned);
|
|
||||||
|
/**
|
||||||
|
* bch_key_resize - adjust size of @k
|
||||||
|
*
|
||||||
|
* bkey_start_offset(k) will be preserved, modifies where the extent ends
|
||||||
|
*/
|
||||||
|
static inline void bch2_key_resize(struct bkey *k, unsigned new_size)
|
||||||
|
{
|
||||||
|
k->p.offset -= k->size;
|
||||||
|
k->p.offset += new_size;
|
||||||
|
k->size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In extent_sort_fix_overlapping(), insert_fixup_extent(),
|
* In extent_sort_fix_overlapping(), insert_fixup_extent(),
|
||||||
|
@ -676,8 +676,8 @@ static int bch2_page_reservation_get(struct bch_fs *c,
|
|||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = offset / 512;
|
for (i = round_down(offset, block_bytes(c)) >> 9;
|
||||||
i < DIV_ROUND_UP(offset + len, 512);
|
i < round_up(offset + len, block_bytes(c)) >> 9;
|
||||||
i++) {
|
i++) {
|
||||||
disk_sectors += sectors_to_reserve(&s->s[i],
|
disk_sectors += sectors_to_reserve(&s->s[i],
|
||||||
res->disk.nr_replicas);
|
res->disk.nr_replicas);
|
||||||
@ -749,8 +749,8 @@ static void bch2_set_page_dirty(struct bch_fs *c,
|
|||||||
struct bch_page_state *s = bch2_page_state(page);
|
struct bch_page_state *s = bch2_page_state(page);
|
||||||
unsigned i, dirty_sectors = 0;
|
unsigned i, dirty_sectors = 0;
|
||||||
|
|
||||||
for (i = offset / 512;
|
for (i = round_down(offset, block_bytes(c)) >> 9;
|
||||||
i < DIV_ROUND_UP(offset + len, 512);
|
i < round_up(offset + len, block_bytes(c)) >> 9;
|
||||||
i++) {
|
i++) {
|
||||||
unsigned sectors = sectors_to_reserve(&s->s[i],
|
unsigned sectors = sectors_to_reserve(&s->s[i],
|
||||||
res->disk.nr_replicas);
|
res->disk.nr_replicas);
|
||||||
@ -1086,7 +1086,7 @@ retry:
|
|||||||
bkey_start_offset(k.k);
|
bkey_start_offset(k.k);
|
||||||
sectors = k.k->size - offset_into_extent;
|
sectors = k.k->size - offset_into_extent;
|
||||||
|
|
||||||
ret = bch2_read_indirect_extent(trans, iter,
|
ret = bch2_read_indirect_extent(trans,
|
||||||
&offset_into_extent, &tmp.k);
|
&offset_into_extent, &tmp.k);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
@ -1124,6 +1124,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
|
|||||||
struct btree_iter *iter;
|
struct btree_iter *iter;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
BKEY_PADDED(k) cur, prev;
|
BKEY_PADDED(k) cur, prev;
|
||||||
|
struct bpos end = POS(ei->v.i_ino, (start + len) >> 9);
|
||||||
unsigned offset_into_extent, sectors;
|
unsigned offset_into_extent, sectors;
|
||||||
bool have_extent = false;
|
bool have_extent = false;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1134,14 +1135,16 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
|
|||||||
bch2_trans_init(&trans, c, 0, 0);
|
bch2_trans_init(&trans, c, 0, 0);
|
||||||
|
|
||||||
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
|
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
|
||||||
POS(ei->v.i_ino, start >> 9),
|
POS(ei->v.i_ino, start >> 9), 0);
|
||||||
BTREE_ITER_SLOTS);
|
retry:
|
||||||
|
while ((k = bch2_btree_iter_peek(iter)).k &&
|
||||||
while (bkey_cmp(iter->pos, POS(ei->v.i_ino, (start + len) >> 9)) < 0) {
|
!(ret = bkey_err(k)) &&
|
||||||
k = bch2_btree_iter_peek_slot(iter);
|
bkey_cmp(iter->pos, end) < 0) {
|
||||||
ret = bkey_err(k);
|
if (!bkey_extent_is_data(k.k) &&
|
||||||
if (ret)
|
k.k->type != KEY_TYPE_reservation) {
|
||||||
goto err;
|
bch2_btree_iter_next(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bkey_reassemble(&cur.k, k);
|
bkey_reassemble(&cur.k, k);
|
||||||
k = bkey_i_to_s_c(&cur.k);
|
k = bkey_i_to_s_c(&cur.k);
|
||||||
@ -1150,41 +1153,44 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
|
|||||||
bkey_start_offset(k.k);
|
bkey_start_offset(k.k);
|
||||||
sectors = k.k->size - offset_into_extent;
|
sectors = k.k->size - offset_into_extent;
|
||||||
|
|
||||||
ret = bch2_read_indirect_extent(&trans, iter,
|
ret = bch2_read_indirect_extent(&trans,
|
||||||
&offset_into_extent, &cur.k);
|
&offset_into_extent, &cur.k);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sectors = min(sectors, k.k->size - offset_into_extent);
|
sectors = min(sectors, k.k->size - offset_into_extent);
|
||||||
|
|
||||||
bch2_cut_front(POS(k.k->p.inode,
|
if (offset_into_extent)
|
||||||
bkey_start_offset(k.k) + offset_into_extent),
|
bch2_cut_front(POS(k.k->p.inode,
|
||||||
&cur.k);
|
bkey_start_offset(k.k) +
|
||||||
|
offset_into_extent),
|
||||||
|
&cur.k);
|
||||||
bch2_key_resize(&cur.k.k, sectors);
|
bch2_key_resize(&cur.k.k, sectors);
|
||||||
cur.k.k.p.offset = iter->pos.offset + cur.k.k.size;
|
cur.k.k.p.offset = iter->pos.offset + cur.k.k.size;
|
||||||
|
|
||||||
if (bkey_extent_is_data(k.k) ||
|
if (have_extent) {
|
||||||
k.k->type == KEY_TYPE_reservation) {
|
ret = bch2_fill_extent(c, info,
|
||||||
if (have_extent) {
|
bkey_i_to_s_c(&prev.k), 0);
|
||||||
ret = bch2_fill_extent(c, info,
|
if (ret)
|
||||||
bkey_i_to_s_c(&prev.k), 0);
|
break;
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bkey_copy(&prev.k, &cur.k);
|
|
||||||
have_extent = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bch2_btree_iter_set_pos(iter,
|
bkey_copy(&prev.k, &cur.k);
|
||||||
POS(iter->pos.inode,
|
have_extent = true;
|
||||||
iter->pos.offset + sectors));
|
|
||||||
|
if (k.k->type == KEY_TYPE_reflink_v)
|
||||||
|
bch2_btree_iter_set_pos(iter, k.k->p);
|
||||||
|
else
|
||||||
|
bch2_btree_iter_next(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == -EINTR)
|
||||||
|
goto retry;
|
||||||
|
|
||||||
if (!ret && have_extent)
|
if (!ret && have_extent)
|
||||||
ret = bch2_fill_extent(c, info, bkey_i_to_s_c(&prev.k),
|
ret = bch2_fill_extent(c, info, bkey_i_to_s_c(&prev.k),
|
||||||
FIEMAP_EXTENT_LAST);
|
FIEMAP_EXTENT_LAST);
|
||||||
err:
|
|
||||||
ret = bch2_trans_exit(&trans) ?: ret;
|
ret = bch2_trans_exit(&trans) ?: ret;
|
||||||
return ret < 0 ? ret : 0;
|
return ret < 0 ? ret : 0;
|
||||||
}
|
}
|
||||||
@ -1449,12 +1455,6 @@ static int bch2_vfs_write_inode(struct inode *vinode,
|
|||||||
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME);
|
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME);
|
||||||
mutex_unlock(&inode->ei_update_lock);
|
mutex_unlock(&inode->ei_update_lock);
|
||||||
|
|
||||||
if (c->opts.journal_flush_disabled)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!ret && wbc->sync_mode == WB_SYNC_ALL)
|
|
||||||
ret = bch2_journal_flush_seq(&c->journal, inode->ei_journal_seq);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1511,6 +1511,9 @@ static int bch2_sync_fs(struct super_block *sb, int wait)
|
|||||||
{
|
{
|
||||||
struct bch_fs *c = sb->s_fs_info;
|
struct bch_fs *c = sb->s_fs_info;
|
||||||
|
|
||||||
|
if (c->opts.journal_flush_disabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!wait) {
|
if (!wait) {
|
||||||
bch2_journal_flush_async(&c->journal, NULL);
|
bch2_journal_flush_async(&c->journal, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -454,7 +454,10 @@ static struct bio *bch2_write_bio_alloc(struct bch_fs *c,
|
|||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
unsigned output_available =
|
unsigned output_available =
|
||||||
min(wp->sectors_free << 9, src->bi_iter.bi_size);
|
min(wp->sectors_free << 9, src->bi_iter.bi_size);
|
||||||
unsigned pages = DIV_ROUND_UP(output_available, PAGE_SIZE);
|
unsigned pages = DIV_ROUND_UP(output_available +
|
||||||
|
(buf
|
||||||
|
? ((unsigned long) buf & (PAGE_SIZE - 1))
|
||||||
|
: 0), PAGE_SIZE);
|
||||||
|
|
||||||
bio = bio_alloc_bioset(GFP_NOIO, pages, &c->bio_write);
|
bio = bio_alloc_bioset(GFP_NOIO, pages, &c->bio_write);
|
||||||
wbio = wbio_init(bio);
|
wbio = wbio_init(bio);
|
||||||
@ -912,30 +915,39 @@ flush_io:
|
|||||||
void bch2_write(struct closure *cl)
|
void bch2_write(struct closure *cl)
|
||||||
{
|
{
|
||||||
struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
|
struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
|
||||||
|
struct bio *bio = &op->wbio.bio;
|
||||||
struct bch_fs *c = op->c;
|
struct bch_fs *c = op->c;
|
||||||
|
|
||||||
BUG_ON(!op->nr_replicas);
|
BUG_ON(!op->nr_replicas);
|
||||||
BUG_ON(!op->write_point.v);
|
BUG_ON(!op->write_point.v);
|
||||||
BUG_ON(!bkey_cmp(op->pos, POS_MAX));
|
BUG_ON(!bkey_cmp(op->pos, POS_MAX));
|
||||||
|
|
||||||
|
if (bio_sectors(bio) & (c->opts.block_size - 1)) {
|
||||||
|
__bcache_io_error(c, "misaligned write");
|
||||||
|
op->error = -EIO;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
op->start_time = local_clock();
|
op->start_time = local_clock();
|
||||||
|
|
||||||
bch2_keylist_init(&op->insert_keys, op->inline_keys);
|
bch2_keylist_init(&op->insert_keys, op->inline_keys);
|
||||||
wbio_init(&op->wbio.bio)->put_bio = false;
|
wbio_init(bio)->put_bio = false;
|
||||||
|
|
||||||
if (c->opts.nochanges ||
|
if (c->opts.nochanges ||
|
||||||
!percpu_ref_tryget(&c->writes)) {
|
!percpu_ref_tryget(&c->writes)) {
|
||||||
__bcache_io_error(c, "read only");
|
__bcache_io_error(c, "read only");
|
||||||
op->error = -EROFS;
|
op->error = -EROFS;
|
||||||
if (!(op->flags & BCH_WRITE_NOPUT_RESERVATION))
|
goto err;
|
||||||
bch2_disk_reservation_put(c, &op->res);
|
|
||||||
closure_return(cl);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bch2_increment_clock(c, bio_sectors(&op->wbio.bio), WRITE);
|
bch2_increment_clock(c, bio_sectors(bio), WRITE);
|
||||||
|
|
||||||
continue_at_nobarrier(cl, __bch2_write, NULL);
|
continue_at_nobarrier(cl, __bch2_write, NULL);
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
if (!(op->flags & BCH_WRITE_NOPUT_RESERVATION))
|
||||||
|
bch2_disk_reservation_put(c, &op->res);
|
||||||
|
closure_return(cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cache promotion on read */
|
/* Cache promotion on read */
|
||||||
@ -1285,7 +1297,7 @@ retry:
|
|||||||
bkey_start_offset(k.k);
|
bkey_start_offset(k.k);
|
||||||
sectors = k.k->size - offset_into_extent;
|
sectors = k.k->size - offset_into_extent;
|
||||||
|
|
||||||
ret = bch2_read_indirect_extent(&trans, iter,
|
ret = bch2_read_indirect_extent(&trans,
|
||||||
&offset_into_extent, &tmp.k);
|
&offset_into_extent, &tmp.k);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
@ -1574,19 +1586,15 @@ static void bch2_read_endio(struct bio *bio)
|
|||||||
bch2_rbio_punt(rbio, __bch2_read_endio, context, wq);
|
bch2_rbio_punt(rbio, __bch2_read_endio, context, wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bch2_read_indirect_extent(struct btree_trans *trans,
|
int __bch2_read_indirect_extent(struct btree_trans *trans,
|
||||||
struct btree_iter *extent_iter,
|
unsigned *offset_into_extent,
|
||||||
unsigned *offset_into_extent,
|
struct bkey_i *orig_k)
|
||||||
struct bkey_i *orig_k)
|
|
||||||
{
|
{
|
||||||
struct btree_iter *iter;
|
struct btree_iter *iter;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
u64 reflink_offset;
|
u64 reflink_offset;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (orig_k->k.type != KEY_TYPE_reflink_p)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
reflink_offset = le64_to_cpu(bkey_i_to_reflink_p(orig_k)->v.idx) +
|
reflink_offset = le64_to_cpu(bkey_i_to_reflink_p(orig_k)->v.idx) +
|
||||||
*offset_into_extent;
|
*offset_into_extent;
|
||||||
|
|
||||||
@ -1893,7 +1901,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
|
|||||||
bkey_start_offset(k.k);
|
bkey_start_offset(k.k);
|
||||||
sectors = k.k->size - offset_into_extent;
|
sectors = k.k->size - offset_into_extent;
|
||||||
|
|
||||||
ret = bch2_read_indirect_extent(&trans, iter,
|
ret = bch2_read_indirect_extent(&trans,
|
||||||
&offset_into_extent, &tmp.k);
|
&offset_into_extent, &tmp.k);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -95,8 +95,17 @@ struct bch_devs_mask;
|
|||||||
struct cache_promote_op;
|
struct cache_promote_op;
|
||||||
struct extent_ptr_decoded;
|
struct extent_ptr_decoded;
|
||||||
|
|
||||||
int bch2_read_indirect_extent(struct btree_trans *, struct btree_iter *,
|
int __bch2_read_indirect_extent(struct btree_trans *, unsigned *,
|
||||||
unsigned *, struct bkey_i *);
|
struct bkey_i *);
|
||||||
|
|
||||||
|
static inline int bch2_read_indirect_extent(struct btree_trans *trans,
|
||||||
|
unsigned *offset_into_extent,
|
||||||
|
struct bkey_i *k)
|
||||||
|
{
|
||||||
|
return k->k.type == KEY_TYPE_reflink_p
|
||||||
|
? __bch2_read_indirect_extent(trans, offset_into_extent, k)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
enum bch_read_flags {
|
enum bch_read_flags {
|
||||||
BCH_READ_RETRY_IF_STALE = 1 << 0,
|
BCH_READ_RETRY_IF_STALE = 1 << 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user