diff --git a/.bcachefs_revision b/.bcachefs_revision index c2426462..4f5b2097 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -c887148ebf9989ce8bdf6f814d4342ba5bf465fa +a623b3063d5d6ab6652314028531060d5a0d192e diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c index 4de4036d..ccd6cbfd 100644 --- a/libbcachefs/alloc_background.c +++ b/libbcachefs/alloc_background.c @@ -1878,10 +1878,11 @@ static void bch2_do_discards_fast_work(struct work_struct *work) if (!got_bucket) break; - blkdev_issue_discard(ca->disk_sb.bdev, - bucket.offset * ca->mi.bucket_size, - ca->mi.bucket_size, - GFP_KERNEL); + if (ca->mi.discard && !c->opts.nochanges) + blkdev_issue_discard(ca->disk_sb.bdev, + bucket.offset * ca->mi.bucket_size, + ca->mi.bucket_size, + GFP_KERNEL); int ret = bch2_trans_do(c, NULL, NULL, BCH_WATERMARK_btree| diff --git a/libbcachefs/backpointers.c b/libbcachefs/backpointers.c index 23fe9378..f2b33fe4 100644 --- a/libbcachefs/backpointers.c +++ b/libbcachefs/backpointers.c @@ -68,9 +68,11 @@ void bch2_backpointer_to_text(struct printbuf *out, const struct bch_backpointer void bch2_backpointer_k_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k) { - prt_str(out, "bucket="); - bch2_bpos_to_text(out, bp_pos_to_bucket(c, k.k->p)); - prt_str(out, " "); + if (bch2_dev_exists2(c, k.k->p.inode)) { + prt_str(out, "bucket="); + bch2_bpos_to_text(out, bp_pos_to_bucket(c, k.k->p)); + prt_str(out, " "); + } bch2_backpointer_to_text(out, bkey_s_c_to_backpointer(k).v); } diff --git a/libbcachefs/bcachefs_format.h b/libbcachefs/bcachefs_format.h index 9f45f833..bff8750a 100644 --- a/libbcachefs/bcachefs_format.h +++ b/libbcachefs/bcachefs_format.h @@ -653,7 +653,7 @@ struct bch_encrypted_key { /* * If this field is present in the superblock, it stores an encryption key which - * is used to encrypt all other data/metadata. The key will normally be encrypted + * is used encrypt all other data/metadata. The key will normally be encrypted * with the key userspace provides, but if encryption has been turned off we'll * just store the master key unencrypted in the superblock so we can access the * previously encrypted data. diff --git a/libbcachefs/btree_update.c b/libbcachefs/btree_update.c index cbb7cf21..f58e5b33 100644 --- a/libbcachefs/btree_update.c +++ b/libbcachefs/btree_update.c @@ -848,7 +848,7 @@ __bch2_fs_log_msg(struct bch_fs *c, unsigned commit_flags, const char *fmt, if (ret) goto err; - if (!test_bit(JOURNAL_STARTED, &c->journal.flags)) { + if (!test_bit(JOURNAL_RUNNING, &c->journal.flags)) { ret = darray_make_room(&c->journal.early_journal_entries, jset_u64s(u64s)); if (ret) goto err; diff --git a/libbcachefs/errcode.c b/libbcachefs/errcode.c index d260ff9b..43557beb 100644 --- a/libbcachefs/errcode.c +++ b/libbcachefs/errcode.c @@ -2,6 +2,7 @@ #include "bcachefs.h" #include "errcode.h" +#include "trace.h" #include @@ -49,15 +50,17 @@ bool __bch2_err_matches(int err, int class) return err == class; } -int __bch2_err_class(int err) +int __bch2_err_class(int bch_err) { - err = -err; - BUG_ON((unsigned) err >= BCH_ERR_MAX); + int std_err = -bch_err; + BUG_ON((unsigned) std_err >= BCH_ERR_MAX); - while (err >= BCH_ERR_START && bch2_errcode_parents[err - BCH_ERR_START]) - err = bch2_errcode_parents[err - BCH_ERR_START]; + while (std_err >= BCH_ERR_START && bch2_errcode_parents[std_err - BCH_ERR_START]) + std_err = bch2_errcode_parents[std_err - BCH_ERR_START]; - return -err; + trace_error_downcast(bch_err, std_err, _RET_IP_); + + return -std_err; } const char *bch2_blk_status_to_str(blk_status_t status) diff --git a/libbcachefs/errcode.h b/libbcachefs/errcode.h index fe3fc14d..e960a6ea 100644 --- a/libbcachefs/errcode.h +++ b/libbcachefs/errcode.h @@ -78,6 +78,7 @@ x(ENOMEM, ENOMEM_fs_name_alloc) \ x(ENOMEM, ENOMEM_fs_other_alloc) \ x(ENOMEM, ENOMEM_dev_alloc) \ + x(ENOMEM, ENOMEM_disk_accounting) \ x(ENOSPC, ENOSPC_disk_reservation) \ x(ENOSPC, ENOSPC_bucket_alloc) \ x(ENOSPC, ENOSPC_disk_label_add) \ diff --git a/libbcachefs/fs-io-buffered.c b/libbcachefs/fs-io-buffered.c index 73c12e56..27710cdd 100644 --- a/libbcachefs/fs-io-buffered.c +++ b/libbcachefs/fs-io-buffered.c @@ -303,18 +303,6 @@ void bch2_readahead(struct readahead_control *ractl) darray_exit(&readpages_iter.folios); } -static void __bchfs_readfolio(struct bch_fs *c, struct bch_read_bio *rbio, - subvol_inum inum, struct folio *folio) -{ - bch2_folio_create(folio, __GFP_NOFAIL); - - rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC; - rbio->bio.bi_iter.bi_sector = folio_sector(folio); - BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); - - bch2_trans_run(c, (bchfs_read(trans, rbio, inum, NULL), 0)); -} - static void bch2_read_single_folio_end_io(struct bio *bio) { complete(bio->bi_private); @@ -329,6 +317,9 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping) int ret; DECLARE_COMPLETION_ONSTACK(done); + if (!bch2_folio_create(folio, GFP_KERNEL)) + return -ENOMEM; + bch2_inode_opts_get(&opts, c, &inode->ei_inode); rbio = rbio_init(bio_alloc_bioset(NULL, 1, REQ_OP_READ, GFP_KERNEL, &c->bio_read), @@ -336,7 +327,11 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping) rbio->bio.bi_private = &done; rbio->bio.bi_end_io = bch2_read_single_folio_end_io; - __bchfs_readfolio(c, rbio, inode_inum(inode), folio); + rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC; + rbio->bio.bi_iter.bi_sector = folio_sector(folio); + BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); + + bch2_trans_run(c, (bchfs_read(trans, rbio, inode_inum(inode), NULL), 0)); wait_for_completion(&done); ret = blk_status_to_errno(rbio->bio.bi_status); diff --git a/libbcachefs/journal.c b/libbcachefs/journal.c index 46dc25ad..d717e90a 100644 --- a/libbcachefs/journal.c +++ b/libbcachefs/journal.c @@ -1183,12 +1183,13 @@ void bch2_fs_journal_stop(struct journal *j) bch2_journal_meta(j); journal_quiesce(j); + cancel_delayed_work_sync(&j->write_work); BUG_ON(!bch2_journal_error(j) && test_bit(JOURNAL_REPLAY_DONE, &j->flags) && j->last_empty_seq != journal_cur_seq(j)); - cancel_delayed_work_sync(&j->write_work); + clear_bit(JOURNAL_RUNNING, &j->flags); } int bch2_fs_journal_start(struct journal *j, u64 cur_seq) @@ -1262,7 +1263,7 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq) spin_lock(&j->lock); - set_bit(JOURNAL_STARTED, &j->flags); + set_bit(JOURNAL_RUNNING, &j->flags); j->last_flush_write = jiffies; j->reservations.idx = j->reservations.unwritten_idx = journal_cur_seq(j); diff --git a/libbcachefs/journal.h b/libbcachefs/journal.h index 7c7528f8..4b8c709b 100644 --- a/libbcachefs/journal.h +++ b/libbcachefs/journal.h @@ -372,7 +372,7 @@ static inline int bch2_journal_res_get(struct journal *j, struct journal_res *re int ret; EBUG_ON(res->ref); - EBUG_ON(!test_bit(JOURNAL_STARTED, &j->flags)); + EBUG_ON(!test_bit(JOURNAL_RUNNING, &j->flags)); res->u64s = u64s; @@ -418,7 +418,7 @@ struct bch_dev; static inline void bch2_journal_set_replay_done(struct journal *j) { - BUG_ON(!test_bit(JOURNAL_STARTED, &j->flags)); + BUG_ON(!test_bit(JOURNAL_RUNNING, &j->flags)); set_bit(JOURNAL_REPLAY_DONE, &j->flags); } diff --git a/libbcachefs/journal_reclaim.c b/libbcachefs/journal_reclaim.c index ab811c0d..5e3a6d63 100644 --- a/libbcachefs/journal_reclaim.c +++ b/libbcachefs/journal_reclaim.c @@ -831,7 +831,7 @@ bool bch2_journal_flush_pins(struct journal *j, u64 seq_to_flush) /* time_stats this */ bool did_work = false; - if (!test_bit(JOURNAL_STARTED, &j->flags)) + if (!test_bit(JOURNAL_RUNNING, &j->flags)) return false; closure_wait_event(&j->async_wait, diff --git a/libbcachefs/journal_types.h b/libbcachefs/journal_types.h index 011f7a0d..508d0ede 100644 --- a/libbcachefs/journal_types.h +++ b/libbcachefs/journal_types.h @@ -131,7 +131,7 @@ enum journal_space_from { enum journal_flags { JOURNAL_REPLAY_DONE, - JOURNAL_STARTED, + JOURNAL_RUNNING, JOURNAL_MAY_SKIP_FLUSH, JOURNAL_NEED_FLUSH_WRITE, }; diff --git a/libbcachefs/snapshot.c b/libbcachefs/snapshot.c index 45f67e8b..ac6ba04d 100644 --- a/libbcachefs/snapshot.c +++ b/libbcachefs/snapshot.c @@ -728,7 +728,7 @@ static int check_snapshot(struct btree_trans *trans, return 0; memset(&s, 0, sizeof(s)); - memcpy(&s, k.v, bkey_val_bytes(k.k)); + memcpy(&s, k.v, min(sizeof(s), bkey_val_bytes(k.k))); id = le32_to_cpu(s.parent); if (id) { diff --git a/libbcachefs/super-io.c b/libbcachefs/super-io.c index a3a9e85a..38a50732 100644 --- a/libbcachefs/super-io.c +++ b/libbcachefs/super-io.c @@ -804,7 +804,6 @@ got_super: goto err; } - ret = 0; sb->have_layout = true; ret = bch2_sb_validate(sb, &err, READ); diff --git a/libbcachefs/super.c b/libbcachefs/super.c index a7f9de22..46da8204 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -286,8 +286,13 @@ static void __bch2_fs_read_only(struct bch_fs *c) if (test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags) && !test_bit(BCH_FS_emergency_ro, &c->flags)) set_bit(BCH_FS_clean_shutdown, &c->flags); + bch2_fs_journal_stop(&c->journal); + bch_info(c, "%sshutdown complete, journal seq %llu", + test_bit(BCH_FS_clean_shutdown, &c->flags) ? "" : "un", + c->journal.seq_ondisk); + /* * After stopping journal: */ @@ -461,6 +466,7 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) * at least one non-flush write in the journal or recovery will fail: */ set_bit(JOURNAL_NEED_FLUSH_WRITE, &c->journal.flags); + set_bit(JOURNAL_RUNNING, &c->journal.flags); for_each_rw_member(c, ca) bch2_dev_allocator_add(c, ca); diff --git a/libbcachefs/trace.h b/libbcachefs/trace.h index 293b90d7..6aa81d1e 100644 --- a/libbcachefs/trace.h +++ b/libbcachefs/trace.h @@ -1431,6 +1431,25 @@ DEFINE_EVENT(fs_str, data_update, TP_ARGS(c, str) ); +TRACE_EVENT(error_downcast, + TP_PROTO(int bch_err, int std_err, unsigned long ip), + TP_ARGS(bch_err, std_err, ip), + + TP_STRUCT__entry( + __array(char, bch_err, 32 ) + __array(char, std_err, 32 ) + __array(char, ip, 32 ) + ), + + TP_fast_assign( + strscpy(__entry->bch_err, bch2_err_str(bch_err), sizeof(__entry->bch_err)); + strscpy(__entry->std_err, bch2_err_str(std_err), sizeof(__entry->std_err)); + snprintf(__entry->ip, sizeof(__entry->ip), "%ps", (void *) ip); + ), + + TP_printk("%s -> %s %s", __entry->bch_err, __entry->std_err, __entry->ip) +); + #endif /* _TRACE_BCACHEFS_H */ /* This part must be outside protection */ diff --git a/linux/time_stats.c b/linux/time_stats.c index 0b90c80c..d7dd64ba 100644 --- a/linux/time_stats.c +++ b/linux/time_stats.c @@ -313,7 +313,7 @@ void time_stats_to_json(struct seq_buf *out, struct time_stats *stats, seq_buf_printf(out, " \"stddev\": %llu\n", d_stddev); seq_buf_printf(out, " },\n"); - seq_buf_printf(out, " \"frequency_ns\": {\n"); + seq_buf_printf(out, " \"between_ns\": {\n"); seq_buf_printf(out, " \"min\": %llu,\n", stats->min_freq); seq_buf_printf(out, " \"max\": %llu,\n", stats->max_freq); seq_buf_printf(out, " \"mean\": %llu,\n", f_mean); @@ -323,14 +323,14 @@ void time_stats_to_json(struct seq_buf *out, struct time_stats *stats, f_mean = mean_and_variance_weighted_get_mean(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT); f_stddev = mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT); - seq_buf_printf(out, " \"frequency_ewma_ns\": {\n"); + seq_buf_printf(out, " \"between_ewma_ns\": {\n"); seq_buf_printf(out, " \"mean\": %llu,\n", f_mean); seq_buf_printf(out, " \"stddev\": %llu\n", f_stddev); if (quantiles) { u64 last_q = 0; - /* close frequency_ewma_ns but signal more items */ + /* close between_ewma_ns but signal more items */ seq_buf_printf(out, " },\n"); seq_buf_printf(out, " \"quantiles_ns\": [\n"); @@ -345,7 +345,7 @@ void time_stats_to_json(struct seq_buf *out, struct time_stats *stats, } seq_buf_printf(out, " ]\n"); } else { - /* close frequency_ewma_ns without dumping further */ + /* close between_ewma_ns without dumping further */ seq_buf_printf(out, " }\n"); }