diff --git a/sys-kernel/hardened-kernel/Manifest b/sys-kernel/hardened-kernel/Manifest index 9b9fd17..6ba5db3 100644 --- a/sys-kernel/hardened-kernel/Manifest +++ b/sys-kernel/hardened-kernel/Manifest @@ -1,10 +1,10 @@ -DIST genpatches-6.12-13.base.tar.xz 806528 BLAKE2B 0eec1195d5a497e64556d992893f251a54c558151aef1fc1d03de0b95bdbe03588ef486875e7676f9635da62e975dd8509279ed2d96b4dcb3796e1d8a4bb3768 SHA512 3cf8549679aae42fe56a25c0f9d5eb5c59fb867c77dc22c21446064e55d91276ec75f60f5737ab9a39c82dd0e74ab1ee3bd62b5a78f7448827b5577257976aed -DIST genpatches-6.12-13.experimental.tar.xz 78444 BLAKE2B 721334f36ae20a598295ce87c31acb12eadee9080bed53ba3a4fbd03180abfa4771c39d0b2d79ccdd28b04766ddd6eb80b1c8f3dc9e5fd2b8c17fe921125d1ba SHA512 834f04aed25aa6f9e660e64b02e488f2c99cf8cb4e20a11c813c8e21b7d91a650e0c795c1369147206d707c75f2a1d25144b08ca9b1b02162443d4ea1bd36d26 -DIST genpatches-6.12-13.extras.tar.xz 4056 BLAKE2B af48fba5d81bf8e13658555d94fa131e3f8fa06144148dd11b58823f802c5c4aea823fc4cd8f308ba6518638b65637d0b8a030d513d4b2a05384fc8f40550d94 SHA512 d7b1290d44696284fde4980ad3b90a190659056739a084ae704d1edf1a06ee166fa78960a42999b9e6e2d8aad4fd330621c8865f5e2517f1453c916d6375a365 -DIST gentoo-kernel-config-g14.tar.gz 5686 BLAKE2B e5147ff4ffab92428b3e7f1b0897b997f8a298805f4f43b0a4d3047607bbb1a5ebfc268e0bb9688372a5eda561df9f256c78e00cdd7e3caf7868724214722f56 SHA512 f79638f9ff9dd0154512baf0234024216b6708d35a3c03a580ca5913286ad1ea13bdde5ea9b4722c6a7cd8d591c11ec52c1e225111a260343cd56aa1f1a88502 -DIST kernel-aarch64-fedora.config.6.12.1-gentoo 287989 BLAKE2B fbf6183487ffc6d30543c6b9caedbca224cc9ce4ec917e35ab351030212b721af8cc33aafa1feb229a1d6b45c9f45329f8e4957bdb3d43bee7ac223eeb90a994 SHA512 fad6121dfe4a3c82039cfe77614e90b4a954fe12d156f29ef9a596745327a3d30c7a40fc4002405a692685c7deaf9a7d3d6f944d505bc51ed5c387f9c9fd6311 -DIST kernel-i686-fedora.config.6.12.1-gentoo 255123 BLAKE2B 186e22a426f2485ba46429852d94e139b91cc3508eb405028b3fd779a224a2c8eaf3e6a15bbee7ebc54a295bf8c3d434d972cd33b42b87951cf826435a3c3d65 SHA512 90f505be0faab191dc06dba834e4d6726f88d9868b6610ab5b89c496a4b4c37e9ce414e6e1447136edb028420a243b1ce620de5e97aa2b4b784e20a6eeacd015 -DIST kernel-ppc64le-fedora.config.6.12.1-gentoo 241811 BLAKE2B 59fcfd508a208e7a6a393d1b35811e553098669e9db7302fe929d998fb705330f104b671ba34d6e5992f9c4ddb2e7f30509a261f324400cb3cd5216405ef4614 SHA512 ab0bf86e20bf3348b8703fbf7aeb29105a02ca768f9a4cf47fc59c77e452b4659367bd8c10ceb67295d869158905e2c76c2a55745e01db3fab420ce257c11cb6 -DIST kernel-x86_64-fedora.config.6.12.1-gentoo 256170 BLAKE2B 39e03735453c66f4262005517fe00e66da0b8c813f7d4a0247083a69eac998c81d75ccdd6c56a389f287f2b9dd5d20e3703b9cfb4d3f89b4672897d026a6a00b SHA512 57f584d82145c5d35bd71f7b3fa5f45adb12cc46915d6f88c7c6f291b6dfde73a4a7f4b796cecf46b145fde5090efc26fdc4fe3945b37d5878efc94ce39b4b7a +DIST genpatches-6.12-15.base.tar.xz 856536 BLAKE2B dba6809d63e9ff073b40a08afdeadc173e3ab5d739cb251e4415887815a420ba295fcdb80f53f2601f5274ba206d9f562d3841977391f254ef5783dc5f329010 SHA512 ca9958e76b1c156e7ebad1c14a1f957733a8cd99f9c8e23b82bd06bc4fc982c70685668f5d5dbc251abc4e7ea32a9508b0215babf18511514aa2c159767760f4 +DIST genpatches-6.12-15.experimental.tar.xz 78472 BLAKE2B 4f03e5134b855fab5f001a688ccc200243f8e51a258e65064bd664d1f6a4a97bba5735f67ce9972640ee52db2244049a8ba2dc192283047287b10ececb528fed SHA512 320f7277284ea3f4ab8fb47b23aedfcaf6bb1f9b882a45d389b7e4ecb017d058f6f6fd9dea961d9c465da79877f287656e4791779fd911c4f7b43c05745321c1 +DIST genpatches-6.12-15.extras.tar.xz 4056 BLAKE2B f3b21174d15e3ee9f367ddd10745e1812b2a7573dc618f1c42db7afc9794208fdb67f62e2f400a144ad2f6d050b0419d67152c10af83ca263ba210bd8d939972 SHA512 7a5460091350c279519bacbfdcc83ee69d14364c0a8b5c192b244695196f72ec24e27d85d1f87608b1af6e9adcb5089ffb079c3e5190b7580833a438a2672c32 +DIST gentoo-kernel-config-g15.tar.gz 5746 BLAKE2B 2baef40e18cbf3bb975362d71ad674604ad80338d1e6914ffa2fc03af26f1b9c9cec66d39a56077693a7327060bc29bd5eb5787549857dd3779e841192cb2016 SHA512 45d609ee25a529988868b8c99c808f4e6abbde34ae501bf35523431ee85c9f3657663d6f938f2036a5f012a55a68965b32fd41fc44d8f6ca606a6fd38f952445 +DIST kernel-aarch64-fedora.config.6.12.8-gentoo 288081 BLAKE2B 08273a34c387621d0ccffcc325a0a34b40e0a8fbe78f2429c8a9efc73aa05f8fb563ed53e5fadb25662089f23ebafb61b2d08f91ea00b073e67e702798255e9c SHA512 58ea4f247aa9af6f7535ab5fe44dae2fbf286c7fbceeda86df532125807bbd4c25a89ddeeff4284592efefbaaef5022626abad7f1d1d64976e3040dc6e89251a +DIST kernel-i686-fedora.config.6.12.8-gentoo 255163 BLAKE2B 7015bbcfb2aed0ba70173dc7e9abf464e167184e2bc8cea6d26623972bbe6b42956241a7d75ff8604d70d5c0202db6e40cdb890abfcea3d0c8e0d00aa869353e SHA512 a1b4b688510a231fe079b4158e8aaddaddc4e719367132668279edcb16e32b6c7f2c449ec196646b0986171dc43a82475255502ae40679e0433de9f9876e0a20 +DIST kernel-ppc64le-fedora.config.6.12.8-gentoo 241851 BLAKE2B e7b8833572348037d7af2ba1f9671e8010276d853e0d85b8a175c0dcc5c212c57c7660be54a7ba2621c427cc8120acbeb1063a1c1a1c293894ebe1d63921b684 SHA512 7a81fe1c4b1d4fb9f2d68846882a8869c0888c8fa764ec41f41d27e61b7a69825ea8ceba2209b40deb7c0e8f4bb2c5d81226a4f28e7ca8aff4788bc7a3292194 +DIST kernel-x86_64-fedora.config.6.12.8-gentoo 256210 BLAKE2B f14f7de8ae573561824df47cf94c3c0ce52a820456ebd0e618e4c1e7f5454b7d3f6f86c559a3cd98dd94c55aaeed397f3d0cee6b0e37cf6b47d3aedd920a9dea SHA512 ea87b4b45c78888e02d0288dd5844cf2d97a14e251b565c7d6451a0e62fbe0dbef38f46715467af2f869995d6bbc8be61d5b70476a86d607a5bfa27fbaf36e92 DIST linux-6.12.tar.xz 147906904 BLAKE2B b2ec2fc69218cacabbbe49f78384a5d259ca581b717617c12b000b16f4a4c59ee348ea886b37147f5f70fb9a7a01c1e2c8f19021078f6b23f5bc62d1c48d5e5e SHA512 a37b1823df7b4f72542f689b65882634740ba0401a42fdcf6601d9efd2e132e5a7650e70450ba76f6cd1f13ca31180f2ccee9d54fe4df89bc0000ade4380a548 -DIST linux-hardened-v6.12.10-hardened1.patch 89621 BLAKE2B f33abaf900d6401b58bdd712f0ab3069aa9156d2b68666248e53dc7c93a9817d6ee220cb70b47f3b225cfb39d779094c1021f20a93c060933bff94ba0f51a3d1 SHA512 66c70fd5d98a5a603b5661f6a0915fc34544180cededfd02c8f5b374da5af2b1d5a5b2e6dd52aa8aaa8b59f07ae0a4f2adafc8c970a6c08e7cc56289ef0e96bf +DIST linux-hardened-v6.12.12-hardened1.patch 89621 BLAKE2B c4e952725fb88b990568e316b39d98c9bf19ccdc428445c786e0e69e84b1cde50c2f111b01b38bc7265bf3db2def51444e39402ed23998f2fea2885f84fb113c SHA512 0dd84b0442b6e7783dcfd03e2802531e9e45a3c678f9218824899ff88f67c2f527cff1e370938c942d37ba1ad325aefd8cc1598fa115d2088437316ea87ff7e3 diff --git a/sys-kernel/hardened-kernel/files/linux-6.12/1191-bcachefs-cherry-pick-updates-from-bcachefs-for-upstream-5d9ccda.patch b/sys-kernel/hardened-kernel/files/linux-6.12/1191-bcachefs-upd-from-bcachefs-for-upstream-595170d.patch similarity index 90% rename from sys-kernel/hardened-kernel/files/linux-6.12/1191-bcachefs-cherry-pick-updates-from-bcachefs-for-upstream-5d9ccda.patch rename to sys-kernel/hardened-kernel/files/linux-6.12/1191-bcachefs-upd-from-bcachefs-for-upstream-595170d.patch index 697d602..9d73c53 100644 --- a/sys-kernel/hardened-kernel/files/linux-6.12/1191-bcachefs-cherry-pick-updates-from-bcachefs-for-upstream-5d9ccda.patch +++ b/sys-kernel/hardened-kernel/files/linux-6.12/1191-bcachefs-upd-from-bcachefs-for-upstream-595170d.patch @@ -1,23 +1,27 @@ -From 4696907078c0fda263fdbf0e0f68d9579085e03e Mon Sep 17 00:00:00 2001 +From fc593d8ca7362bbfa11f87eb07b691475fa869e4 Mon Sep 17 00:00:00 2001 From: Alexander Miroshnichenko -Date: Mon, 3 Feb 2025 07:16:47 +0300 +Date: Sun, 9 Feb 2025 20:09:20 +0300 Subject: [PATCH] bcachefs: cherry-pick updates from bcachefs-for-upstream - 5d9ccda + 595170d Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Signed-off-by: Alexander Miroshnichenko --- .../filesystems/bcachefs/CodingStyle.rst | 2 +- + .../bcachefs/SubmittingPatches.rst | 98 ++ + Documentation/filesystems/bcachefs/index.rst | 1 + + MAINTAINERS | 1 + fs/bcachefs/Kconfig | 2 +- fs/bcachefs/Makefile | 1 + fs/bcachefs/acl.c | 11 +- - fs/bcachefs/alloc_background.c | 558 +++++------ + fs/bcachefs/alloc_background.c | 601 +++++++------ fs/bcachefs/alloc_background.h | 18 +- fs/bcachefs/alloc_background_format.h | 4 +- - fs/bcachefs/alloc_foreground.c | 315 +++---- - fs/bcachefs/alloc_foreground.h | 21 +- - fs/bcachefs/backpointers.c | 864 +++++++++++------- + fs/bcachefs/alloc_foreground.c | 312 +++---- + fs/bcachefs/alloc_foreground.h | 4 +- + fs/bcachefs/alloc_types.h | 1 + + fs/bcachefs/backpointers.c | 838 +++++++++++------- fs/bcachefs/backpointers.h | 97 +- fs/bcachefs/bbpos.h | 2 +- fs/bcachefs/bcachefs.h | 70 +- @@ -32,12 +36,12 @@ Signed-off-by: Alexander Miroshnichenko fs/bcachefs/btree_gc.h | 4 +- fs/bcachefs/btree_io.c | 225 +++-- fs/bcachefs/btree_io.h | 6 +- - fs/bcachefs/btree_iter.c | 593 +++++++----- + fs/bcachefs/btree_iter.c | 593 ++++++++----- fs/bcachefs/btree_iter.h | 134 ++- fs/bcachefs/btree_journal_iter.c | 237 ++++- fs/bcachefs/btree_journal_iter.h | 22 +- fs/bcachefs/btree_journal_iter_types.h | 36 + - fs/bcachefs/btree_key_cache.c | 73 +- + fs/bcachefs/btree_key_cache.c | 74 +- fs/bcachefs/btree_locking.c | 78 +- fs/bcachefs/btree_locking.h | 50 +- fs/bcachefs/btree_node_scan.c | 153 ++-- @@ -46,29 +50,30 @@ Signed-off-by: Alexander Miroshnichenko fs/bcachefs/btree_types.h | 42 +- fs/bcachefs/btree_update.c | 70 +- fs/bcachefs/btree_update.h | 29 +- - fs/bcachefs/btree_update_interior.c | 313 ++++--- - fs/bcachefs/btree_update_interior.h | 7 +- + fs/bcachefs/btree_update_interior.c | 293 +++--- + fs/bcachefs/btree_update_interior.h | 3 +- fs/bcachefs/btree_write_buffer.c | 83 +- fs/bcachefs/buckets.c | 133 +-- fs/bcachefs/buckets.h | 30 +- fs/bcachefs/buckets_types.h | 2 +- + fs/bcachefs/buckets_waiting_for_journal.c | 12 +- + fs/bcachefs/buckets_waiting_for_journal.h | 4 +- fs/bcachefs/chardev.c | 219 +---- fs/bcachefs/checksum.c | 10 +- fs/bcachefs/checksum.h | 2 +- fs/bcachefs/compress.c | 127 ++- fs/bcachefs/compress.h | 4 +- fs/bcachefs/darray.h | 2 +- - fs/bcachefs/data_update.c | 295 ++++-- - fs/bcachefs/data_update.h | 9 +- + fs/bcachefs/data_update.c | 126 +-- fs/bcachefs/debug.c | 5 +- fs/bcachefs/dirent.c | 10 +- fs/bcachefs/dirent.h | 9 +- - fs/bcachefs/disk_accounting.c | 150 +-- + fs/bcachefs/disk_accounting.c | 150 ++-- fs/bcachefs/disk_accounting.h | 73 +- fs/bcachefs/ec.c | 267 +++--- fs/bcachefs/ec.h | 5 +- fs/bcachefs/ec_format.h | 17 + - fs/bcachefs/errcode.h | 26 +- + fs/bcachefs/errcode.h | 21 +- fs/bcachefs/error.c | 187 ++-- fs/bcachefs/error.h | 58 +- fs/bcachefs/extent_update.c | 4 +- @@ -77,46 +82,45 @@ Signed-off-by: Alexander Miroshnichenko fs/bcachefs/extents_format.h | 15 +- fs/bcachefs/fs-common.c | 119 ++- fs/bcachefs/fs-common.h | 2 + - fs/bcachefs/fs-io-buffered.c | 68 +- - fs/bcachefs/fs-io-direct.c | 25 +- + fs/bcachefs/fs-io-buffered.c | 45 +- + fs/bcachefs/fs-io-direct.c | 5 + fs/bcachefs/fs-io-pagecache.c | 4 +- fs/bcachefs/fs-io.c | 54 +- fs/bcachefs/fs-ioctl.c | 7 +- - fs/bcachefs/fs.c | 101 +- + fs/bcachefs/fs.c | 101 ++- fs/bcachefs/fs.h | 1 + fs/bcachefs/fsck.c | 772 ++++++++++------ fs/bcachefs/fsck.h | 11 + fs/bcachefs/inode.c | 169 ++-- - fs/bcachefs/inode.h | 43 +- + fs/bcachefs/inode.h | 45 +- fs/bcachefs/inode_format.h | 15 +- fs/bcachefs/io_misc.c | 22 +- - fs/bcachefs/io_read.c | 726 ++++++++------- - fs/bcachefs/io_read.h | 98 +- - fs/bcachefs/io_write.c | 184 ++-- - fs/bcachefs/io_write.h | 31 +- - fs/bcachefs/io_write_types.h | 2 +- - fs/bcachefs/journal.c | 252 ++--- - fs/bcachefs/journal.h | 18 +- + fs/bcachefs/io_read.c | 259 +++--- + fs/bcachefs/io_read.h | 28 +- + fs/bcachefs/io_write.c | 104 ++- + fs/bcachefs/io_write.h | 2 + + fs/bcachefs/journal.c | 266 +++--- + fs/bcachefs/journal.h | 19 +- fs/bcachefs/journal_io.c | 223 +++-- fs/bcachefs/journal_io.h | 2 +- fs/bcachefs/journal_reclaim.c | 161 +++- fs/bcachefs/journal_reclaim.h | 3 + - fs/bcachefs/journal_types.h | 18 +- + fs/bcachefs/journal_types.h | 19 +- fs/bcachefs/logged_ops.c | 11 +- fs/bcachefs/logged_ops_format.h | 5 + fs/bcachefs/lru.c | 4 +- fs/bcachefs/lru.h | 2 +- - fs/bcachefs/move.c | 248 ++--- + fs/bcachefs/move.c | 184 ++-- fs/bcachefs/move.h | 5 +- fs/bcachefs/movinggc.c | 17 +- fs/bcachefs/opts.c | 26 +- - fs/bcachefs/opts.h | 61 +- + fs/bcachefs/opts.h | 47 +- fs/bcachefs/printbuf.h | 15 +- fs/bcachefs/quota.c | 2 +- fs/bcachefs/quota.h | 4 +- fs/bcachefs/rcu_pending.c | 38 +- - fs/bcachefs/rebalance.c | 270 +++++- - fs/bcachefs/rebalance.h | 10 + + fs/bcachefs/rebalance.c | 264 +++++- + fs/bcachefs/rebalance.h | 30 + fs/bcachefs/rebalance_format.h | 53 ++ fs/bcachefs/rebalance_types.h | 2 - fs/bcachefs/recovery.c | 212 +++-- @@ -124,29 +128,29 @@ Signed-off-by: Alexander Miroshnichenko fs/bcachefs/recovery_passes.c | 112 ++- fs/bcachefs/recovery_passes.h | 1 + fs/bcachefs/recovery_passes_types.h | 92 +- - fs/bcachefs/reflink.c | 496 +++++++--- + fs/bcachefs/reflink.c | 498 ++++++++--- fs/bcachefs/reflink.h | 20 +- fs/bcachefs/reflink_format.h | 7 +- fs/bcachefs/sb-clean.c | 6 +- fs/bcachefs/sb-counters_format.h | 165 ++-- fs/bcachefs/sb-downgrade.c | 28 +- - fs/bcachefs/sb-errors_format.h | 56 +- + fs/bcachefs/sb-errors_format.h | 60 +- fs/bcachefs/six.c | 27 +- fs/bcachefs/six.h | 1 + fs/bcachefs/snapshot.c | 515 +++++------ fs/bcachefs/snapshot.h | 17 +- fs/bcachefs/str_hash.c | 295 ++++++ fs/bcachefs/str_hash.h | 28 +- - fs/bcachefs/subvolume.c | 68 +- + fs/bcachefs/subvolume.c | 73 +- fs/bcachefs/subvolume.h | 19 +- fs/bcachefs/subvolume_types.h | 2 +- fs/bcachefs/super-io.c | 83 +- fs/bcachefs/super-io.h | 21 +- - fs/bcachefs/super.c | 54 +- - fs/bcachefs/super.h | 10 - + fs/bcachefs/super.c | 65 +- + fs/bcachefs/super.h | 11 +- fs/bcachefs/sysfs.c | 60 +- fs/bcachefs/tests.c | 26 +- - fs/bcachefs/trace.h | 103 ++- + fs/bcachefs/trace.h | 117 ++- fs/bcachefs/util.h | 32 + fs/bcachefs/varint.c | 5 +- fs/bcachefs/xattr.c | 13 +- @@ -154,7 +158,8 @@ Signed-off-by: Alexander Miroshnichenko fs/fs_parser.c | 3 +- include/linux/fs_parser.h | 2 + include/linux/min_heap.h | 4 +- - 146 files changed, 7996 insertions(+), 5234 deletions(-) + 150 files changed, 7624 insertions(+), 4814 deletions(-) + create mode 100644 Documentation/filesystems/bcachefs/SubmittingPatches.rst create mode 100644 fs/bcachefs/btree_journal_iter_types.h create mode 100644 fs/bcachefs/rebalance_format.h create mode 100644 fs/bcachefs/str_hash.c @@ -169,6 +174,132 @@ index 01de555e21d8..b29562a6bf55 100644 organized into small clean and tidy modules, with clear and descriptive names -for functions and variable, where every line of code has a clear purpose. +for functions and variables, where every line of code has a clear purpose. +diff --git a/Documentation/filesystems/bcachefs/SubmittingPatches.rst b/Documentation/filesystems/bcachefs/SubmittingPatches.rst +new file mode 100644 +index 000000000000..026b12ae0d6a +--- /dev/null ++++ b/Documentation/filesystems/bcachefs/SubmittingPatches.rst +@@ -0,0 +1,98 @@ ++Submitting patches to bcachefs: ++=============================== ++ ++Patches must be tested before being submitted, either with the xfstests suite ++[0], or the full bcachefs test suite in ktest [1], depending on what's being ++touched. Note that ktest wraps xfstests and will be an easier method to running ++it for most users; it includes single-command wrappers for all the mainstream ++in-kernel local filesystems. ++ ++Patches will undergo more testing after being merged (including ++lockdep/kasan/preempt/etc. variants), these are not generally required to be ++run by the submitter - but do put some thought into what you're changing and ++which tests might be relevant, e.g. are you dealing with tricky memory layout ++work? kasan, are you doing locking work? then lockdep; and ktest includes ++single-command variants for the debug build types you'll most likely need. ++ ++The exception to this rule is incomplete WIP/RFC patches: if you're working on ++something nontrivial, it's encouraged to send out a WIP patch to let people ++know what you're doing and make sure you're on the right track. Just make sure ++it includes a brief note as to what's done and what's incomplete, to avoid ++confusion. ++ ++Rigorous checkpatch.pl adherence is not required (many of its warnings are ++considered out of date), but try not to deviate too much without reason. ++ ++Focus on writing code that reads well and is organized well; code should be ++aesthetically pleasing. ++ ++CI: ++=== ++ ++Instead of running your tests locally, when running the full test suite it's ++prefereable to let a server farm do it in parallel, and then have the results ++in a nice test dashboard (which can tell you which failures are new, and ++presents results in a git log view, avoiding the need for most bisecting). ++ ++That exists [2], and community members may request an account. If you work for ++a big tech company, you'll need to help out with server costs to get access - ++but the CI is not restricted to running bcachefs tests: it runs any ktest test ++(which generally makes it easy to wrap other tests that can run in qemu). ++ ++Other things to think about: ++============================ ++ ++- How will we debug this code? Is there sufficient introspection to diagnose ++ when something starts acting wonky on a user machine? ++ ++ We don't necessarily need every single field of every data structure visible ++ with introspection, but having the important fields of all the core data ++ types wired up makes debugging drastically easier - a bit of thoughtful ++ foresight greatly reduces the need to have people build custom kernels with ++ debug patches. ++ ++ More broadly, think about all the debug tooling that might be needed. ++ ++- Does it make the codebase more or less of a mess? Can we also try to do some ++ organizing, too? ++ ++- Do new tests need to be written? New assertions? How do we know and verify ++ that the code is correct, and what happens if something goes wrong? ++ ++ We don't yet have automated code coverage analysis or easy fault injection - ++ but for now, pretend we did and ask what they might tell us. ++ ++ Assertions are hugely important, given that we don't yet have a systems ++ language that can do ergonomic embedded correctness proofs. Hitting an assert ++ in testing is much better than wandering off into undefined behaviour la-la ++ land - use them. Use them judiciously, and not as a replacement for proper ++ error handling, but use them. ++ ++- Does it need to be performance tested? Should we add new peformance counters? ++ ++ bcachefs has a set of persistent runtime counters which can be viewed with ++ the 'bcachefs fs top' command; this should give users a basic idea of what ++ their filesystem is currently doing. If you're doing a new feature or looking ++ at old code, think if anything should be added. ++ ++- If it's a new on disk format feature - have upgrades and downgrades been ++ tested? (Automated tests exists but aren't in the CI, due to the hassle of ++ disk image management; coordinate to have them run.) ++ ++Mailing list, IRC: ++================== ++ ++Patches should hit the list [3], but much discussion and code review happens on ++IRC as well [4]; many people appreciate the more conversational approach and ++quicker feedback. ++ ++Additionally, we have a lively user community doing excellent QA work, which ++exists primarily on IRC. Please make use of that resource; user feedback is ++important for any nontrivial feature, and documenting it in commit messages ++would be a good idea. ++ ++[0]: git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git ++[1]: https://evilpiepirate.org/git/ktest.git/ ++[2]: https://evilpiepirate.org/~testdashboard/ci/ ++[3]: linux-bcachefs@vger.kernel.org ++[4]: irc.oftc.net#bcache, #bcachefs-dev +diff --git a/Documentation/filesystems/bcachefs/index.rst b/Documentation/filesystems/bcachefs/index.rst +index 95fc4b90739e..7db4d7ceab58 100644 +--- a/Documentation/filesystems/bcachefs/index.rst ++++ b/Documentation/filesystems/bcachefs/index.rst +@@ -9,4 +9,5 @@ bcachefs Documentation + :numbered: + + CodingStyle ++ SubmittingPatches + errorcodes +diff --git a/MAINTAINERS b/MAINTAINERS +index 6bb4ec0c162a..1a4d3e3b14fd 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3848,6 +3848,7 @@ M: Kent Overstreet + L: linux-bcachefs@vger.kernel.org + S: Supported + C: irc://irc.oftc.net/bcache ++P: Documentation/filesystems/bcachefs/SubmittingPatches.rst + T: git https://evilpiepirate.org/git/bcachefs.git + F: fs/bcachefs/ + F: Documentation/filesystems/bcachefs/ diff --git a/fs/bcachefs/Kconfig b/fs/bcachefs/Kconfig index 5bac803ea367..e8549d04dcb8 100644 --- a/fs/bcachefs/Kconfig @@ -234,7 +365,7 @@ index 87f1be9d4db4..99487727ae64 100644 entry->e_tag = cpu_to_le16(acl_e->e_tag); diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c -index c84a91572a1d..fc2ef33b67b3 100644 +index c84a91572a1d..3ea809990ef1 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -198,7 +198,7 @@ static unsigned bch_alloc_v1_val_u64s(const struct bch_alloc *a) @@ -853,7 +984,14 @@ index c84a91572a1d..fc2ef33b67b3 100644 if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) { ret = 0; continue; -@@ -1757,7 +1810,8 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, +@@ -1750,14 +1803,14 @@ struct discard_buckets_state { + u64 open; + u64 need_journal_commit; + u64 discarded; +- u64 need_journal_commit_this_dev; + }; + + static int bch2_discard_one_bucket(struct btree_trans *trans, struct bch_dev *ca, struct btree_iter *need_discard_iter, struct bpos *discard_pos_done, @@ -863,7 +1001,24 @@ index c84a91572a1d..fc2ef33b67b3 100644 { struct bch_fs *c = trans->c; struct bpos pos = need_discard_iter->pos; -@@ -1793,44 +1847,23 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, +@@ -1773,11 +1826,11 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, + goto out; + } + +- if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, +- c->journal.flushed_seq_ondisk, +- pos.inode, pos.offset)) { +- s->need_journal_commit++; +- s->need_journal_commit_this_dev++; ++ u64 seq_ready = bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal, ++ pos.inode, pos.offset); ++ if (seq_ready > c->journal.flushed_seq_ondisk) { ++ if (seq_ready > c->journal.flushing_seq) ++ s->need_journal_commit++; + goto out; + } + +@@ -1793,80 +1846,64 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, if (ret) goto out; @@ -916,17 +1071,38 @@ index c84a91572a1d..fc2ef33b67b3 100644 + discard_locked = true; + } - if (!bkey_eq(*discard_pos_done, iter.pos) && - ca->mi.discard && !c->opts.nochanges) { -@@ -1844,6 +1877,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, - ca->mi.bucket_size, - GFP_KERNEL); - *discard_pos_done = iter.pos; +- if (!bkey_eq(*discard_pos_done, iter.pos) && +- ca->mi.discard && !c->opts.nochanges) { +- /* +- * This works without any other locks because this is the only +- * thread that removes items from the need_discard tree +- */ +- bch2_trans_unlock_long(trans); +- blkdev_issue_discard(ca->disk_sb.bdev, +- k.k->p.offset * ca->mi.bucket_size, +- ca->mi.bucket_size, +- GFP_KERNEL); ++ if (!bkey_eq(*discard_pos_done, iter.pos)) { + s->discarded++; + *discard_pos_done = iter.pos; - ret = bch2_trans_relock_notrace(trans); - if (ret) -@@ -1851,22 +1885,25 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, +- ret = bch2_trans_relock_notrace(trans); +- if (ret) +- goto out; ++ if (ca->mi.discard && !c->opts.nochanges) { ++ /* ++ * This works without any other locks because this is the only ++ * thread that removes items from the need_discard tree ++ */ ++ bch2_trans_unlock_long(trans); ++ blkdev_issue_discard(ca->disk_sb.bdev, ++ k.k->p.offset * ca->mi.bucket_size, ++ ca->mi.bucket_size, ++ GFP_KERNEL); ++ ret = bch2_trans_relock_notrace(trans); ++ if (ret) ++ goto out; ++ } } SET_BCH_ALLOC_V4_NEED_DISCARD(&a->v, false); @@ -959,7 +1135,7 @@ index c84a91572a1d..fc2ef33b67b3 100644 bch2_trans_iter_exit(trans, &iter); printbuf_exit(&buf); return ret; -@@ -1886,11 +1923,11 @@ static void bch2_do_discards_work(struct work_struct *work) +@@ -1886,11 +1923,14 @@ static void bch2_do_discards_work(struct work_struct *work) * successful commit: */ ret = bch2_trans_run(c, @@ -970,10 +1146,13 @@ index c84a91572a1d..fc2ef33b67b3 100644 POS(ca->dev_idx, U64_MAX), 0, k, - bch2_discard_one_bucket(trans, ca, &iter, &discard_pos_done, &s))); + bch2_discard_one_bucket(trans, ca, &iter, &discard_pos_done, &s, false))); ++ ++ if (s.need_journal_commit > dev_buckets_available(ca, BCH_WATERMARK_normal)) ++ bch2_journal_flush_async(&c->journal, NULL); trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); -@@ -1923,27 +1960,29 @@ void bch2_do_discards(struct bch_fs *c) +@@ -1923,27 +1963,29 @@ void bch2_do_discards(struct bch_fs *c) bch2_dev_do_discards(ca); } @@ -1020,7 +1199,7 @@ index c84a91572a1d..fc2ef33b67b3 100644 return ret; } -@@ -1951,6 +1990,10 @@ static void bch2_do_discards_fast_work(struct work_struct *work) +@@ -1951,6 +1993,10 @@ static void bch2_do_discards_fast_work(struct work_struct *work) { struct bch_dev *ca = container_of(work, struct bch_dev, discard_fast_work); struct bch_fs *c = ca->fs; @@ -1031,7 +1210,7 @@ index c84a91572a1d..fc2ef33b67b3 100644 while (1) { bool got_bucket = false; -@@ -1971,16 +2014,8 @@ static void bch2_do_discards_fast_work(struct work_struct *work) +@@ -1971,16 +2017,8 @@ static void bch2_do_discards_fast_work(struct work_struct *work) if (!got_bucket) break; @@ -1050,17 +1229,17 @@ index c84a91572a1d..fc2ef33b67b3 100644 bch_err_fn(c, ret); discard_in_flight_remove(ca, bucket); -@@ -1989,6 +2024,9 @@ static void bch2_do_discards_fast_work(struct work_struct *work) +@@ -1989,6 +2027,9 @@ static void bch2_do_discards_fast_work(struct work_struct *work) break; } -+ trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); ++ trace_discard_buckets_fast(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); + + bch2_trans_put(trans); percpu_ref_put(&ca->io_ref); bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast); } -@@ -2030,8 +2068,11 @@ static int invalidate_one_bucket(struct btree_trans *trans, +@@ -2030,8 +2071,11 @@ static int invalidate_one_bucket(struct btree_trans *trans, return 1; if (!bch2_dev_bucket_exists(c, bucket)) { @@ -1074,7 +1253,7 @@ index c84a91572a1d..fc2ef33b67b3 100644 } if (bch2_bucket_is_open_safe(c, bucket.inode, bucket.offset)) -@@ -2072,28 +2113,9 @@ static int invalidate_one_bucket(struct btree_trans *trans, +@@ -2072,28 +2116,9 @@ static int invalidate_one_bucket(struct btree_trans *trans, trace_and_count(c, bucket_invalidate, c, bucket.inode, bucket.offset, cached_sectors); --*nr_to_invalidate; out: @@ -1104,7 +1283,7 @@ index c84a91572a1d..fc2ef33b67b3 100644 } static struct bkey_s_c next_lru_key(struct btree_trans *trans, struct btree_iter *iter, -@@ -2101,7 +2123,7 @@ static struct bkey_s_c next_lru_key(struct btree_trans *trans, struct btree_iter +@@ -2101,7 +2126,7 @@ static struct bkey_s_c next_lru_key(struct btree_trans *trans, struct btree_iter { struct bkey_s_c k; again: @@ -1186,7 +1365,7 @@ index befdaa95c515..740238369a5a 100644 __u32 pad; } __packed __aligned(8); diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c -index 372178c8d416..ecd14962ab01 100644 +index 372178c8d416..5a781fb4c794 100644 --- a/fs/bcachefs/alloc_foreground.c +++ b/fs/bcachefs/alloc_foreground.c @@ -107,14 +107,10 @@ void __bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob) @@ -1219,98 +1398,92 @@ index 372178c8d416..ecd14962ab01 100644 static void open_bucket_free_unused(struct bch_fs *c, struct open_bucket *ob) { BUG_ON(c->open_buckets_partial_nr >= -@@ -175,70 +179,46 @@ static void open_bucket_free_unused(struct bch_fs *c, struct open_bucket *ob) +@@ -175,20 +179,6 @@ static void open_bucket_free_unused(struct bch_fs *c, struct open_bucket *ob) closure_wake_up(&c->freelist_wait); } -/* _only_ for allocating the journal on a new device: */ -long bch2_bucket_alloc_new_fs(struct bch_dev *ca) -+static inline bool may_alloc_bucket(struct bch_fs *c, -+ struct bpos bucket, -+ struct bucket_alloc_state *s) - { +-{ - while (ca->new_fs_bucket_idx < ca->mi.nbuckets) { - u64 b = ca->new_fs_bucket_idx++; - - if (!is_superblock_bucket(ca, b) && - (!ca->buckets_nouse || !test_bit(b, ca->buckets_nouse))) - return b; -+ if (bch2_bucket_is_open(c, bucket.inode, bucket.offset)) { -+ s->skipped_open++; -+ return false; - } - +- } +- - return -1; -} -+ if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, -+ c->journal.flushed_seq_ondisk, bucket.inode, bucket.offset)) { -+ s->skipped_need_journal_commit++; -+ return false; -+ } - --static inline unsigned open_buckets_reserved(enum bch_watermark watermark) --{ -- switch (watermark) { -- case BCH_WATERMARK_interior_updates: -- return 0; -- case BCH_WATERMARK_reclaim: -- return OPEN_BUCKETS_COUNT / 6; -- case BCH_WATERMARK_btree: -- case BCH_WATERMARK_btree_copygc: -- return OPEN_BUCKETS_COUNT / 4; -- case BCH_WATERMARK_copygc: -- return OPEN_BUCKETS_COUNT / 3; -- default: -- return OPEN_BUCKETS_COUNT / 2; -+ if (bch2_bucket_nocow_is_locked(&c->nocow_locks, bucket)) { -+ s->skipped_nocow++; -+ return false; +- + static inline unsigned open_buckets_reserved(enum bch_watermark watermark) + { + switch (watermark) { +@@ -206,33 +196,44 @@ static inline unsigned open_buckets_reserved(enum bch_watermark watermark) } -+ -+ return true; } - static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev *ca, +-static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev *ca, - u64 bucket, -+ u64 bucket, u8 gen, - enum bch_watermark watermark, +- enum bch_watermark watermark, - const struct bch_alloc_v4 *a, - struct bucket_alloc_state *s, - struct closure *cl) +- struct bucket_alloc_state *s, +- struct closure *cl) ++static inline bool may_alloc_bucket(struct bch_fs *c, ++ struct bpos bucket, ++ struct bucket_alloc_state *s) { - struct open_bucket *ob; +- +- if (unlikely(ca->buckets_nouse && test_bit(bucket, ca->buckets_nouse))) { +- s->skipped_nouse++; +- return NULL; +- } +- +- if (bch2_bucket_is_open(c, ca->dev_idx, bucket)) { ++ if (bch2_bucket_is_open(c, bucket.inode, bucket.offset)) { + s->skipped_open++; +- return NULL; ++ return false; + } + +- if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, +- c->journal.flushed_seq_ondisk, ca->dev_idx, bucket)) { ++ u64 journal_seq_ready = ++ bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal, ++ bucket.inode, bucket.offset); ++ if (journal_seq_ready > c->journal.flushed_seq_ondisk) { ++ if (journal_seq_ready > c->journal.flushing_seq) ++ s->need_journal_commit++; + s->skipped_need_journal_commit++; +- return NULL; ++ return false; + } + +- if (bch2_bucket_nocow_is_locked(&c->nocow_locks, POS(ca->dev_idx, bucket))) { ++ if (bch2_bucket_nocow_is_locked(&c->nocow_locks, bucket)) { + s->skipped_nocow++; ++ return false; ++ } ++ ++ return true; ++} ++ ++static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev *ca, ++ u64 bucket, u8 gen, ++ enum bch_watermark watermark, ++ struct bucket_alloc_state *s, ++ struct closure *cl) ++{ + if (unlikely(is_superblock_bucket(c, ca, bucket))) + return NULL; - - if (unlikely(ca->buckets_nouse && test_bit(bucket, ca->buckets_nouse))) { - s->skipped_nouse++; ++ ++ if (unlikely(ca->buckets_nouse && test_bit(bucket, ca->buckets_nouse))) { ++ s->skipped_nouse++; return NULL; } -- if (bch2_bucket_is_open(c, ca->dev_idx, bucket)) { -- s->skipped_open++; -- return NULL; -- } -- -- if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, -- c->journal.flushed_seq_ondisk, ca->dev_idx, bucket)) { -- s->skipped_need_journal_commit++; -- return NULL; -- } -- -- if (bch2_bucket_nocow_is_locked(&c->nocow_locks, POS(ca->dev_idx, bucket))) { -- s->skipped_nocow++; -- return NULL; -- } -- - spin_lock(&c->freelist_lock); - -- if (unlikely(c->open_buckets_nr_free <= open_buckets_reserved(watermark))) { -+ if (unlikely(c->open_buckets_nr_free <= bch2_open_buckets_reserved(watermark))) { - if (cl) - closure_wait(&c->open_buckets_wait, cl); - -@@ -254,14 +234,13 @@ static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev * +@@ -254,14 +255,13 @@ static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev * return NULL; } @@ -1327,7 +1500,7 @@ index 372178c8d416..ecd14962ab01 100644 ob->bucket = bucket; spin_unlock(&ob->lock); -@@ -276,111 +255,29 @@ static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev * +@@ -276,111 +276,29 @@ static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev * } static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bch_dev *ca, @@ -1358,7 +1531,8 @@ index 372178c8d416..ecd14962ab01 100644 - ob = ERR_PTR(-EIO); - goto err; - } -- ++ u64 b = freespace_iter->pos.offset & ~(~0ULL << 56); + - k = bch2_bkey_get_iter(trans, &iter, - BTREE_ID_alloc, POS(ca->dev_idx, b), - BTREE_ITER_cached); @@ -1402,8 +1576,7 @@ index 372178c8d416..ecd14962ab01 100644 - if (c->curr_recovery_pass <= BCH_RECOVERY_PASS_check_extents_to_backpointers) { - struct bch_backpointer bp; - struct bpos bp_pos = POS_MIN; -+ u64 b = freespace_iter->pos.offset & ~(~0ULL << 56); - +- - ret = bch2_get_next_backpointer(trans, ca, POS(ca->dev_idx, b), -1, - &bp_pos, &bp, - BTREE_ITER_nopreserve); @@ -1451,7 +1624,7 @@ index 372178c8d416..ecd14962ab01 100644 */ static noinline struct open_bucket * bch2_bucket_alloc_early(struct btree_trans *trans, -@@ -389,10 +286,11 @@ bch2_bucket_alloc_early(struct btree_trans *trans, +@@ -389,10 +307,11 @@ bch2_bucket_alloc_early(struct btree_trans *trans, struct bucket_alloc_state *s, struct closure *cl) { @@ -1464,7 +1637,7 @@ index 372178c8d416..ecd14962ab01 100644 u64 *dev_alloc_cursor = &ca->alloc_cursor[s->btree_bitmap]; u64 alloc_start = max(first_bucket, *dev_alloc_cursor); u64 alloc_cursor = alloc_start; -@@ -415,10 +313,6 @@ bch2_bucket_alloc_early(struct btree_trans *trans, +@@ -415,10 +334,6 @@ bch2_bucket_alloc_early(struct btree_trans *trans, if (bkey_ge(k.k->p, POS(ca->dev_idx, ca->mi.nbuckets))) break; @@ -1475,7 +1648,7 @@ index 372178c8d416..ecd14962ab01 100644 if (s->btree_bitmap != BTREE_BITMAP_ANY && s->btree_bitmap != bch2_dev_btree_bitmap_marked_sectors(ca, bucket_to_sector(ca, bucket), ca->mi.bucket_size)) { -@@ -452,7 +346,10 @@ bch2_bucket_alloc_early(struct btree_trans *trans, +@@ -452,7 +367,10 @@ bch2_bucket_alloc_early(struct btree_trans *trans, s->buckets_seen++; @@ -1487,7 +1660,7 @@ index 372178c8d416..ecd14962ab01 100644 next: bch2_set_btree_iter_dontneed(&citer); bch2_trans_iter_exit(trans, &citer); -@@ -489,20 +386,21 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, +@@ -489,20 +407,21 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, u64 alloc_start = max_t(u64, ca->mi.first_bucket, READ_ONCE(*dev_alloc_cursor)); u64 alloc_cursor = alloc_start; int ret; @@ -1519,7 +1692,7 @@ index 372178c8d416..ecd14962ab01 100644 if (s->btree_bitmap != BTREE_BITMAP_ANY && s->btree_bitmap != bch2_dev_btree_bitmap_marked_sectors(ca, bucket_to_sector(ca, bucket), ca->mi.bucket_size)) { -@@ -511,32 +409,36 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, +@@ -511,32 +430,36 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, goto fail; bucket = sector_to_bucket(ca, @@ -1566,7 +1739,7 @@ index 372178c8d416..ecd14962ab01 100644 ob = ERR_PTR(ret); if (!ob && alloc_start > ca->mi.first_bucket) { -@@ -544,8 +446,6 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, +@@ -544,8 +467,6 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, goto again; } @@ -1575,7 +1748,7 @@ index 372178c8d416..ecd14962ab01 100644 return ob; } -@@ -595,6 +495,7 @@ static noinline void trace_bucket_alloc2(struct bch_fs *c, struct bch_dev *ca, +@@ -595,6 +516,7 @@ static noinline void trace_bucket_alloc2(struct bch_fs *c, struct bch_dev *ca, * @watermark: how important is this allocation? * @data_type: BCH_DATA_journal, btree, user... * @cl: if not NULL, closure to be used to wait if buckets not available @@ -1583,7 +1756,7 @@ index 372178c8d416..ecd14962ab01 100644 * @usage: for secondarily also returning the current device usage * * Returns: an open_bucket on success, or an ERR_PTR() on failure. -@@ -629,6 +530,10 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, +@@ -629,6 +551,10 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, bch2_dev_do_invalidates(ca); if (!avail) { @@ -1594,7 +1767,16 @@ index 372178c8d416..ecd14962ab01 100644 if (cl && !waiting) { closure_wait(&c->freelist_wait, cl); waiting = true; -@@ -711,9 +616,9 @@ struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *c, +@@ -648,7 +574,7 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, + ? bch2_bucket_alloc_freelist(trans, ca, watermark, &s, cl) + : bch2_bucket_alloc_early(trans, ca, watermark, &s, cl); + +- if (s.skipped_need_journal_commit * 2 > avail) ++ if (s.need_journal_commit * 2 > avail) + bch2_journal_flush_async(&c->journal, NULL); + + if (!ob && s.btree_bitmap != BTREE_BITMAP_ANY) { +@@ -711,9 +637,9 @@ struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *c, unsigned i; for_each_set_bit(i, devs->d, BCH_SB_MEMBERS_MAX) @@ -1606,7 +1788,7 @@ index 372178c8d416..ecd14962ab01 100644 return ret; } -@@ -785,18 +690,13 @@ int bch2_bucket_alloc_set_trans(struct btree_trans *trans, +@@ -785,18 +711,13 @@ int bch2_bucket_alloc_set_trans(struct btree_trans *trans, struct closure *cl) { struct bch_fs *c = trans->c; @@ -1628,7 +1810,7 @@ index 372178c8d416..ecd14962ab01 100644 if (!ca) continue; -@@ -805,8 +705,9 @@ int bch2_bucket_alloc_set_trans(struct btree_trans *trans, +@@ -805,8 +726,9 @@ int bch2_bucket_alloc_set_trans(struct btree_trans *trans, continue; } @@ -1636,11 +1818,11 @@ index 372178c8d416..ecd14962ab01 100644 - cl, flags & BCH_WRITE_ALLOC_NOWAIT, &usage); + struct bch_dev_usage usage; + struct open_bucket *ob = bch2_bucket_alloc_trans(trans, ca, watermark, data_type, -+ cl, flags & BCH_WRITE_alloc_nowait, &usage); ++ cl, flags & BCH_WRITE_ALLOC_NOWAIT, &usage); if (!IS_ERR(ob)) bch2_dev_stripe_increment_inlined(ca, stripe, &usage); bch2_dev_put(ca); -@@ -850,10 +751,6 @@ static int bucket_alloc_from_stripe(struct btree_trans *trans, +@@ -850,10 +772,6 @@ static int bucket_alloc_from_stripe(struct btree_trans *trans, struct closure *cl) { struct bch_fs *c = trans->c; @@ -1651,7 +1833,7 @@ index 372178c8d416..ecd14962ab01 100644 int ret = 0; if (nr_replicas < 2) -@@ -862,34 +759,32 @@ static int bucket_alloc_from_stripe(struct btree_trans *trans, +@@ -862,34 +780,32 @@ static int bucket_alloc_from_stripe(struct btree_trans *trans, if (ec_open_bucket(c, ptrs)) return 0; @@ -1703,26 +1885,8 @@ index 372178c8d416..ecd14962ab01 100644 bch2_ec_stripe_head_put(c, h); return ret; } -@@ -1420,7 +1315,7 @@ int bch2_alloc_sectors_start_trans(struct btree_trans *trans, - if (wp->data_type != BCH_DATA_user) - have_cache = true; - -- if (target && !(flags & BCH_WRITE_ONLY_SPECIFIED_DEVS)) { -+ if (target && !(flags & BCH_WRITE_only_specified_devs)) { - ret = open_bucket_add_buckets(trans, &ptrs, wp, devs_have, - target, erasure_code, - nr_replicas, &nr_effective, -@@ -1510,7 +1405,7 @@ int bch2_alloc_sectors_start_trans(struct btree_trans *trans, - if (cl && bch2_err_matches(ret, BCH_ERR_open_buckets_empty)) - ret = -BCH_ERR_bucket_alloc_blocked; - -- if (cl && !(flags & BCH_WRITE_ALLOC_NOWAIT) && -+ if (cl && !(flags & BCH_WRITE_alloc_nowait) && - bch2_err_matches(ret, BCH_ERR_freelist_empty)) - ret = -BCH_ERR_bucket_alloc_blocked; - diff --git a/fs/bcachefs/alloc_foreground.h b/fs/bcachefs/alloc_foreground.h -index 1a16fd5bd4f8..baf5dc163c8a 100644 +index 1a16fd5bd4f8..f25481a0d1a0 100644 --- a/fs/bcachefs/alloc_foreground.h +++ b/fs/bcachefs/alloc_foreground.h @@ -20,7 +20,7 @@ void bch2_reset_alloc_cursors(struct bch_fs *); @@ -1734,7 +1898,7 @@ index 1a16fd5bd4f8..baf5dc163c8a 100644 }; struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *, -@@ -28,13 +28,28 @@ struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *, +@@ -28,8 +28,6 @@ struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *, struct bch_devs_mask *); void bch2_dev_stripe_increment(struct bch_dev *, struct dev_stripe_state *); @@ -1743,30 +1907,20 @@ index 1a16fd5bd4f8..baf5dc163c8a 100644 static inline struct bch_dev *ob_dev(struct bch_fs *c, struct open_bucket *ob) { return bch2_dev_have_ref(c, ob->dev); - } - -+static inline unsigned bch2_open_buckets_reserved(enum bch_watermark watermark) -+{ -+ switch (watermark) { -+ case BCH_WATERMARK_interior_updates: -+ return 0; -+ case BCH_WATERMARK_reclaim: -+ return OPEN_BUCKETS_COUNT / 6; -+ case BCH_WATERMARK_btree: -+ case BCH_WATERMARK_btree_copygc: -+ return OPEN_BUCKETS_COUNT / 4; -+ case BCH_WATERMARK_copygc: -+ return OPEN_BUCKETS_COUNT / 3; -+ default: -+ return OPEN_BUCKETS_COUNT / 2; -+ } -+} -+ - struct open_bucket *bch2_bucket_alloc(struct bch_fs *, struct bch_dev *, - enum bch_watermark, enum bch_data_type, - struct closure *); +diff --git a/fs/bcachefs/alloc_types.h b/fs/bcachefs/alloc_types.h +index 9bbb28e90b93..4aa8ee026cb8 100644 +--- a/fs/bcachefs/alloc_types.h ++++ b/fs/bcachefs/alloc_types.h +@@ -18,6 +18,7 @@ struct bucket_alloc_state { + u64 buckets_seen; + u64 skipped_open; + u64 skipped_need_journal_commit; ++ u64 need_journal_commit; + u64 skipped_nocow; + u64 skipped_nouse; + u64 skipped_mi_btree_bitmap; diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c -index 654a58132a4d..655be2332742 100644 +index 654a58132a4d..ebeb6a5ff9d2 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -14,42 +14,8 @@ @@ -1949,7 +2103,7 @@ index 654a58132a4d..655be2332742 100644 prt_newline(&buf); prt_printf(&buf, "for "); -@@ -167,230 +136,188 @@ static noinline int backpointer_mod_err(struct btree_trans *trans, +@@ -167,161 +136,118 @@ static noinline int backpointer_mod_err(struct btree_trans *trans, } int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans, @@ -2157,56 +2311,40 @@ index 654a58132a4d..655be2332742 100644 { - if (likely(!bp.level)) { - struct bch_fs *c = trans->c; -- ++ struct bch_fs *c = trans->c; + - struct bpos bucket; - if (!bp_pos_to_bucket_nodev(c, bp_pos, &bucket)) - return bkey_s_c_err(-EIO); -- -- bch2_trans_node_iter_init(trans, iter, -- bp.btree_id, -- bp.pos, -- 0, 0, -- iter_flags); -- struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); -- if (bkey_err(k)) { -- bch2_trans_iter_exit(trans, iter); -- return k; -- } -+ struct bch_fs *c = trans->c; - -- if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp)) -- return k; + if (unlikely(bp.v->btree_id >= btree_id_nr_alive(c))) + return bkey_s_c_null; -+ bch2_trans_node_iter_init(trans, iter, -+ bp.v->btree_id, -+ bp.v->pos, -+ 0, -+ bp.v->level, -+ iter_flags); -+ struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); -+ if (bkey_err(k)) { ++ if (likely(!bp.v->level)) { + bch2_trans_node_iter_init(trans, iter, +- bp.btree_id, +- bp.pos, ++ bp.v->btree_id, ++ bp.v->pos, + 0, 0, + iter_flags); + struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); +@@ -330,67 +256,64 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, + return k; + } + +- if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp)) ++ if (k.k && ++ extent_matches_bp(c, bp.v->btree_id, bp.v->level, k, bp)) + return k; + bch2_trans_iter_exit(trans, iter); - backpointer_not_found(trans, bp_pos, bp, k); - return bkey_s_c_null; -+ return k; -+ } -+ -+ if (k.k && -+ extent_matches_bp(c, bp.v->btree_id, bp.v->level, k, bp)) -+ return k; -+ -+ bch2_trans_iter_exit(trans, iter); -+ -+ if (!bp.v->level) { + int ret = backpointer_target_not_found(trans, bp, k, last_flushed); + return ret ? bkey_s_c_err(ret) : bkey_s_c_null; } else { - struct btree *b = bch2_backpointer_get_node(trans, iter, bp_pos, bp); + struct btree *b = bch2_backpointer_get_node(trans, bp, iter, last_flushed); -+ if (b == ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node)) -+ return bkey_s_c_null; + if (IS_ERR_OR_NULL(b)) + return ((struct bkey_s_c) { .k = ERR_CAST(b) }); @@ -2281,7 +2419,7 @@ index 654a58132a4d..655be2332742 100644 struct bch_fs *c = trans->c; struct btree_iter alloc_iter = { NULL }; struct bkey_s_c alloc_k; -@@ -399,10 +326,14 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_ +@@ -399,10 +322,14 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_ struct bpos bucket; if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) { @@ -2297,7 +2435,7 @@ index 654a58132a4d..655be2332742 100644 goto out; } -@@ -411,13 +342,16 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_ +@@ -411,13 +338,16 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_ if (ret) goto out; @@ -2321,7 +2459,7 @@ index 654a58132a4d..655be2332742 100644 } out: fsck_err: -@@ -429,18 +363,24 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_ +@@ -429,18 +359,24 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_ /* verify that every backpointer has a corresponding alloc key */ int bch2_check_btree_backpointers(struct bch_fs *c) { @@ -2349,7 +2487,7 @@ index 654a58132a4d..655be2332742 100644 struct bkey_buf last_flushed; }; -@@ -501,9 +441,13 @@ static int check_extent_checksum(struct btree_trans *trans, +@@ -501,9 +437,13 @@ static int check_extent_checksum(struct btree_trans *trans, goto err; prt_str(&buf, "extents pointing to same space, but first extent checksum bad:"); @@ -2365,7 +2503,7 @@ index 654a58132a4d..655be2332742 100644 bch2_bkey_val_to_text(&buf, c, extent2); struct nonce nonce = extent_nonce(extent.k->bversion, p.crc); -@@ -524,41 +468,25 @@ static int check_extent_checksum(struct btree_trans *trans, +@@ -524,41 +464,25 @@ static int check_extent_checksum(struct btree_trans *trans, static int check_bp_exists(struct btree_trans *trans, struct extents_to_bp_state *s, @@ -2380,7 +2518,7 @@ index 654a58132a4d..655be2332742 100644 struct printbuf buf = PRINTBUF; - struct bkey_s_c bp_k; - int ret = 0; -- + - struct bch_dev *ca = bch2_dev_bucket_tryget(c, bucket); - if (!ca) { - prt_str(&buf, "extent for nonexistent device:bucket "); @@ -2391,7 +2529,7 @@ index 654a58132a4d..655be2332742 100644 - ret = -BCH_ERR_fsck_repair_unimplemented; - goto err; - } - +- - if (bpos_lt(bucket, s->bucket_start) || - bpos_gt(bucket, s->bucket_end)) - goto out; @@ -2415,7 +2553,7 @@ index 654a58132a4d..655be2332742 100644 ret = bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed); if (ret) goto err; -@@ -570,7 +498,6 @@ static int check_bp_exists(struct btree_trans *trans, +@@ -570,7 +494,6 @@ static int check_bp_exists(struct btree_trans *trans, fsck_err: bch2_trans_iter_exit(trans, &other_extent_iter); bch2_trans_iter_exit(trans, &bp_iter); @@ -2423,7 +2561,7 @@ index 654a58132a4d..655be2332742 100644 printbuf_exit(&buf); return ret; check_existing_bp: -@@ -578,10 +505,10 @@ static int check_bp_exists(struct btree_trans *trans, +@@ -578,10 +501,10 @@ static int check_bp_exists(struct btree_trans *trans, if (bp_k.k->type != KEY_TYPE_backpointer) goto missing; @@ -2436,7 +2574,7 @@ index 654a58132a4d..655be2332742 100644 ret = bkey_err(other_extent); if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node) ret = 0; -@@ -600,19 +527,23 @@ static int check_bp_exists(struct btree_trans *trans, +@@ -600,19 +523,23 @@ static int check_bp_exists(struct btree_trans *trans, bch_err(c, "%s", buf.buf); if (other_extent.k->size <= orig_k.k->size) { @@ -2463,7 +2601,7 @@ index 654a58132a4d..655be2332742 100644 if (ret < 0) goto err; if (ret) { -@@ -620,7 +551,8 @@ static int check_bp_exists(struct btree_trans *trans, +@@ -620,7 +547,8 @@ static int check_bp_exists(struct btree_trans *trans, goto missing; } @@ -2473,7 +2611,7 @@ index 654a58132a4d..655be2332742 100644 if (ret < 0) goto err; if (ret) { -@@ -629,7 +561,7 @@ static int check_bp_exists(struct btree_trans *trans, +@@ -629,7 +557,7 @@ static int check_bp_exists(struct btree_trans *trans, } printbuf_reset(&buf); @@ -2482,7 +2620,7 @@ index 654a58132a4d..655be2332742 100644 bch2_bkey_val_to_text(&buf, c, orig_k); prt_str(&buf, "\n "); bch2_bkey_val_to_text(&buf, c, other_extent); -@@ -638,21 +570,15 @@ static int check_bp_exists(struct btree_trans *trans, +@@ -638,21 +566,15 @@ static int check_bp_exists(struct btree_trans *trans, goto err; missing: printbuf_reset(&buf); @@ -2509,7 +2647,7 @@ index 654a58132a4d..655be2332742 100644 goto out; } -@@ -663,31 +589,33 @@ static int check_extent_to_backpointers(struct btree_trans *trans, +@@ -663,31 +585,33 @@ static int check_extent_to_backpointers(struct btree_trans *trans, struct bkey_s_c k) { struct bch_fs *c = trans->c; @@ -2556,7 +2694,7 @@ index 654a58132a4d..655be2332742 100644 } return 0; -@@ -896,54 +824,330 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans, +@@ -896,54 +820,330 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans, return 0; } @@ -2905,7 +3043,7 @@ index 654a58132a4d..655be2332742 100644 bch_err_fn(c, ret); return ret; -@@ -959,44 +1163,43 @@ static int check_one_backpointer(struct btree_trans *trans, +@@ -959,44 +1159,43 @@ static int check_one_backpointer(struct btree_trans *trans, return 0; struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(bp_k); @@ -2972,7 +3110,7 @@ index 654a58132a4d..655be2332742 100644 static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans, struct bbpos start, struct bbpos end) -@@ -1009,9 +1212,8 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans, +@@ -1009,9 +1208,8 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans, bkey_init(&last_flushed.k->k); progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_backpointers)); @@ -6515,7 +6653,7 @@ index 000000000000..8b773823704f + +#endif /* _BCACHEFS_BTREE_JOURNAL_ITER_TYPES_H */ diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c -index 244610b1d0b5..c378b97ebeca 100644 +index 244610b1d0b5..1821f40c161a 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -197,7 +197,9 @@ bkey_cached_reuse(struct btree_key_cache *c) @@ -6683,6 +6821,14 @@ index 244610b1d0b5..c378b97ebeca 100644 } static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, +@@ -711,7 +748,6 @@ void bch2_fs_btree_key_cache_exit(struct btree_key_cache *bc) + rcu_read_unlock(); + mutex_lock(&bc->table.mutex); + mutex_unlock(&bc->table.mutex); +- rcu_read_lock(); + continue; + } + for (i = 0; i < tbl->size; i++) diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c index efe2a007b482..10b805a60f52 100644 --- a/fs/bcachefs/btree_locking.c @@ -8008,7 +8154,7 @@ index 70b3c989fac2..8f22ef9a7651 100644 struct bkey_i *k = bch2_trans_kmalloc(trans, sizeof(*k) + val_size); int ret; diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c -index d596ef93239f..ab111fec1701 100644 +index d596ef93239f..f4aeadbe53c1 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -58,11 +58,15 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b) @@ -8348,33 +8494,7 @@ index d596ef93239f..ab111fec1701 100644 bch2_btree_node_free_inmem(trans, btree_iter_path(trans, iter), b); -@@ -2195,48 +2189,76 @@ int bch2_btree_node_rewrite(struct btree_trans *trans, - goto out; - } - -+int bch2_btree_node_rewrite_key(struct btree_trans *trans, -+ enum btree_id btree, unsigned level, -+ struct bpos pos, unsigned flags) -+{ -+ BUG_ON(!level); -+ -+ /* Traverse one depth lower to get a pointer to the node itself: */ -+ struct btree_iter iter; -+ bch2_trans_node_iter_init(trans, &iter, btree, pos, 0, level - 1, 0); -+ struct btree *b = bch2_btree_iter_peek_node(&iter); -+ int ret = PTR_ERR_OR_ZERO(b); -+ if (ret) -+ goto err; -+ -+ ret = bch2_btree_node_rewrite(trans, &iter, b, flags); -+err: -+ bch2_trans_iter_exit(trans, &iter); -+ return ret; -+} -+ - struct async_btree_rewrite { - struct bch_fs *c; - struct work_struct work; +@@ -2201,42 +2195,50 @@ struct async_btree_rewrite { struct list_head list; enum btree_id btree_id; unsigned level; @@ -8445,7 +8565,7 @@ index d596ef93239f..ab111fec1701 100644 return ret; } -@@ -2247,81 +2269,97 @@ static void async_btree_node_rewrite_work(struct work_struct *work) +@@ -2247,81 +2249,97 @@ static void async_btree_node_rewrite_work(struct work_struct *work) struct bch_fs *c = a->c; int ret = bch2_trans_do(c, async_btree_node_rewrite_trans(trans, a)); @@ -8584,7 +8704,7 @@ index d596ef93239f..ab111fec1701 100644 } static int __bch2_btree_node_update_key(struct btree_trans *trans, -@@ -2575,8 +2613,9 @@ static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update +@@ -2575,8 +2593,9 @@ static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update prt_printf(out, "%ps: ", (void *) as->ip_started); bch2_trans_commit_flags_to_text(out, as->flags); @@ -8596,7 +8716,7 @@ index d596ef93239f..ab111fec1701 100644 as->update_level_start, as->update_level_end, bch2_btree_update_modes[as->mode], -@@ -2677,6 +2716,9 @@ void bch2_btree_reserve_cache_to_text(struct printbuf *out, struct bch_fs *c) +@@ -2677,6 +2696,9 @@ void bch2_btree_reserve_cache_to_text(struct printbuf *out, struct bch_fs *c) void bch2_fs_btree_interior_update_exit(struct bch_fs *c) { @@ -8606,7 +8726,7 @@ index d596ef93239f..ab111fec1701 100644 if (c->btree_node_rewrite_worker) destroy_workqueue(c->btree_node_rewrite_worker); if (c->btree_interior_update_worker) -@@ -2692,8 +2734,9 @@ void bch2_fs_btree_interior_update_init_early(struct bch_fs *c) +@@ -2692,8 +2714,9 @@ void bch2_fs_btree_interior_update_init_early(struct bch_fs *c) mutex_init(&c->btree_interior_update_lock); INIT_WORK(&c->btree_interior_update_work, btree_interior_update_work); @@ -8619,7 +8739,7 @@ index d596ef93239f..ab111fec1701 100644 int bch2_fs_btree_interior_update_init(struct bch_fs *c) diff --git a/fs/bcachefs/btree_update_interior.h b/fs/bcachefs/btree_update_interior.h -index 10f400957f21..fa5a88f95d89 100644 +index 10f400957f21..7930ffea3075 100644 --- a/fs/bcachefs/btree_update_interior.h +++ b/fs/bcachefs/btree_update_interior.h @@ -159,7 +159,7 @@ static inline int bch2_foreground_maybe_merge(struct btree_trans *trans, @@ -8631,19 +8751,7 @@ index 10f400957f21..fa5a88f95d89 100644 return bch2_foreground_maybe_merge_sibling(trans, path, level, flags, btree_prev_sib) ?: -@@ -169,7 +169,11 @@ static inline int bch2_foreground_maybe_merge(struct btree_trans *trans, - - int bch2_btree_node_rewrite(struct btree_trans *, struct btree_iter *, - struct btree *, unsigned); -+int bch2_btree_node_rewrite_key(struct btree_trans *, -+ enum btree_id, unsigned, -+ struct bpos, unsigned); - void bch2_btree_node_rewrite_async(struct bch_fs *, struct btree *); -+ - int bch2_btree_node_update_key(struct btree_trans *, struct btree_iter *, - struct btree *, struct bkey_i *, - unsigned, bool); -@@ -334,6 +338,7 @@ void bch2_journal_entry_to_btree_root(struct bch_fs *, struct jset_entry *); +@@ -334,6 +334,7 @@ void bch2_journal_entry_to_btree_root(struct bch_fs *, struct jset_entry *); struct jset_entry *bch2_btree_roots_to_journal_entries(struct bch_fs *, struct jset_entry *, unsigned long); @@ -9227,6 +9335,54 @@ index 28bd09a253c8..7174047b8e92 100644 }; struct bch_dev_usage { +diff --git a/fs/bcachefs/buckets_waiting_for_journal.c b/fs/bcachefs/buckets_waiting_for_journal.c +index f9fb150eda70..c8a488e6b7b8 100644 +--- a/fs/bcachefs/buckets_waiting_for_journal.c ++++ b/fs/bcachefs/buckets_waiting_for_journal.c +@@ -22,23 +22,21 @@ static void bucket_table_init(struct buckets_waiting_for_journal_table *t, size_ + memset(t->d, 0, sizeof(t->d[0]) << t->bits); + } + +-bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b, +- u64 flushed_seq, +- unsigned dev, u64 bucket) ++u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *b, ++ unsigned dev, u64 bucket) + { + struct buckets_waiting_for_journal_table *t; + u64 dev_bucket = (u64) dev << 56 | bucket; +- bool ret = false; +- unsigned i; ++ u64 ret = 0; + + mutex_lock(&b->lock); + t = b->t; + +- for (i = 0; i < ARRAY_SIZE(t->hash_seeds); i++) { ++ for (unsigned i = 0; i < ARRAY_SIZE(t->hash_seeds); i++) { + struct bucket_hashed *h = bucket_hash(t, i, dev_bucket); + + if (h->dev_bucket == dev_bucket) { +- ret = h->journal_seq > flushed_seq; ++ ret = h->journal_seq; + break; + } + } +diff --git a/fs/bcachefs/buckets_waiting_for_journal.h b/fs/bcachefs/buckets_waiting_for_journal.h +index d2ae19cbe18c..365619ca44c8 100644 +--- a/fs/bcachefs/buckets_waiting_for_journal.h ++++ b/fs/bcachefs/buckets_waiting_for_journal.h +@@ -4,8 +4,8 @@ + + #include "buckets_waiting_for_journal_types.h" + +-bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, +- u64, unsigned, u64); ++u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *, ++ unsigned, u64); + int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, + u64, unsigned, u64, u64); + diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 2182b555c112..46e9e32105a9 100644 --- a/fs/bcachefs/chardev.c @@ -9832,28 +9988,10 @@ index 8f4c3f0665c4..c6151495985f 100644 #define darray_init(_d) \ do { \ diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c -index 8e75a852b358..92c6ac20d993 100644 +index 8e75a852b358..337494facac6 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c -@@ -20,6 +20,8 @@ - #include "subvolume.h" - #include "trace.h" - -+#include -+ - static void bkey_put_dev_refs(struct bch_fs *c, struct bkey_s_c k) - { - struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); -@@ -33,7 +35,7 @@ static bool bkey_get_dev_refs(struct bch_fs *c, struct bkey_s_c k) - struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); - - bkey_for_each_ptr(ptrs, ptr) { -- if (!bch2_dev_tryget(c, ptr->dev)) { -+ if (unlikely(!bch2_dev_tryget(c, ptr->dev))) { - bkey_for_each_ptr(ptrs, ptr2) { - if (ptr2 == ptr) - break; -@@ -91,15 +93,28 @@ static bool bkey_nocow_lock(struct bch_fs *c, struct moving_context *ctxt, struc +@@ -91,15 +91,28 @@ static bool bkey_nocow_lock(struct bch_fs *c, struct moving_context *ctxt, struc return true; } @@ -9889,7 +10027,7 @@ index 8e75a852b358..92c6ac20d993 100644 } static void trace_move_extent_fail2(struct data_update *m, -@@ -110,11 +125,8 @@ static void trace_move_extent_fail2(struct data_update *m, +@@ -110,11 +123,8 @@ static void trace_move_extent_fail2(struct data_update *m, { struct bch_fs *c = m->op.c; struct bkey_s_c old = bkey_i_to_s_c(m->k.k); @@ -9902,7 +10040,7 @@ index 8e75a852b358..92c6ac20d993 100644 if (!trace_move_extent_fail_enabled()) return; -@@ -122,27 +134,25 @@ static void trace_move_extent_fail2(struct data_update *m, +@@ -122,27 +132,25 @@ static void trace_move_extent_fail2(struct data_update *m, prt_str(&buf, msg); if (insert) { @@ -9942,7 +10080,7 @@ index 8e75a852b358..92c6ac20d993 100644 prt_str(&buf, "\nold: "); bch2_bkey_val_to_text(&buf, c, old); -@@ -194,7 +204,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, +@@ -194,7 +202,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, struct bpos next_pos; bool should_check_enospc; s64 i_sectors_delta = 0, disk_sectors_delta = 0; @@ -9951,7 +10089,7 @@ index 8e75a852b358..92c6ac20d993 100644 bch2_trans_begin(trans); -@@ -231,16 +241,16 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, +@@ -231,16 +239,16 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, * * Fist, drop rewrite_ptrs from @new: */ @@ -9972,7 +10110,7 @@ index 8e75a852b358..92c6ac20d993 100644 } if (m->data_opts.rewrite_ptrs && -@@ -323,8 +333,11 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, +@@ -323,8 +331,11 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, * it's been hard to reproduce, so this should give us some more * information when it does occur: */ @@ -9986,7 +10124,7 @@ index 8e75a852b358..92c6ac20d993 100644 if (invalid) { struct printbuf buf = PRINTBUF; -@@ -362,7 +375,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, +@@ -362,7 +373,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, k.k->p, bkey_start_pos(&insert->k)) ?: bch2_insert_snapshot_whiteouts(trans, m->btree_id, k.k->p, insert->k.p) ?: @@ -9995,7 +10133,7 @@ index 8e75a852b358..92c6ac20d993 100644 bch2_trans_update(trans, &iter, insert, BTREE_UPDATE_internal_snapshot_node) ?: bch2_trans_commit(trans, &op->res, -@@ -374,7 +387,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, +@@ -374,7 +385,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, bch2_btree_iter_set_pos(&iter, next_pos); this_cpu_add(c->counters[BCH_COUNTER_move_extent_finish], new->k.size); @@ -10005,102 +10143,11 @@ index 8e75a852b358..92c6ac20d993 100644 } err: if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) -@@ -414,14 +428,15 @@ int bch2_data_update_index_update(struct bch_write_op *op) - return bch2_trans_run(op->c, __bch2_data_update_index_update(trans, op)); - } - --void bch2_data_update_read_done(struct data_update *m, -- struct bch_extent_crc_unpacked crc) -+void bch2_data_update_read_done(struct data_update *m) - { -+ m->read_done = true; -+ - /* write bio must own pages: */ - BUG_ON(!m->op.wbio.bio.bi_vcnt); - -- m->op.crc = crc; -- m->op.wbio.bio.bi_iter.bi_size = crc.compressed_size << 9; -+ m->op.crc = m->rbio.pick.crc; -+ m->op.wbio.bio.bi_iter.bi_size = m->op.crc.compressed_size << 9; - - closure_call(&m->op.cl, bch2_write, NULL, NULL); - } -@@ -431,31 +446,34 @@ void bch2_data_update_exit(struct data_update *update) - struct bch_fs *c = update->op.c; - struct bkey_s_c k = bkey_i_to_s_c(update->k.k); - -+ bch2_bio_free_pages_pool(c, &update->op.wbio.bio); -+ kfree(update->bvecs); -+ update->bvecs = NULL; -+ - if (c->opts.nocow_enabled) - bkey_nocow_unlock(c, k); - bkey_put_dev_refs(c, k); -- bch2_bkey_buf_exit(&update->k, c); - bch2_disk_reservation_put(c, &update->op.res); -- bch2_bio_free_pages_pool(c, &update->op.wbio.bio); -+ bch2_bkey_buf_exit(&update->k, c); - } - --static void bch2_update_unwritten_extent(struct btree_trans *trans, -- struct data_update *update) -+static int bch2_update_unwritten_extent(struct btree_trans *trans, -+ struct data_update *update) - { - struct bch_fs *c = update->op.c; -- struct bio *bio = &update->op.wbio.bio; - struct bkey_i_extent *e; - struct write_point *wp; - struct closure cl; - struct btree_iter iter; - struct bkey_s_c k; -- int ret; -+ int ret = 0; - - closure_init_stack(&cl); - bch2_keylist_init(&update->op.insert_keys, update->op.inline_keys); - -- while (bio_sectors(bio)) { -- unsigned sectors = bio_sectors(bio); -+ while (bpos_lt(update->op.pos, update->k.k->k.p)) { -+ unsigned sectors = update->k.k->k.p.offset - -+ update->op.pos.offset; - - bch2_trans_begin(trans); - -@@ -491,7 +509,7 @@ static void bch2_update_unwritten_extent(struct btree_trans *trans, - bch_err_fn_ratelimited(c, ret); - - if (ret) -- return; -+ break; - - sectors = min(sectors, wp->sectors_free); - -@@ -501,7 +519,6 @@ static void bch2_update_unwritten_extent(struct btree_trans *trans, - bch2_alloc_sectors_append_ptrs(c, wp, &e->k_i, sectors, false); - bch2_alloc_sectors_done(c, wp); - -- bio_advance(bio, sectors << 9); - update->op.pos.offset += sectors; - - extent_for_each_ptr(extent_i_to_s(e), ptr) -@@ -520,41 +537,60 @@ static void bch2_update_unwritten_extent(struct btree_trans *trans, - bch2_trans_unlock(trans); - closure_sync(&cl); - } -+ -+ return ret; - } - - void bch2_data_update_opts_to_text(struct printbuf *out, struct bch_fs *c, - struct bch_io_opts *io_opts, +@@ -527,34 +539,38 @@ void bch2_data_update_opts_to_text(struct printbuf *out, struct bch_fs *c, struct data_update_opts *data_opts) { -- printbuf_tabstop_push(out, 20); + printbuf_tabstop_push(out, 20); - prt_str(out, "rewrite ptrs:\t"); -+ if (!out->nr_tabstops) -+ printbuf_tabstop_push(out, 20); + + prt_str_indented(out, "rewrite ptrs:\t"); bch2_prt_u64_base2(out, data_opts->rewrite_ptrs); @@ -10130,72 +10177,21 @@ index 8e75a852b358..92c6ac20d993 100644 - prt_str(out, "extra replicas:\t"); + prt_str_indented(out, "extra replicas:\t"); prt_u64(out, data_opts->extra_replicas); -+ prt_newline(out); } void bch2_data_update_to_text(struct printbuf *out, struct data_update *m) -+{ -+ bch2_data_update_opts_to_text(out, m->op.c, &m->op.opts, &m->data_opts); + { +- bch2_bkey_val_to_text(out, m->op.c, bkey_i_to_s_c(m->k.k)); +- prt_newline(out); + bch2_data_update_opts_to_text(out, m->op.c, &m->op.opts, &m->data_opts); + prt_newline(out); + + prt_str_indented(out, "old key:\t"); + bch2_bkey_val_to_text(out, m->op.c, bkey_i_to_s_c(m->k.k)); -+} -+ -+void bch2_data_update_inflight_to_text(struct printbuf *out, struct data_update *m) - { - bch2_bkey_val_to_text(out, m->op.c, bkey_i_to_s_c(m->k.k)); - prt_newline(out); -+ printbuf_indent_add(out, 2); - bch2_data_update_opts_to_text(out, m->op.c, &m->op.opts, &m->data_opts); -+ prt_printf(out, "read_done:\t\%u\n", m->read_done); -+ bch2_write_op_to_text(out, &m->op); -+ printbuf_indent_sub(out, 2); } int bch2_extent_drop_ptrs(struct btree_trans *trans, -@@ -600,6 +636,40 @@ int bch2_extent_drop_ptrs(struct btree_trans *trans, - bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc); - } - -+static bool can_allocate_without_blocking(struct bch_fs *c, -+ struct data_update *m) -+{ -+ if (unlikely(c->open_buckets_nr_free <= bch2_open_buckets_reserved(m->op.watermark))) -+ return false; -+ -+ unsigned target = m->op.flags & BCH_WRITE_only_specified_devs -+ ? m->op.target -+ : 0; -+ struct bch_devs_mask devs = target_rw_devs(c, BCH_DATA_user, target); -+ -+ darray_for_each(m->op.devs_have, i) -+ __clear_bit(*i, devs.d); -+ -+ rcu_read_lock(); -+ unsigned nr_replicas = 0, i; -+ for_each_set_bit(i, devs.d, BCH_SB_MEMBERS_MAX) { -+ struct bch_dev *ca = bch2_dev_rcu(c, i); -+ -+ struct bch_dev_usage usage; -+ bch2_dev_usage_read_fast(ca, &usage); -+ -+ if (!dev_buckets_free(ca, usage, m->op.watermark)) -+ continue; -+ -+ nr_replicas += ca->mi.durability; -+ if (nr_replicas >= m->op.nr_replicas) -+ break; -+ } -+ rcu_read_unlock(); -+ -+ return nr_replicas >= m->op.nr_replicas; -+} -+ - int bch2_data_update_init(struct btree_trans *trans, - struct btree_iter *iter, - struct moving_context *ctxt, -@@ -614,7 +684,7 @@ int bch2_data_update_init(struct btree_trans *trans, +@@ -614,7 +630,7 @@ int bch2_data_update_init(struct btree_trans *trans, struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); const union bch_extent_entry *entry; struct extent_ptr_decoded p; @@ -10204,38 +10200,18 @@ index 8e75a852b358..92c6ac20d993 100644 int ret = 0; /* -@@ -622,17 +692,8 @@ int bch2_data_update_init(struct btree_trans *trans, +@@ -622,7 +638,7 @@ int bch2_data_update_init(struct btree_trans *trans, * and we have to check for this because we go rw before repairing the * snapshots table - just skip it, we can move it later. */ - if (unlikely(k.k->p.snapshot && !bch2_snapshot_equiv(c, k.k->p.snapshot))) -- return -BCH_ERR_data_update_done; -- -- if (!bkey_get_dev_refs(c, k)) -- return -BCH_ERR_data_update_done; -- -- if (c->opts.nocow_enabled && -- !bkey_nocow_lock(c, ctxt, k)) { -- bkey_put_dev_refs(c, k); -- return -BCH_ERR_nocow_lock_blocked; -- } + if (unlikely(k.k->p.snapshot && !bch2_snapshot_exists(c, k.k->p.snapshot))) -+ return -BCH_ERR_data_update_done_no_snapshot; + return -BCH_ERR_data_update_done; - bch2_bkey_buf_init(&m->k); - bch2_bkey_buf_reassemble(&m->k, c, k); -@@ -647,27 +708,27 @@ int bch2_data_update_init(struct btree_trans *trans, - m->op.target = data_opts.target; - m->op.write_point = wp; - m->op.nr_replicas = 0; -- m->op.flags |= BCH_WRITE_PAGES_STABLE| -- BCH_WRITE_PAGES_OWNED| -- BCH_WRITE_DATA_ENCODED| -- BCH_WRITE_MOVE| -+ m->op.flags |= BCH_WRITE_pages_stable| -+ BCH_WRITE_pages_owned| -+ BCH_WRITE_data_encoded| -+ BCH_WRITE_move| + if (!bkey_get_dev_refs(c, k)) +@@ -652,22 +668,22 @@ int bch2_data_update_init(struct btree_trans *trans, + BCH_WRITE_DATA_ENCODED| + BCH_WRITE_MOVE| m->data_opts.write_flags; - m->op.compression_opt = background_compression(io_opts); + m->op.compression_opt = io_opts.background_compression; @@ -10260,7 +10236,7 @@ index 8e75a852b358..92c6ac20d993 100644 bch2_dev_list_add_dev(&m->op.devs_have, p.ptr.dev); durability_have += bch2_extent_ptr_durability(c, &p); } -@@ -687,7 +748,7 @@ int bch2_data_update_init(struct btree_trans *trans, +@@ -687,7 +703,7 @@ int bch2_data_update_init(struct btree_trans *trans, if (p.crc.compression_type == BCH_COMPRESSION_TYPE_incompressible) m->op.incompressible = true; @@ -10269,93 +10245,7 @@ index 8e75a852b358..92c6ac20d993 100644 } unsigned durability_required = max(0, (int) (io_opts.data_replicas - durability_have)); -@@ -724,7 +785,15 @@ int bch2_data_update_init(struct btree_trans *trans, - /* if iter == NULL, it's just a promote */ - if (iter) - ret = bch2_extent_drop_ptrs(trans, iter, k, &io_opts, &m->data_opts); -- goto out; -+ if (!ret) -+ ret = -BCH_ERR_data_update_done_no_writes_needed; -+ goto out_bkey_buf_exit; -+ } -+ -+ if ((m->op.flags & BCH_WRITE_alloc_nowait) && -+ !can_allocate_without_blocking(c, m)) { -+ ret = -BCH_ERR_data_update_done_would_block; -+ goto out_bkey_buf_exit; - } - - if (reserve_sectors) { -@@ -733,31 +802,77 @@ int bch2_data_update_init(struct btree_trans *trans, - ? 0 - : BCH_DISK_RESERVATION_NOFAIL); - if (ret) -- goto out; -+ goto out_bkey_buf_exit; -+ } -+ -+ if (!bkey_get_dev_refs(c, k)) { -+ ret = -BCH_ERR_data_update_done_no_dev_refs; -+ goto out_put_disk_res; -+ } -+ -+ if (c->opts.nocow_enabled && -+ !bkey_nocow_lock(c, ctxt, k)) { -+ ret = -BCH_ERR_nocow_lock_blocked; -+ goto out_put_dev_refs; - } - - if (bkey_extent_is_unwritten(k)) { -- bch2_update_unwritten_extent(trans, m); -- goto out; -+ ret = bch2_update_unwritten_extent(trans, m) ?: -+ -BCH_ERR_data_update_done_unwritten; -+ goto out_nocow_unlock; - } - -+ /* write path might have to decompress data: */ -+ unsigned buf_bytes = 0; -+ bkey_for_each_ptr_decode(k.k, ptrs, p, entry) -+ buf_bytes = max_t(unsigned, buf_bytes, p.crc.uncompressed_size << 9); -+ -+ unsigned nr_vecs = DIV_ROUND_UP(buf_bytes, PAGE_SIZE); -+ -+ m->bvecs = kmalloc_array(nr_vecs, sizeof*(m->bvecs), GFP_KERNEL); -+ if (!m->bvecs) -+ goto enomem; -+ -+ bio_init(&m->rbio.bio, NULL, m->bvecs, nr_vecs, REQ_OP_READ); -+ bio_init(&m->op.wbio.bio, NULL, m->bvecs, nr_vecs, 0); -+ -+ if (bch2_bio_alloc_pages(&m->op.wbio.bio, buf_bytes, GFP_KERNEL)) -+ goto enomem; -+ -+ rbio_init(&m->rbio.bio, c, io_opts, NULL); -+ m->rbio.bio.bi_iter.bi_size = buf_bytes; -+ m->rbio.bio.bi_iter.bi_sector = bkey_start_offset(k.k); -+ -+ bio_set_prio(&m->op.wbio.bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); -+ - return 0; --out: -- bch2_data_update_exit(m); -- return ret ?: -BCH_ERR_data_update_done; -+enomem: -+ ret = -ENOMEM; -+ kfree(m->bvecs); -+ m->bvecs = NULL; -+out_nocow_unlock: -+ if (c->opts.nocow_enabled) -+ bkey_nocow_unlock(c, k); -+out_put_dev_refs: -+ bkey_put_dev_refs(c, k); -+out_put_disk_res: -+ bch2_disk_reservation_put(c, &m->op.res); -+out_bkey_buf_exit: -+ bch2_bkey_buf_exit(&m->k, c); -+ return ret; - } - +@@ -750,14 +766,14 @@ int bch2_data_update_init(struct btree_trans *trans, void bch2_data_update_opts_normalize(struct bkey_s_c k, struct data_update_opts *opts) { struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); @@ -10375,45 +10265,6 @@ index 8e75a852b358..92c6ac20d993 100644 + ptr_bit <<= 1; } } -diff --git a/fs/bcachefs/data_update.h b/fs/bcachefs/data_update.h -index e4b50723428e..f4cf5d17cc37 100644 ---- a/fs/bcachefs/data_update.h -+++ b/fs/bcachefs/data_update.h -@@ -4,6 +4,7 @@ - #define _BCACHEFS_DATA_UPDATE_H - - #include "bkey_buf.h" -+#include "io_read.h" - #include "io_write_types.h" - - struct moving_context; -@@ -22,20 +23,24 @@ void bch2_data_update_opts_to_text(struct printbuf *, struct bch_fs *, - - struct data_update { - /* extent being updated: */ -+ bool read_done; - enum btree_id btree_id; - struct bkey_buf k; - struct data_update_opts data_opts; - struct moving_context *ctxt; - struct bch_move_stats *stats; -+ -+ struct bch_read_bio rbio; - struct bch_write_op op; -+ struct bio_vec *bvecs; - }; - - void bch2_data_update_to_text(struct printbuf *, struct data_update *); -+void bch2_data_update_inflight_to_text(struct printbuf *, struct data_update *); - - int bch2_data_update_index_update(struct bch_write_op *); - --void bch2_data_update_read_done(struct data_update *, -- struct bch_extent_crc_unpacked); -+void bch2_data_update_read_done(struct data_update *); - - int bch2_extent_drop_ptrs(struct btree_trans *, - struct btree_iter *, diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 45aec1afdb0e..55333e82d1fe 100644 --- a/fs/bcachefs/debug.c @@ -11576,7 +11427,7 @@ index 64ef52e00078..b9770f24f213 100644 } __packed __aligned(8); diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h -index 9c4fe5cdbfb7..d65a75e7216e 100644 +index 9c4fe5cdbfb7..4590cd0c7c90 100644 --- a/fs/bcachefs/errcode.h +++ b/fs/bcachefs/errcode.h @@ -54,7 +54,8 @@ @@ -11614,7 +11465,7 @@ index 9c4fe5cdbfb7..d65a75e7216e 100644 x(0, journal_reclaim_would_deadlock) \ x(EINVAL, fsck) \ x(BCH_ERR_fsck, fsck_fix) \ -@@ -173,8 +176,15 @@ +@@ -173,7 +176,9 @@ x(BCH_ERR_fsck, fsck_errors_not_fixed) \ x(BCH_ERR_fsck, fsck_repair_unimplemented) \ x(BCH_ERR_fsck, fsck_repair_impossible) \ @@ -11623,15 +11474,9 @@ index 9c4fe5cdbfb7..d65a75e7216e 100644 + x(EINVAL, not_in_recovery) \ + x(EINVAL, cannot_rewind_recovery) \ x(0, data_update_done) \ -+ x(BCH_ERR_data_update_done, data_update_done_would_block) \ -+ x(BCH_ERR_data_update_done, data_update_done_unwritten) \ -+ x(BCH_ERR_data_update_done, data_update_done_no_writes_needed) \ -+ x(BCH_ERR_data_update_done, data_update_done_no_snapshot) \ -+ x(BCH_ERR_data_update_done, data_update_done_no_dev_refs) \ x(EINVAL, device_state_not_allowed) \ x(EINVAL, member_info_missing) \ - x(EINVAL, mismatched_block_size) \ -@@ -192,7 +202,9 @@ +@@ -192,7 +197,9 @@ x(EINVAL, opt_parse_error) \ x(EINVAL, remove_with_metadata_missing_unimplemented)\ x(EINVAL, remove_would_lose_data) \ @@ -11642,7 +11487,7 @@ index 9c4fe5cdbfb7..d65a75e7216e 100644 x(EROFS, erofs_trans_commit) \ x(EROFS, erofs_no_writes) \ x(EROFS, erofs_journal_err) \ -@@ -241,7 +253,10 @@ +@@ -241,7 +248,10 @@ x(BCH_ERR_invalid_sb, invalid_sb_downgrade) \ x(BCH_ERR_invalid, invalid_bkey) \ x(BCH_ERR_operation_blocked, nocow_lock_blocked) \ @@ -11653,7 +11498,7 @@ index 9c4fe5cdbfb7..d65a75e7216e 100644 x(EIO, sb_not_downgraded) \ x(EIO, btree_node_write_all_failed) \ x(EIO, btree_node_read_error) \ -@@ -257,6 +272,8 @@ +@@ -257,6 +267,8 @@ x(EIO, no_device_to_read_from) \ x(EIO, missing_indirect_extent) \ x(EIO, invalidate_stripe_to_dev) \ @@ -11662,7 +11507,7 @@ index 9c4fe5cdbfb7..d65a75e7216e 100644 x(BCH_ERR_btree_node_read_err, btree_node_read_err_fixable) \ x(BCH_ERR_btree_node_read_err, btree_node_read_err_want_retry) \ x(BCH_ERR_btree_node_read_err, btree_node_read_err_must_retry) \ -@@ -305,6 +322,7 @@ static inline long bch2_err_class(long err) +@@ -305,6 +317,7 @@ static inline long bch2_err_class(long err) #define BLK_STS_REMOVED ((__force blk_status_t)128) @@ -12832,25 +12677,10 @@ index c934e807b380..2b59210bb5e8 100644 + #endif /* _BCACHEFS_FS_COMMON_H */ diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c -index 95972809e76d..83e15908250d 100644 +index 95972809e76d..ab1d5db2fa56 100644 --- a/fs/bcachefs/fs-io-buffered.c +++ b/fs/bcachefs/fs-io-buffered.c -@@ -149,12 +149,10 @@ static void bchfs_read(struct btree_trans *trans, - struct bch_fs *c = trans->c; - struct btree_iter iter; - struct bkey_buf sk; -- int flags = BCH_READ_RETRY_IF_STALE| -- BCH_READ_MAY_PROMOTE; -+ int flags = BCH_READ_retry_if_stale| -+ BCH_READ_may_promote; - int ret = 0; - -- rbio->c = c; -- rbio->start_time = local_clock(); - rbio->subvol = inum.subvol; - - bch2_bkey_buf_init(&sk); -@@ -164,7 +162,8 @@ static void bchfs_read(struct btree_trans *trans, +@@ -164,7 +164,8 @@ static void bchfs_read(struct btree_trans *trans, BTREE_ITER_slots); while (1) { struct bkey_s_c k; @@ -12860,7 +12690,7 @@ index 95972809e76d..83e15908250d 100644 enum btree_id data_btree = BTREE_ID_extents; bch2_trans_begin(trans); -@@ -197,7 +196,7 @@ static void bchfs_read(struct btree_trans *trans, +@@ -197,7 +198,7 @@ static void bchfs_read(struct btree_trans *trans, k = bkey_i_to_s_c(sk.k); @@ -12869,24 +12699,7 @@ index 95972809e76d..83e15908250d 100644 if (readpages_iter) { ret = readpage_bio_extend(trans, readpages_iter, &rbio->bio, sectors, -@@ -210,14 +209,14 @@ static void bchfs_read(struct btree_trans *trans, - swap(rbio->bio.bi_iter.bi_size, bytes); - - if (rbio->bio.bi_iter.bi_size == bytes) -- flags |= BCH_READ_LAST_FRAGMENT; -+ flags |= BCH_READ_last_fragment; - - bch2_bio_page_state_set(&rbio->bio, k); - - bch2_read_extent(trans, rbio, iter.pos, - data_btree, k, offset_into_extent, flags); - -- if (flags & BCH_READ_LAST_FRAGMENT) -+ if (flags & BCH_READ_last_fragment) - break; - - swap(rbio->bio.bi_iter.bi_size, bytes); -@@ -230,10 +229,12 @@ static void bchfs_read(struct btree_trans *trans, +@@ -230,10 +231,12 @@ static void bchfs_read(struct btree_trans *trans, bch2_trans_iter_exit(trans, &iter); if (ret) { @@ -12903,7 +12716,7 @@ index 95972809e76d..83e15908250d 100644 rbio->bio.bi_status = BLK_STS_IOERR; bio_endio(&rbio->bio); } -@@ -248,6 +249,7 @@ void bch2_readahead(struct readahead_control *ractl) +@@ -248,6 +251,7 @@ void bch2_readahead(struct readahead_control *ractl) struct bch_io_opts opts; struct folio *folio; struct readpages_iter readpages_iter; @@ -12911,7 +12724,7 @@ index 95972809e76d..83e15908250d 100644 bch2_inode_opts_get(&opts, c, &inode->ei_inode); -@@ -255,6 +257,16 @@ void bch2_readahead(struct readahead_control *ractl) +@@ -255,6 +259,16 @@ void bch2_readahead(struct readahead_control *ractl) if (ret) return; @@ -12928,23 +12741,7 @@ index 95972809e76d..83e15908250d 100644 bch2_pagecache_add_get(inode); struct btree_trans *trans = bch2_trans_get(c); -@@ -266,12 +278,13 @@ void bch2_readahead(struct readahead_control *ractl) - struct bch_read_bio *rbio = - rbio_init(bio_alloc_bioset(NULL, n, REQ_OP_READ, - GFP_KERNEL, &c->bio_read), -- opts); -+ c, -+ opts, -+ bch2_readpages_end_io); - - readpage_iter_advance(&readpages_iter); - - rbio->bio.bi_iter.bi_sector = folio_sector(folio); -- rbio->bio.bi_end_io = bch2_readpages_end_io; - BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); - - bchfs_read(trans, rbio, inode_inum(inode), -@@ -281,7 +294,7 @@ void bch2_readahead(struct readahead_control *ractl) +@@ -281,7 +295,7 @@ void bch2_readahead(struct readahead_control *ractl) bch2_trans_put(trans); bch2_pagecache_add_put(inode); @@ -12953,7 +12750,7 @@ index 95972809e76d..83e15908250d 100644 darray_exit(&readpages_iter.folios); } -@@ -296,24 +309,30 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping) +@@ -296,9 +310,13 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping) struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_read_bio *rbio; struct bch_io_opts opts; @@ -12967,17 +12764,7 @@ index 95972809e76d..83e15908250d 100644 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), -- opts); -+ c, -+ opts, -+ bch2_read_single_folio_end_io); - rbio->bio.bi_private = &done; -- rbio->bio.bi_end_io = bch2_read_single_folio_end_io; -- - rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC; +@@ -313,7 +331,9 @@ int bch2_read_single_folio(struct folio *folio, struct address_space *mapping) rbio->bio.bi_iter.bi_sector = folio_sector(folio); BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); @@ -12987,16 +12774,7 @@ index 95972809e76d..83e15908250d 100644 wait_for_completion(&done); ret = blk_status_to_errno(rbio->bio.bi_status); -@@ -400,7 +419,7 @@ static void bch2_writepage_io_done(struct bch_write_op *op) - } - } - -- if (io->op.flags & BCH_WRITE_WROTE_DATA_INLINE) { -+ if (io->op.flags & BCH_WRITE_wrote_data_inline) { - bio_for_each_folio_all(fi, bio) { - struct bch_folio *s; - -@@ -605,15 +624,6 @@ static int __bch2_writepage(struct folio *folio, +@@ -605,15 +625,6 @@ static int __bch2_writepage(struct folio *folio, BUG_ON(!bio_add_folio(&w->io->op.wbio.bio, folio, sectors << 9, offset << 9)); @@ -13012,7 +12790,7 @@ index 95972809e76d..83e15908250d 100644 w->io->op.res.sectors += reserved_sectors; w->io->op.i_sectors_delta -= dirty_sectors; w->io->op.new_i_size = i_size; -@@ -669,7 +679,7 @@ int bch2_write_begin(struct file *file, struct address_space *mapping, +@@ -669,7 +680,7 @@ int bch2_write_begin(struct file *file, struct address_space *mapping, folio = __filemap_get_folio(mapping, pos >> PAGE_SHIFT, FGP_WRITEBEGIN | fgf_set_order(len), mapping_gfp_mask(mapping)); @@ -13022,30 +12800,18 @@ index 95972809e76d..83e15908250d 100644 offset = pos - folio_pos(folio); diff --git a/fs/bcachefs/fs-io-direct.c b/fs/bcachefs/fs-io-direct.c -index 6d3a05ae5da8..535bc5fcbcc0 100644 +index 6d3a05ae5da8..2089c36b5866 100644 --- a/fs/bcachefs/fs-io-direct.c +++ b/fs/bcachefs/fs-io-direct.c -@@ -70,8 +70,10 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) +@@ -70,6 +70,7 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) struct bch_io_opts opts; struct dio_read *dio; struct bio *bio; + struct blk_plug plug; loff_t offset = req->ki_pos; bool sync = is_sync_kiocb(req); -+ bool split = false; size_t shorten; - ssize_t ret; - -@@ -98,8 +100,6 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) - GFP_KERNEL, - &c->dio_read_bioset); - -- bio->bi_end_io = bch2_direct_IO_read_endio; -- - dio = container_of(bio, struct dio_read, rbio.bio); - closure_init(&dio->cl, NULL); - -@@ -128,14 +128,17 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) +@@ -128,6 +129,8 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) */ dio->should_dirty = iter_is_iovec(iter); @@ -13053,31 +12819,9 @@ index 6d3a05ae5da8..535bc5fcbcc0 100644 + goto start; while (iter->count) { -+ split = true; -+ bio = bio_alloc_bioset(NULL, - bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS), - REQ_OP_READ, - GFP_KERNEL, - &c->bio_read); -- bio->bi_end_io = bch2_direct_IO_read_split_endio; - start: - bio->bi_opf = REQ_OP_READ|REQ_SYNC; - bio->bi_iter.bi_sector = offset >> 9; -@@ -157,9 +160,19 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) - if (iter->count) - closure_get(&dio->cl); - -- bch2_read(c, rbio_init(bio, opts), inode_inum(inode)); -+ struct bch_read_bio *rbio = -+ rbio_init(bio, -+ c, -+ opts, -+ split -+ ? bch2_direct_IO_read_split_endio -+ : bch2_direct_IO_read_endio); -+ -+ bch2_read(c, rbio, inode_inum(inode)); +@@ -160,6 +163,8 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter) + bch2_read(c, rbio_init(bio, opts), inode_inum(inode)); } + blk_finish_plug(&plug); @@ -13085,17 +12829,6 @@ index 6d3a05ae5da8..535bc5fcbcc0 100644 iter->count += shorten; if (sync) { -@@ -506,8 +519,8 @@ static __always_inline long bch2_dio_write_loop(struct dio_write *dio) - dio->op.devs_need_flush = &inode->ei_devs_need_flush; - - if (sync) -- dio->op.flags |= BCH_WRITE_SYNC; -- dio->op.flags |= BCH_WRITE_CHECK_ENOSPC; -+ dio->op.flags |= BCH_WRITE_sync; -+ dio->op.flags |= BCH_WRITE_check_enospc; - - ret = bch2_quota_reservation_add(c, inode, &dio->quota_res, - bio_sectors(bio), true); diff --git a/fs/bcachefs/fs-io-pagecache.c b/fs/bcachefs/fs-io-pagecache.c index 1d4910ea0f1d..e072900e6a5b 100644 --- a/fs/bcachefs/fs-io-pagecache.c @@ -15132,7 +14865,7 @@ index 039cb7a22244..04ec05206f8c 100644 ret = bch2_inode_rm_snapshot(trans, k.k->p.offset, k.k->p.snapshot); /* diff --git a/fs/bcachefs/inode.h b/fs/bcachefs/inode.h -index eab82b5eb897..d2e134528f0e 100644 +index eab82b5eb897..428b9be6af34 100644 --- a/fs/bcachefs/inode.h +++ b/fs/bcachefs/inode.h @@ -7,15 +7,14 @@ @@ -15210,16 +14943,18 @@ index eab82b5eb897..d2e134528f0e 100644 { bool inode_has_bp = inode->bi_dir || inode->bi_dir_offset; -@@ -262,6 +285,14 @@ void bch2_inode_opts_get(struct bch_io_opts *, struct bch_fs *, +@@ -262,6 +285,16 @@ void bch2_inode_opts_get(struct bch_io_opts *, struct bch_fs *, struct bch_inode_unpacked *); int bch2_inum_opts_get(struct btree_trans*, subvol_inum, struct bch_io_opts *); ++#include "rebalance.h" ++ +static inline struct bch_extent_rebalance +bch2_inode_rebalance_opts_get(struct bch_fs *c, struct bch_inode_unpacked *inode) +{ + struct bch_io_opts io_opts; + bch2_inode_opts_get(&io_opts, c, inode); -+ return io_opts_to_rebalance_opts(&io_opts); ++ return io_opts_to_rebalance_opts(c, &io_opts); +} + int bch2_inode_rm_snapshot(struct btree_trans *, u64, u32); @@ -15319,7 +15054,7 @@ index f283051758d6..5353979117b0 100644 bch2_btree_insert_trans(trans, BTREE_ID_extents, copy, 0) ?: bch2_logged_op_update(trans, &op->k_i) ?: diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c -index b3b934a87c6d..6276f375dbc9 100644 +index b3b934a87c6d..8c7b2d3d779d 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c @@ -21,6 +21,7 @@ @@ -15330,15 +15065,7 @@ index b3b934a87c6d..6276f375dbc9 100644 #include "subvolume.h" #include "trace.h" -@@ -79,6 +80,7 @@ struct promote_op { - struct rhash_head hash; - struct bpos pos; - -+ struct work_struct work; - struct data_update write; - struct bio_vec bi_inline_vecs[]; /* must be last */ - }; -@@ -90,16 +92,41 @@ static const struct rhashtable_params bch_promote_params = { +@@ -90,13 +91,18 @@ static const struct rhashtable_params bch_promote_params = { .automatic_shrinking = true, }; @@ -15346,26 +15073,6 @@ index b3b934a87c6d..6276f375dbc9 100644 +{ + return failed && failed->nr; +} -+ -+static bool ptr_being_rewritten(struct bch_read_bio *orig, -+ unsigned dev, -+ unsigned flags) -+{ -+ if (!(flags & BCH_READ_data_update)) -+ return false; -+ -+ struct data_update *u = container_of(orig, struct data_update, rbio); -+ struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(u->k.k)); -+ unsigned i = 0; -+ bkey_for_each_ptr(ptrs, ptr) { -+ if (ptr->dev == dev && -+ u->data_opts.rewrite_ptrs & BIT(i)) -+ return true; -+ i++; -+ } -+ -+ return false; -+} + static inline int should_promote(struct bch_fs *c, struct bkey_s_c k, struct bpos pos, @@ -15377,245 +15084,32 @@ index b3b934a87c6d..6276f375dbc9 100644 + if (!have_io_error(failed)) { BUG_ON(!opts.promote_target); -- if (!(flags & BCH_READ_MAY_PROMOTE)) -+ if (!(flags & BCH_READ_may_promote)) - return -BCH_ERR_nopromote_may_not; + if (!(flags & BCH_READ_MAY_PROMOTE)) +@@ -223,7 +229,7 @@ static struct promote_op *__promote_alloc(struct btree_trans *trans, - if (bch2_bkey_has_target(c, k, opts.promote_target)) -@@ -119,98 +146,94 @@ static inline int should_promote(struct bch_fs *c, struct bkey_s_c k, - return 0; - } + struct data_update_opts update_opts = {}; --static void promote_free(struct bch_fs *c, struct promote_op *op) -+static noinline void promote_free(struct bch_read_bio *rbio) - { -- int ret; -+ struct promote_op *op = container_of(rbio, struct promote_op, write.rbio); -+ struct bch_fs *c = rbio->c; -+ -+ int ret = rhashtable_remove_fast(&c->promote_table, &op->hash, -+ bch_promote_params); -+ BUG_ON(ret); - - bch2_data_update_exit(&op->write); - -- ret = rhashtable_remove_fast(&c->promote_table, &op->hash, -- bch_promote_params); -- BUG_ON(ret); - bch2_write_ref_put(c, BCH_WRITE_REF_promote); - kfree_rcu(op, rcu); - } - - static void promote_done(struct bch_write_op *wop) - { -- struct promote_op *op = -- container_of(wop, struct promote_op, write.op); -- struct bch_fs *c = op->write.op.c; -+ struct promote_op *op = container_of(wop, struct promote_op, write.op); -+ struct bch_fs *c = op->write.rbio.c; - -- bch2_time_stats_update(&c->times[BCH_TIME_data_promote], -- op->start_time); -- promote_free(c, op); -+ bch2_time_stats_update(&c->times[BCH_TIME_data_promote], op->start_time); -+ promote_free(&op->write.rbio); - } - --static void promote_start(struct promote_op *op, struct bch_read_bio *rbio) -+static void promote_start_work(struct work_struct *work) - { -- struct bio *bio = &op->write.op.wbio.bio; -+ struct promote_op *op = container_of(work, struct promote_op, work); - -- trace_and_count(op->write.op.c, read_promote, &rbio->bio); -+ bch2_data_update_read_done(&op->write); -+} - -- /* we now own pages: */ -- BUG_ON(!rbio->bounce); -- BUG_ON(rbio->bio.bi_vcnt > bio->bi_max_vecs); -+static noinline void promote_start(struct bch_read_bio *rbio) -+{ -+ struct promote_op *op = container_of(rbio, struct promote_op, write.rbio); - -- memcpy(bio->bi_io_vec, rbio->bio.bi_io_vec, -- sizeof(struct bio_vec) * rbio->bio.bi_vcnt); -- swap(bio->bi_vcnt, rbio->bio.bi_vcnt); -+ trace_and_count(op->write.op.c, read_promote, &rbio->bio); - -- bch2_data_update_read_done(&op->write, rbio->pick.crc); -+ INIT_WORK(&op->work, promote_start_work); -+ queue_work(rbio->c->write_ref_wq, &op->work); - } - --static struct promote_op *__promote_alloc(struct btree_trans *trans, -- enum btree_id btree_id, -- struct bkey_s_c k, -- struct bpos pos, -- struct extent_ptr_decoded *pick, -- struct bch_io_opts opts, -- unsigned sectors, -- struct bch_read_bio **rbio, -- struct bch_io_failures *failed) -+static struct bch_read_bio *__promote_alloc(struct btree_trans *trans, -+ enum btree_id btree_id, -+ struct bkey_s_c k, -+ struct bpos pos, -+ struct extent_ptr_decoded *pick, -+ unsigned sectors, -+ unsigned flags, -+ struct bch_read_bio *orig, -+ struct bch_io_failures *failed) - { - struct bch_fs *c = trans->c; -- struct promote_op *op = NULL; -- struct bio *bio; -- unsigned pages = DIV_ROUND_UP(sectors, PAGE_SECTORS); - int ret; - -- if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_promote)) -- return ERR_PTR(-BCH_ERR_nopromote_no_writes); -+ struct data_update_opts update_opts = { .write_flags = BCH_WRITE_alloc_nowait }; - -- op = kzalloc(struct_size(op, bi_inline_vecs, pages), GFP_KERNEL); -- if (!op) { -- ret = -BCH_ERR_nopromote_enomem; -- goto err; -- } -+ if (!have_io_error(failed)) { -+ update_opts.target = orig->opts.promote_target; -+ update_opts.extra_replicas = 1; -+ update_opts.write_flags |= BCH_WRITE_cached; -+ update_opts.write_flags |= BCH_WRITE_only_specified_devs; -+ } else { -+ update_opts.target = orig->opts.foreground_target; - -- op->start_time = local_clock(); -- op->pos = pos; -+ struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); -+ unsigned ptr_bit = 1; -+ bkey_for_each_ptr(ptrs, ptr) { -+ if (bch2_dev_io_failures(failed, ptr->dev) && -+ !ptr_being_rewritten(orig, ptr->dev, flags)) -+ update_opts.rewrite_ptrs |= ptr_bit; -+ ptr_bit <<= 1; -+ } - -- /* -- * We don't use the mempool here because extents that aren't -- * checksummed or compressed can be too big for the mempool: -- */ -- *rbio = kzalloc(sizeof(struct bch_read_bio) + -- sizeof(struct bio_vec) * pages, -- GFP_KERNEL); -- if (!*rbio) { -- ret = -BCH_ERR_nopromote_enomem; -- goto err; -+ if (!update_opts.rewrite_ptrs) -+ return NULL; - } - -- rbio_init(&(*rbio)->bio, opts); -- bio_init(&(*rbio)->bio, NULL, (*rbio)->bio.bi_inline_vecs, pages, 0); -+ if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_promote)) -+ return ERR_PTR(-BCH_ERR_nopromote_no_writes); - -- if (bch2_bio_alloc_pages(&(*rbio)->bio, sectors << 9, GFP_KERNEL)) { -+ struct promote_op *op = kzalloc(sizeof(*op), GFP_KERNEL); -+ if (!op) { - ret = -BCH_ERR_nopromote_enomem; -- goto err; -+ goto err_put; - } - -- (*rbio)->bounce = true; -- (*rbio)->split = true; -- (*rbio)->kmalloc = true; -+ op->start_time = local_clock(); -+ op->pos = pos; - - if (rhashtable_lookup_insert_fast(&c->promote_table, &op->hash, - bch_promote_params)) { -@@ -218,64 +241,43 @@ static struct promote_op *__promote_alloc(struct btree_trans *trans, - goto err; - } - -- bio = &op->write.op.wbio.bio; -- bio_init(bio, NULL, bio->bi_inline_vecs, pages, 0); -- -- struct data_update_opts update_opts = {}; -- - if (!failed) { -- update_opts.target = opts.promote_target; -- update_opts.extra_replicas = 1; -- update_opts.write_flags = BCH_WRITE_ALLOC_NOWAIT|BCH_WRITE_CACHED; -- } else { -- update_opts.target = opts.foreground_target; -- -- struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); ++ if (!have_io_error(failed)) { + update_opts.target = opts.promote_target; + update_opts.extra_replicas = 1; + update_opts.write_flags = BCH_WRITE_ALLOC_NOWAIT|BCH_WRITE_CACHED; +@@ -231,11 +237,11 @@ static struct promote_op *__promote_alloc(struct btree_trans *trans, + update_opts.target = opts.foreground_target; + + struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); - unsigned i = 0; -- bkey_for_each_ptr(ptrs, ptr) { -- if (bch2_dev_io_failures(failed, ptr->dev)) ++ unsigned ptr_bit = 1; + bkey_for_each_ptr(ptrs, ptr) { + if (bch2_dev_io_failures(failed, ptr->dev)) - update_opts.rewrite_ptrs |= BIT(i); - i++; -- } -- } -- - ret = bch2_data_update_init(trans, NULL, NULL, &op->write, - writepoint_hashed((unsigned long) current), -- opts, -+ orig->opts, - update_opts, - btree_id, k); - /* - * possible errors: -BCH_ERR_nocow_lock_blocked, - * -BCH_ERR_ENOSPC_disk_reservation: - */ -- if (ret) { -- BUG_ON(rhashtable_remove_fast(&c->promote_table, &op->hash, -- bch_promote_params)); -- goto err; -- } -+ if (ret) -+ goto err_remove_hash; ++ update_opts.rewrite_ptrs |= ptr_bit; ++ ptr_bit <<= 1; + } + } -+ rbio_init_fragment(&op->write.rbio.bio, orig); -+ op->write.rbio.bounce = true; -+ op->write.rbio.promote = true; - op->write.op.end_io = promote_done; - -- return op; -+ return &op->write.rbio; -+err_remove_hash: -+ BUG_ON(rhashtable_remove_fast(&c->promote_table, &op->hash, -+ bch_promote_params)); - err: -- if (*rbio) -- bio_free_pages(&(*rbio)->bio); -- kfree(*rbio); -- *rbio = NULL; -+ bio_free_pages(&op->write.op.wbio.bio); - /* We may have added to the rhashtable and thus need rcu freeing: */ - kfree_rcu(op, rcu); -+err_put: - bch2_write_ref_put(c, BCH_WRITE_REF_promote); - return ERR_PTR(ret); - } - - noinline --static struct promote_op *promote_alloc(struct btree_trans *trans, -+static struct bch_read_bio *promote_alloc(struct btree_trans *trans, - struct bvec_iter iter, - struct bkey_s_c k, - struct extent_ptr_decoded *pick, -- struct bch_io_opts opts, - unsigned flags, -- struct bch_read_bio **rbio, -+ struct bch_read_bio *orig, - bool *bounce, - bool *read_full, - struct bch_io_failures *failed) -@@ -285,7 +287,7 @@ static struct promote_op *promote_alloc(struct btree_trans *trans, +@@ -285,7 +291,7 @@ static struct promote_op *promote_alloc(struct btree_trans *trans, * if failed != NULL we're not actually doing a promote, we're * recovering from an io/checksum error */ @@ -15624,36 +15118,7 @@ index b3b934a87c6d..6276f375dbc9 100644 *read_full || READ_ONCE(c->opts.promote_whole_extents)); /* data might have to be decompressed in the write path: */ -@@ -295,18 +297,21 @@ static struct promote_op *promote_alloc(struct btree_trans *trans, - struct bpos pos = promote_full - ? bkey_start_pos(k.k) - : POS(k.k->p.inode, iter.bi_sector); -- struct promote_op *promote; - int ret; - -- ret = should_promote(c, k, pos, opts, flags, failed); -+ ret = should_promote(c, k, pos, orig->opts, flags, failed); - if (ret) - goto nopromote; - -- promote = __promote_alloc(trans, -- k.k->type == KEY_TYPE_reflink_v -- ? BTREE_ID_reflink -- : BTREE_ID_extents, -- k, pos, pick, opts, sectors, rbio, failed); -+ struct bch_read_bio *promote = -+ __promote_alloc(trans, -+ k.k->type == KEY_TYPE_reflink_v -+ ? BTREE_ID_reflink -+ : BTREE_ID_extents, -+ k, pos, pick, sectors, flags, orig, failed); -+ if (!promote) -+ return NULL; -+ - ret = PTR_ERR_OR_ZERO(promote); - if (ret) - goto nopromote; -@@ -321,6 +326,20 @@ static struct promote_op *promote_alloc(struct btree_trans *trans, +@@ -321,6 +327,20 @@ static struct promote_op *promote_alloc(struct btree_trans *trans, /* Read */ @@ -15674,159 +15139,7 @@ index b3b934a87c6d..6276f375dbc9 100644 #define READ_RETRY_AVOID 1 #define READ_RETRY 2 #define READ_ERR 3 -@@ -355,20 +374,20 @@ static inline struct bch_read_bio *bch2_rbio_free(struct bch_read_bio *rbio) - { - BUG_ON(rbio->bounce && !rbio->split); - -- if (rbio->promote) -- promote_free(rbio->c, rbio->promote); -- rbio->promote = NULL; -- -- if (rbio->bounce) -- bch2_bio_free_pages_pool(rbio->c, &rbio->bio); -- - if (rbio->split) { - struct bch_read_bio *parent = rbio->parent; - -- if (rbio->kmalloc) -- kfree(rbio); -- else -+ if (unlikely(rbio->promote)) { -+ if (!rbio->bio.bi_status) -+ promote_start(rbio); -+ else -+ promote_free(rbio); -+ } else { -+ if (rbio->bounce) -+ bch2_bio_free_pages_pool(rbio->c, &rbio->bio); -+ - bio_put(&rbio->bio); -+ } - - rbio = parent; - } -@@ -388,61 +407,47 @@ static void bch2_rbio_done(struct bch_read_bio *rbio) - bio_endio(&rbio->bio); - } - --static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio, -+static noinline void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio, - struct bvec_iter bvec_iter, - struct bch_io_failures *failed, - unsigned flags) - { -+ struct data_update *u = container_of(rbio, struct data_update, rbio); - struct btree_trans *trans = bch2_trans_get(c); -- struct btree_iter iter; -- struct bkey_buf sk; -- struct bkey_s_c k; -- int ret; -- -- flags &= ~BCH_READ_LAST_FRAGMENT; -- flags |= BCH_READ_MUST_CLONE; -- -- bch2_bkey_buf_init(&sk); -- -- bch2_trans_iter_init(trans, &iter, rbio->data_btree, -- rbio->read_pos, BTREE_ITER_slots); - retry: - bch2_trans_begin(trans); -- rbio->bio.bi_status = 0; - -- ret = lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_slot(&iter))); -+ struct btree_iter iter; -+ struct bkey_s_c k; -+ int ret = lockrestart_do(trans, -+ bkey_err(k = bch2_bkey_get_iter(trans, &iter, -+ u->btree_id, bkey_start_pos(&u->k.k->k), -+ 0))); - if (ret) - goto err; - -- bch2_bkey_buf_reassemble(&sk, c, k); -- k = bkey_i_to_s_c(sk.k); -- -- if (!bch2_bkey_matches_ptr(c, k, -- rbio->pick.ptr, -- rbio->data_pos.offset - -- rbio->pick.crc.offset)) { -+ if (!bkey_and_val_eq(k, bkey_i_to_s_c(u->k.k))) { - /* extent we wanted to read no longer exists: */ - rbio->hole = true; -- goto out; -+ goto err; - } - - ret = __bch2_read_extent(trans, rbio, bvec_iter, -- rbio->read_pos, -- rbio->data_btree, -- k, 0, failed, flags); -+ bkey_start_pos(&u->k.k->k), -+ u->btree_id, -+ bkey_i_to_s_c(u->k.k), -+ 0, failed, flags); -+err: -+ bch2_trans_iter_exit(trans, &iter); -+ - if (ret == READ_RETRY) - goto retry; - if (ret) -- goto err; --out: -+ rbio->bio.bi_status = BLK_STS_IOERR; -+ -+ BUG_ON(atomic_read(&rbio->bio.__bi_remaining) != 1); - bch2_rbio_done(rbio); -- bch2_trans_iter_exit(trans, &iter); - bch2_trans_put(trans); -- bch2_bkey_buf_exit(&sk, c); -- return; --err: -- rbio->bio.bi_status = BLK_STS_IOERR; -- goto out; - } - - static void bch2_rbio_retry(struct work_struct *work) -@@ -463,21 +468,20 @@ static void bch2_rbio_retry(struct work_struct *work) - if (rbio->retry == READ_RETRY_AVOID) - bch2_mark_io_failure(&failed, &rbio->pick); - -- rbio->bio.bi_status = 0; -+ if (!rbio->split) -+ rbio->bio.bi_status = 0; - - rbio = bch2_rbio_free(rbio); - -- flags |= BCH_READ_IN_RETRY; -- flags &= ~BCH_READ_MAY_PROMOTE; -+ flags |= BCH_READ_in_retry; -+ flags &= ~BCH_READ_may_promote; -+ flags &= ~BCH_READ_last_fragment; -+ flags |= BCH_READ_must_clone; - -- if (flags & BCH_READ_NODECODE) { -+ if (flags & BCH_READ_data_update) - bch2_read_retry_nodecode(c, rbio, iter, &failed, flags); -- } else { -- flags &= ~BCH_READ_LAST_FRAGMENT; -- flags |= BCH_READ_MUST_CLONE; -- -+ else - __bch2_read(c, rbio, iter, inum, &failed, flags); -- } - } - - static void bch2_rbio_error(struct bch_read_bio *rbio, int retry, -@@ -485,7 +489,7 @@ static void bch2_rbio_error(struct bch_read_bio *rbio, int retry, - { - rbio->retry = retry; - -- if (rbio->flags & BCH_READ_IN_RETRY) -+ if (rbio->flags & BCH_READ_in_retry) - return; - - if (retry == READ_ERR) { -@@ -499,6 +503,29 @@ static void bch2_rbio_error(struct bch_read_bio *rbio, int retry, +@@ -499,6 +519,29 @@ static void bch2_rbio_error(struct bch_read_bio *rbio, int retry, } } @@ -15856,7 +15169,7 @@ index b3b934a87c6d..6276f375dbc9 100644 static int __bch2_rbio_narrow_crcs(struct btree_trans *trans, struct bch_read_bio *rbio) { -@@ -562,6 +589,73 @@ static noinline void bch2_rbio_narrow_crcs(struct bch_read_bio *rbio) +@@ -562,6 +605,73 @@ static noinline void bch2_rbio_narrow_crcs(struct bch_read_bio *rbio) __bch2_rbio_narrow_crcs(trans, rbio)); } @@ -15930,92 +15243,7 @@ index b3b934a87c6d..6276f375dbc9 100644 /* Inner part that may run in process context */ static void __bch2_read_endio(struct work_struct *work) { -@@ -602,32 +696,40 @@ static void __bch2_read_endio(struct work_struct *work) - if (unlikely(rbio->narrow_crcs)) - bch2_rbio_narrow_crcs(rbio); - -- if (rbio->flags & BCH_READ_NODECODE) -- goto nodecode; -+ if (likely(!(rbio->flags & BCH_READ_data_update))) { -+ /* Adjust crc to point to subset of data we want: */ -+ crc.offset += rbio->offset_into_extent; -+ crc.live_size = bvec_iter_sectors(rbio->bvec_iter); - -- /* Adjust crc to point to subset of data we want: */ -- crc.offset += rbio->offset_into_extent; -- crc.live_size = bvec_iter_sectors(rbio->bvec_iter); -+ if (crc_is_compressed(crc)) { -+ ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src); -+ if (ret) -+ goto decrypt_err; - -- if (crc_is_compressed(crc)) { -- ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src); -- if (ret) -- goto decrypt_err; -+ if (bch2_bio_uncompress(c, src, dst, dst_iter, crc) && -+ !c->opts.no_data_io) -+ goto decompression_err; -+ } else { -+ /* don't need to decrypt the entire bio: */ -+ nonce = nonce_add(nonce, crc.offset << 9); -+ bio_advance(src, crc.offset << 9); - -- if (bch2_bio_uncompress(c, src, dst, dst_iter, crc) && -- !c->opts.no_data_io) -- goto decompression_err; -- } else { -- /* don't need to decrypt the entire bio: */ -- nonce = nonce_add(nonce, crc.offset << 9); -- bio_advance(src, crc.offset << 9); -+ BUG_ON(src->bi_iter.bi_size < dst_iter.bi_size); -+ src->bi_iter.bi_size = dst_iter.bi_size; - -- BUG_ON(src->bi_iter.bi_size < dst_iter.bi_size); -- src->bi_iter.bi_size = dst_iter.bi_size; -+ ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src); -+ if (ret) -+ goto decrypt_err; - -- ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src); -- if (ret) -- goto decrypt_err; -+ if (rbio->bounce) { -+ struct bvec_iter src_iter = src->bi_iter; -+ -+ bio_copy_data_iter(dst, &dst_iter, src, &src_iter); -+ } -+ } -+ } else { -+ if (rbio->split) -+ rbio->parent->pick = rbio->pick; - - if (rbio->bounce) { - struct bvec_iter src_iter = src->bi_iter; -@@ -644,12 +746,9 @@ static void __bch2_read_endio(struct work_struct *work) - ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src); - if (ret) - goto decrypt_err; -- -- promote_start(rbio->promote, rbio); -- rbio->promote = NULL; - } --nodecode: -- if (likely(!(rbio->flags & BCH_READ_IN_RETRY))) { -+ -+ if (likely(!(rbio->flags & BCH_READ_in_retry))) { - rbio = bch2_rbio_free(rbio); - bch2_rbio_done(rbio); - } -@@ -662,39 +761,19 @@ static void __bch2_read_endio(struct work_struct *work) - * reading into buffers owned by userspace (that userspace can - * scribble over) - retry the read, bouncing it this time: - */ -- if (!rbio->bounce && (rbio->flags & BCH_READ_USER_MAPPED)) { -- rbio->flags |= BCH_READ_MUST_BOUNCE; -+ if (!rbio->bounce && (rbio->flags & BCH_READ_user_mapped)) { -+ rbio->flags |= BCH_READ_must_bounce; - bch2_rbio_error(rbio, READ_RETRY, BLK_STS_IOERR); +@@ -668,33 +778,13 @@ static void __bch2_read_endio(struct work_struct *work) goto out; } @@ -16052,7 +15280,7 @@ index b3b934a87c6d..6276f375dbc9 100644 goto out; } -@@ -715,24 +794,16 @@ static void bch2_read_endio(struct bio *bio) +@@ -715,16 +805,8 @@ static void bch2_read_endio(struct bio *bio) if (!rbio->split) rbio->bio.bi_end_io = rbio->end_io; @@ -16071,17 +15299,7 @@ index b3b934a87c6d..6276f375dbc9 100644 return; } -- if (((rbio->flags & BCH_READ_RETRY_IF_STALE) && race_fault()) || -+ if (((rbio->flags & BCH_READ_retry_if_stale) && race_fault()) || - (ca && dev_ptr_stale(ca, &rbio->pick.ptr))) { - trace_and_count(c, read_reuse_race, &rbio->bio); - -- if (rbio->flags & BCH_READ_RETRY_IF_STALE) -+ if (rbio->flags & BCH_READ_retry_if_stale) - bch2_rbio_error(rbio, READ_RETRY, BLK_STS_AGAIN); - else - bch2_rbio_error(rbio, READ_ERR, BLK_STS_AGAIN); -@@ -750,45 +821,6 @@ static void bch2_read_endio(struct bio *bio) +@@ -750,45 +832,6 @@ static void bch2_read_endio(struct bio *bio) bch2_rbio_punt(rbio, __bch2_read_endio, context, wq); } @@ -16127,15 +15345,7 @@ index b3b934a87c6d..6276f375dbc9 100644 static noinline void read_from_stale_dirty_pointer(struct btree_trans *trans, struct bch_dev *ca, struct bkey_s_c k, -@@ -845,7 +877,6 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - struct bch_fs *c = trans->c; - struct extent_ptr_decoded pick; - struct bch_read_bio *rbio = NULL; -- struct promote_op *promote = NULL; - bool bounce = false, read_full = false, narrow_crcs = false; - struct bpos data_pos = bkey_start_pos(k.k); - int pick_ret; -@@ -868,15 +899,24 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, +@@ -868,15 +911,24 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, if (!pick_ret) goto hole; @@ -16166,188 +15376,16 @@ index b3b934a87c6d..6276f375dbc9 100644 printbuf_exit(&buf); goto err; } -@@ -889,7 +929,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - * retry path, don't check here, it'll be caught in bch2_read_endio() - * and we'll end up in the retry path: - */ -- if ((flags & BCH_READ_IN_RETRY) && -+ if ((flags & BCH_READ_in_retry) && - !pick.ptr.cached && - ca && - unlikely(dev_ptr_stale(ca, &pick.ptr))) { -@@ -903,48 +943,52 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - * Unlock the iterator while the btree node's lock is still in - * cache, before doing the IO: - */ -- bch2_trans_unlock(trans); -+ if (!(flags & BCH_READ_in_retry)) -+ bch2_trans_unlock(trans); -+ else -+ bch2_trans_unlock_long(trans); -+ -+ if (!(flags & BCH_READ_data_update)) { -+ if (!(flags & BCH_READ_last_fragment) || -+ bio_flagged(&orig->bio, BIO_CHAIN)) -+ flags |= BCH_READ_must_clone; -+ -+ narrow_crcs = !(flags & BCH_READ_in_retry) && -+ bch2_can_narrow_extent_crcs(k, pick.crc); -+ -+ if (narrow_crcs && (flags & BCH_READ_user_mapped)) -+ flags |= BCH_READ_must_bounce; - -- if (flags & BCH_READ_NODECODE) { -+ EBUG_ON(offset_into_extent + bvec_iter_sectors(iter) > k.k->size); -+ -+ if (crc_is_compressed(pick.crc) || -+ (pick.crc.csum_type != BCH_CSUM_none && -+ (bvec_iter_sectors(iter) != pick.crc.uncompressed_size || -+ (bch2_csum_type_is_encryption(pick.crc.csum_type) && -+ (flags & BCH_READ_user_mapped)) || -+ (flags & BCH_READ_must_bounce)))) { -+ read_full = true; -+ bounce = true; -+ } -+ } else { -+ read_full = true; - /* - * can happen if we retry, and the extent we were going to read - * has been merged in the meantime: - */ -- if (pick.crc.compressed_size > orig->bio.bi_vcnt * PAGE_SECTORS) { -+ struct data_update *u = container_of(orig, struct data_update, rbio); -+ if (pick.crc.compressed_size > u->op.wbio.bio.bi_iter.bi_size) { - if (ca) - percpu_ref_put(&ca->io_ref); - goto hole; - } - - iter.bi_size = pick.crc.compressed_size << 9; -- goto get_bio; -- } -- -- if (!(flags & BCH_READ_LAST_FRAGMENT) || -- bio_flagged(&orig->bio, BIO_CHAIN)) -- flags |= BCH_READ_MUST_CLONE; -- -- narrow_crcs = !(flags & BCH_READ_IN_RETRY) && -- bch2_can_narrow_extent_crcs(k, pick.crc); -- -- if (narrow_crcs && (flags & BCH_READ_USER_MAPPED)) -- flags |= BCH_READ_MUST_BOUNCE; -- -- EBUG_ON(offset_into_extent + bvec_iter_sectors(iter) > k.k->size); -- -- if (crc_is_compressed(pick.crc) || -- (pick.crc.csum_type != BCH_CSUM_none && -- (bvec_iter_sectors(iter) != pick.crc.uncompressed_size || -- (bch2_csum_type_is_encryption(pick.crc.csum_type) && -- (flags & BCH_READ_USER_MAPPED)) || -- (flags & BCH_READ_MUST_BOUNCE)))) { -- read_full = true; -- bounce = true; +@@ -942,7 +994,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, + bounce = true; } - if (orig->opts.promote_target)// || failed) -- promote = promote_alloc(trans, iter, k, &pick, orig->opts, flags, -- &rbio, &bounce, &read_full, failed); + if (orig->opts.promote_target || have_io_error(failed)) -+ rbio = promote_alloc(trans, iter, k, &pick, flags, orig, -+ &bounce, &read_full, failed); + promote = promote_alloc(trans, iter, k, &pick, orig->opts, flags, + &rbio, &bounce, &read_full, failed); - if (!read_full) { - EBUG_ON(crc_is_compressed(pick.crc)); -@@ -963,7 +1007,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - pick.crc.offset = 0; - pick.crc.live_size = bvec_iter_sectors(iter); - } --get_bio: -+ - if (rbio) { - /* - * promote already allocated bounce rbio: -@@ -978,17 +1022,16 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - } else if (bounce) { - unsigned sectors = pick.crc.compressed_size; - -- rbio = rbio_init(bio_alloc_bioset(NULL, -+ rbio = rbio_init_fragment(bio_alloc_bioset(NULL, - DIV_ROUND_UP(sectors, PAGE_SECTORS), - 0, - GFP_NOFS, - &c->bio_read_split), -- orig->opts); -+ orig); - - bch2_bio_alloc_pages_pool(c, &rbio->bio, sectors << 9); - rbio->bounce = true; -- rbio->split = true; -- } else if (flags & BCH_READ_MUST_CLONE) { -+ } else if (flags & BCH_READ_must_clone) { - /* - * Have to clone if there were any splits, due to error - * reporting issues (if a split errored, and retrying didn't -@@ -997,11 +1040,10 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - * from the whole bio, in which case we don't want to retry and - * lose the error) - */ -- rbio = rbio_init(bio_alloc_clone(NULL, &orig->bio, GFP_NOFS, -+ rbio = rbio_init_fragment(bio_alloc_clone(NULL, &orig->bio, GFP_NOFS, - &c->bio_read_split), -- orig->opts); -+ orig); - rbio->bio.bi_iter = iter; -- rbio->split = true; - } else { - rbio = orig; - rbio->bio.bi_iter = iter; -@@ -1010,11 +1052,8 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - - EBUG_ON(bio_sectors(&rbio->bio) != pick.crc.compressed_size); - -- rbio->c = c; - rbio->submit_time = local_clock(); -- if (rbio->split) -- rbio->parent = orig; -- else -+ if (!rbio->split) - rbio->end_io = orig->bio.bi_end_io; - rbio->bvec_iter = iter; - rbio->offset_into_extent= offset_into_extent; -@@ -1024,20 +1063,14 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - rbio->hole = 0; - rbio->retry = 0; - rbio->context = 0; -- /* XXX: only initialize this if needed */ -- rbio->devs_have = bch2_bkey_devs(k); - rbio->pick = pick; - rbio->subvol = orig->subvol; - rbio->read_pos = read_pos; - rbio->data_btree = data_btree; - rbio->data_pos = data_pos; - rbio->version = k.k->bversion; -- rbio->promote = promote; - INIT_WORK(&rbio->work, NULL); - -- if (flags & BCH_READ_NODECODE) -- orig->pick = pick; -- - rbio->bio.bi_opf = orig->bio.bi_opf; - rbio->bio.bi_iter.bi_sector = pick.ptr.offset; - rbio->bio.bi_end_io = bch2_read_endio; -@@ -1052,21 +1085,25 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - * If it's being moved internally, we don't want to flag it as a cache - * hit: - */ -- if (ca && pick.ptr.cached && !(flags & BCH_READ_NODECODE)) -+ if (ca && pick.ptr.cached && !(flags & BCH_READ_data_update)) - bch2_bucket_io_time_reset(trans, pick.ptr.dev, - PTR_BUCKET_NR(ca, &pick.ptr), READ); - -- if (!(flags & (BCH_READ_IN_RETRY|BCH_READ_LAST_FRAGMENT))) { -+ if (!(flags & (BCH_READ_in_retry|BCH_READ_last_fragment))) { - bio_inc_remaining(&orig->bio); - trace_and_count(c, read_split, &orig->bio); +@@ -1062,11 +1114,15 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, } if (!rbio->pick.idx) { @@ -16368,72 +15406,7 @@ index b3b934a87c6d..6276f375dbc9 100644 bch2_rbio_error(rbio, READ_RETRY_AVOID, BLK_STS_IOERR); goto out; } -@@ -1076,10 +1113,10 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - bio_set_dev(&rbio->bio, ca->disk_sb.bdev); - - if (unlikely(c->opts.no_data_io)) { -- if (likely(!(flags & BCH_READ_IN_RETRY))) -+ if (likely(!(flags & BCH_READ_in_retry))) - bio_endio(&rbio->bio); - } else { -- if (likely(!(flags & BCH_READ_IN_RETRY))) -+ if (likely(!(flags & BCH_READ_in_retry))) - submit_bio(&rbio->bio); - else - submit_bio_wait(&rbio->bio); -@@ -1097,11 +1134,11 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - goto out; - } - -- if (likely(!(flags & BCH_READ_IN_RETRY))) -+ if (likely(!(flags & BCH_READ_in_retry))) - bio_endio(&rbio->bio); - } - out: -- if (likely(!(flags & BCH_READ_IN_RETRY))) { -+ if (likely(!(flags & BCH_READ_in_retry))) { - return 0; - } else { - int ret; -@@ -1124,7 +1161,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - } - - err: -- if (flags & BCH_READ_IN_RETRY) -+ if (flags & BCH_READ_in_retry) - return READ_ERR; - - orig->bio.bi_status = BLK_STS_IOERR; -@@ -1132,16 +1169,16 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, - - hole: - /* -- * won't normally happen in the BCH_READ_NODECODE -+ * won't normally happen in the BCH_READ_data_update - * (bch2_move_extent()) path, but if we retry and the extent we wanted - * to read no longer exists we have to signal that: - */ -- if (flags & BCH_READ_NODECODE) -+ if (flags & BCH_READ_data_update) - orig->hole = true; - - zero_fill_bio_iter(&orig->bio, iter); - out_read_done: -- if (flags & BCH_READ_LAST_FRAGMENT) -+ if (flags & BCH_READ_last_fragment) - bch2_rbio_done(orig); - return 0; - } -@@ -1156,7 +1193,7 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, - struct bkey_s_c k; - int ret; - -- BUG_ON(flags & BCH_READ_NODECODE); -+ BUG_ON(flags & BCH_READ_data_update); - - bch2_bkey_buf_init(&sk); - bch2_trans_iter_init(trans, &iter, BTREE_ID_extents, -@@ -1164,7 +1201,6 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, +@@ -1164,7 +1220,6 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, BTREE_ITER_slots); while (1) { @@ -16441,7 +15414,7 @@ index b3b934a87c6d..6276f375dbc9 100644 enum btree_id data_btree = BTREE_ID_extents; bch2_trans_begin(trans); -@@ -1184,9 +1220,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, +@@ -1184,9 +1239,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, if (ret) goto err; @@ -16453,7 +15426,7 @@ index b3b934a87c6d..6276f375dbc9 100644 bch2_bkey_buf_reassemble(&sk, c, k); -@@ -1201,13 +1237,13 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, +@@ -1201,9 +1256,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, * With indirect extents, the amount of data to read is the min * of the original extent and the indirect extent: */ @@ -16465,21 +15438,7 @@ index b3b934a87c6d..6276f375dbc9 100644 swap(bvec_iter.bi_size, bytes); if (bvec_iter.bi_size == bytes) -- flags |= BCH_READ_LAST_FRAGMENT; -+ flags |= BCH_READ_last_fragment; - - ret = __bch2_read_extent(trans, rbio, bvec_iter, iter.pos, - data_btree, k, -@@ -1215,7 +1251,7 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, - if (ret) - goto err; - -- if (flags & BCH_READ_LAST_FRAGMENT) -+ if (flags & BCH_READ_last_fragment) - break; - - swap(bvec_iter.bi_size, bytes); -@@ -1229,16 +1265,20 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, +@@ -1229,16 +1284,20 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, } bch2_trans_iter_exit(trans, &iter); @@ -16506,7 +15465,7 @@ index b3b934a87c6d..6276f375dbc9 100644 void bch2_fs_io_read_exit(struct bch_fs *c) diff --git a/fs/bcachefs/io_read.h b/fs/bcachefs/io_read.h -index d9c18bb7d403..f54c9943e34a 100644 +index d9c18bb7d403..a82e8a94ccb6 100644 --- a/fs/bcachefs/io_read.h +++ b/fs/bcachefs/io_read.h @@ -3,6 +3,7 @@ @@ -16517,37 +15476,7 @@ index d9c18bb7d403..f54c9943e34a 100644 struct bch_read_bio { struct bch_fs *c; -@@ -34,9 +35,9 @@ struct bch_read_bio { - u16 flags; - union { - struct { -- u16 bounce:1, -+ u16 promote:1, -+ bounce:1, - split:1, -- kmalloc:1, - have_ioref:1, - narrow_crcs:1, - hole:1, -@@ -46,8 +47,6 @@ struct bch_read_bio { - u16 _state; - }; - -- struct bch_devs_list devs_have; -- - struct extent_ptr_decoded pick; - - /* -@@ -64,8 +63,6 @@ struct bch_read_bio { - struct bpos data_pos; - struct bversion version; - -- struct promote_op *promote; -- - struct bch_io_opts opts; - - struct work_struct work; -@@ -79,32 +76,54 @@ struct bch_devs_mask; +@@ -79,19 +80,32 @@ struct bch_devs_mask; struct cache_promote_op; struct extent_ptr_decoded; @@ -16586,90 +15515,9 @@ index d9c18bb7d403..f54c9943e34a 100644 + return 0; } -+#define BCH_READ_FLAGS() \ -+ x(retry_if_stale) \ -+ x(may_promote) \ -+ x(user_mapped) \ -+ x(data_update) \ -+ x(last_fragment) \ -+ x(must_bounce) \ -+ x(must_clone) \ -+ x(in_retry) -+ -+enum __bch_read_flags { -+#define x(n) __BCH_READ_##n, -+ BCH_READ_FLAGS() -+#undef x -+}; -+ enum bch_read_flags { -- BCH_READ_RETRY_IF_STALE = 1 << 0, -- BCH_READ_MAY_PROMOTE = 1 << 1, -- BCH_READ_USER_MAPPED = 1 << 2, -- BCH_READ_NODECODE = 1 << 3, -- BCH_READ_LAST_FRAGMENT = 1 << 4, -- -- /* internal: */ -- BCH_READ_MUST_BOUNCE = 1 << 5, -- BCH_READ_MUST_CLONE = 1 << 6, -- BCH_READ_IN_RETRY = 1 << 7, -+#define x(n) BCH_READ_##n = BIT(__BCH_READ_##n), -+ BCH_READ_FLAGS() -+#undef x - }; - - int __bch2_read_extent(struct btree_trans *, struct bch_read_bio *, -@@ -131,24 +150,39 @@ static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, - - BUG_ON(rbio->_state); - -- rbio->c = c; -- rbio->start_time = local_clock(); - rbio->subvol = inum.subvol; - - __bch2_read(c, rbio, rbio->bio.bi_iter, inum, &failed, -- BCH_READ_RETRY_IF_STALE| -- BCH_READ_MAY_PROMOTE| -- BCH_READ_USER_MAPPED); -+ BCH_READ_retry_if_stale| -+ BCH_READ_may_promote| -+ BCH_READ_user_mapped); - } - --static inline struct bch_read_bio *rbio_init(struct bio *bio, -- struct bch_io_opts opts) -+static inline struct bch_read_bio *rbio_init_fragment(struct bio *bio, -+ struct bch_read_bio *orig) - { - struct bch_read_bio *rbio = to_rbio(bio); - -+ rbio->c = orig->c; - rbio->_state = 0; -- rbio->promote = NULL; -- rbio->opts = opts; -+ rbio->split = true; -+ rbio->parent = orig; -+ rbio->opts = orig->opts; -+ return rbio; -+} -+ -+static inline struct bch_read_bio *rbio_init(struct bio *bio, -+ struct bch_fs *c, -+ struct bch_io_opts opts, -+ bio_end_io_t end_io) -+{ -+ struct bch_read_bio *rbio = to_rbio(bio); -+ -+ rbio->start_time = local_clock(); -+ rbio->c = c; -+ rbio->_state = 0; -+ rbio->opts = opts; -+ rbio->bio.bi_end_io = end_io; - return rbio; - } - diff --git a/fs/bcachefs/io_write.c b/fs/bcachefs/io_write.c -index 96720adcfee0..92abc239599d 100644 +index 96720adcfee0..dd508d93e9fc 100644 --- a/fs/bcachefs/io_write.c +++ b/fs/bcachefs/io_write.c @@ -164,7 +164,7 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans, @@ -16689,7 +15537,7 @@ index 96720adcfee0..92abc239599d 100644 BTREE_ITER_cached); int ret = bkey_err(k); if (unlikely(ret)) -@@ -369,11 +370,11 @@ static int bch2_write_index_default(struct bch_write_op *op) +@@ -369,7 +370,7 @@ static int bch2_write_index_default(struct bch_write_op *op) bkey_start_pos(&sk.k->k), BTREE_ITER_slots|BTREE_ITER_intent); @@ -16698,11 +15546,6 @@ index 96720adcfee0..92abc239599d 100644 bch2_extent_update(trans, inum, &iter, sk.k, &op->res, op->new_i_size, &op->i_sectors_delta, -- op->flags & BCH_WRITE_CHECK_ENOSPC); -+ op->flags & BCH_WRITE_check_enospc); - bch2_trans_iter_exit(trans, &iter); - - if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) @@ -395,6 +396,21 @@ static int bch2_write_index_default(struct bch_write_op *op) /* Writes */ @@ -16714,7 +15557,7 @@ index 96720adcfee0..92abc239599d 100644 + (subvol_inum) { op->subvol, op->pos.inode, }, + offset << 9); + prt_printf(out, "write error%s: ", -+ op->flags & BCH_WRITE_move ? "(internal move)" : ""); ++ op->flags & BCH_WRITE_MOVE ? "(internal move)" : ""); +} + +void bch2_write_op_error(struct printbuf *out, struct bch_write_op *op) @@ -16725,33 +15568,6 @@ index 96720adcfee0..92abc239599d 100644 void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c, enum bch_data_type type, const struct bkey_i *k, -@@ -467,7 +483,7 @@ static void bch2_write_done(struct closure *cl) - bch2_time_stats_update(&c->times[BCH_TIME_data_write], op->start_time); - bch2_disk_reservation_put(c, &op->res); - -- if (!(op->flags & BCH_WRITE_MOVE)) -+ if (!(op->flags & BCH_WRITE_move)) - bch2_write_ref_put(c, BCH_WRITE_REF_write); - bch2_keylist_free(&op->insert_keys, op->inline_keys); - -@@ -513,7 +529,7 @@ static void __bch2_write_index(struct bch_write_op *op) - unsigned dev; - int ret = 0; - -- if (unlikely(op->flags & BCH_WRITE_IO_ERROR)) { -+ if (unlikely(op->flags & BCH_WRITE_io_error)) { - ret = bch2_write_drop_io_error_ptrs(op); - if (ret) - goto err; -@@ -522,7 +538,7 @@ static void __bch2_write_index(struct bch_write_op *op) - if (!bch2_keylist_empty(keys)) { - u64 sectors_start = keylist_sectors(keys); - -- ret = !(op->flags & BCH_WRITE_MOVE) -+ ret = !(op->flags & BCH_WRITE_move) - ? bch2_write_index_default(op) - : bch2_data_update_index_update(op); - @@ -531,14 +547,14 @@ static void __bch2_write_index(struct bch_write_op *op) op->written += sectors_start - keylist_sectors(keys); @@ -16773,27 +15589,7 @@ index 96720adcfee0..92abc239599d 100644 } if (ret) -@@ -554,7 +570,7 @@ static void __bch2_write_index(struct bch_write_op *op) - err: - keys->top = keys->keys; - op->error = ret; -- op->flags |= BCH_WRITE_SUBMITTED; -+ op->flags |= BCH_WRITE_submitted; - goto out; - } - -@@ -589,8 +605,8 @@ static CLOSURE_CALLBACK(bch2_write_index) - struct workqueue_struct *wq = index_update_wq(op); - unsigned long flags; - -- if ((op->flags & BCH_WRITE_SUBMITTED) && -- (op->flags & BCH_WRITE_MOVE)) -+ if ((op->flags & BCH_WRITE_submitted) && -+ (op->flags & BCH_WRITE_move)) - bch2_bio_free_pages_pool(op->c, &op->wbio.bio); - - spin_lock_irqsave(&wp->writes_lock, flags); -@@ -621,20 +637,18 @@ void bch2_write_point_do_index_updates(struct work_struct *work) +@@ -621,9 +637,7 @@ void bch2_write_point_do_index_updates(struct work_struct *work) while (1) { spin_lock_irq(&wp->writes_lock); @@ -16804,46 +15600,6 @@ index 96720adcfee0..92abc239599d 100644 wp_update_state(wp, op != NULL); spin_unlock_irq(&wp->writes_lock); - if (!op) - break; - -- op->flags |= BCH_WRITE_IN_WORKER; -+ op->flags |= BCH_WRITE_in_worker; - - __bch2_write_index(op); - -- if (!(op->flags & BCH_WRITE_SUBMITTED)) -+ if (!(op->flags & BCH_WRITE_submitted)) - __bch2_write(op); - else - bch2_write_done(&op->cl); -@@ -658,7 +672,7 @@ static void bch2_write_endio(struct bio *bio) - "data write error: %s", - bch2_blk_status_to_str(bio->bi_status))) { - set_bit(wbio->dev, op->failed.d); -- op->flags |= BCH_WRITE_IO_ERROR; -+ op->flags |= BCH_WRITE_io_error; - } - - if (wbio->nocow) { -@@ -705,7 +719,7 @@ static void init_append_extent(struct bch_write_op *op, - bch2_extent_crc_append(&e->k_i, crc); - - bch2_alloc_sectors_append_ptrs_inlined(op->c, wp, &e->k_i, crc.compressed_size, -- op->flags & BCH_WRITE_CACHED); -+ op->flags & BCH_WRITE_cached); - - bch2_keylist_push(&op->insert_keys); - } -@@ -822,7 +836,7 @@ static enum prep_encoded_ret { - struct bch_fs *c = op->c; - struct bio *bio = &op->wbio.bio; - -- if (!(op->flags & BCH_WRITE_DATA_ENCODED)) -+ if (!(op->flags & BCH_WRITE_data_encoded)) - return PREP_ENCODED_OK; - - BUG_ON(bio_sectors(bio) != op->crc.compressed_size); @@ -859,7 +873,7 @@ static enum prep_encoded_ret { if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io) return PREP_ENCODED_CHECKSUM_ERR; @@ -16853,45 +15609,6 @@ index 96720adcfee0..92abc239599d 100644 return PREP_ENCODED_ERR; } -@@ -930,9 +944,9 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp, - if (ec_buf || - op->compression_opt || - (op->csum_type && -- !(op->flags & BCH_WRITE_PAGES_STABLE)) || -+ !(op->flags & BCH_WRITE_pages_stable)) || - (bch2_csum_type_is_encryption(op->csum_type) && -- !(op->flags & BCH_WRITE_PAGES_OWNED))) { -+ !(op->flags & BCH_WRITE_pages_owned))) { - dst = bch2_write_bio_alloc(c, wp, src, - &page_alloc_failed, - ec_buf); -@@ -952,7 +966,7 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp, - break; - - BUG_ON(op->compression_opt && -- (op->flags & BCH_WRITE_DATA_ENCODED) && -+ (op->flags & BCH_WRITE_data_encoded) && - bch2_csum_type_is_encryption(op->crc.csum_type)); - BUG_ON(op->compression_opt && !bounce); - -@@ -990,7 +1004,7 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp, - } - } - -- if ((op->flags & BCH_WRITE_DATA_ENCODED) && -+ if ((op->flags & BCH_WRITE_data_encoded) && - !crc_is_compressed(crc) && - bch2_csum_type_is_encryption(op->crc.csum_type) == - bch2_csum_type_is_encryption(op->csum_type)) { -@@ -1022,7 +1036,7 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp, - crc.compression_type = compression_type; - crc.nonce = nonce; - } else { -- if ((op->flags & BCH_WRITE_DATA_ENCODED) && -+ if ((op->flags & BCH_WRITE_data_encoded) && - bch2_rechecksum_bio(c, src, version, op->crc, - NULL, &op->crc, - src_len >> 9, @@ -1080,11 +1094,14 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp, *_dst = dst; return more; @@ -16938,64 +15655,7 @@ index 96720adcfee0..92abc239599d 100644 } if (ret) { -@@ -1193,9 +1210,9 @@ static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op) - - static void __bch2_nocow_write_done(struct bch_write_op *op) - { -- if (unlikely(op->flags & BCH_WRITE_IO_ERROR)) { -+ if (unlikely(op->flags & BCH_WRITE_io_error)) { - op->error = -EIO; -- } else if (unlikely(op->flags & BCH_WRITE_CONVERT_UNWRITTEN)) -+ } else if (unlikely(op->flags & BCH_WRITE_convert_unwritten)) - bch2_nocow_write_convert_unwritten(op); - } - -@@ -1224,7 +1241,7 @@ static void bch2_nocow_write(struct bch_write_op *op) - struct bucket_to_lock *stale_at; - int stale, ret; - -- if (op->flags & BCH_WRITE_MOVE) -+ if (op->flags & BCH_WRITE_move) - return; - - darray_init(&buckets); -@@ -1282,7 +1299,7 @@ static void bch2_nocow_write(struct bch_write_op *op) - }), GFP_KERNEL|__GFP_NOFAIL); - - if (ptr->unwritten) -- op->flags |= BCH_WRITE_CONVERT_UNWRITTEN; -+ op->flags |= BCH_WRITE_convert_unwritten; - } - - /* Unlock before taking nocow locks, doing IO: */ -@@ -1290,7 +1307,7 @@ static void bch2_nocow_write(struct bch_write_op *op) - bch2_trans_unlock(trans); - - bch2_cut_front(op->pos, op->insert_keys.top); -- if (op->flags & BCH_WRITE_CONVERT_UNWRITTEN) -+ if (op->flags & BCH_WRITE_convert_unwritten) - bch2_cut_back(POS(op->pos.inode, op->pos.offset + bio_sectors(bio)), op->insert_keys.top); - - darray_for_each(buckets, i) { -@@ -1315,7 +1332,7 @@ static void bch2_nocow_write(struct bch_write_op *op) - wbio_init(bio)->put_bio = true; - bio->bi_opf = op->wbio.bio.bi_opf; - } else { -- op->flags |= BCH_WRITE_SUBMITTED; -+ op->flags |= BCH_WRITE_submitted; - } - - op->pos.offset += bio_sectors(bio); -@@ -1329,7 +1346,7 @@ static void bch2_nocow_write(struct bch_write_op *op) - op->insert_keys.top, true); - - bch2_keylist_push(&op->insert_keys); -- if (op->flags & BCH_WRITE_SUBMITTED) -+ if (op->flags & BCH_WRITE_submitted) - break; - bch2_btree_iter_advance(&iter); - } -@@ -1339,23 +1356,25 @@ static void bch2_nocow_write(struct bch_write_op *op) +@@ -1339,17 +1356,19 @@ static void bch2_nocow_write(struct bch_write_op *op) if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) goto retry; @@ -17012,48 +15672,19 @@ index 96720adcfee0..92abc239599d 100644 + bch_err_ratelimited(c, "%s", buf.buf); + printbuf_exit(&buf); op->error = ret; -- op->flags |= BCH_WRITE_SUBMITTED; -+ op->flags |= BCH_WRITE_submitted; + op->flags |= BCH_WRITE_SUBMITTED; } - bch2_trans_put(trans); - darray_exit(&buckets); - /* fallback to cow write path? */ -- if (!(op->flags & BCH_WRITE_SUBMITTED)) { -+ if (!(op->flags & BCH_WRITE_submitted)) { + if (!(op->flags & BCH_WRITE_SUBMITTED)) { closure_sync(&op->cl); - __bch2_nocow_write_done(op); - op->insert_keys.top = op->insert_keys.keys; -- } else if (op->flags & BCH_WRITE_SYNC) { -+ } else if (op->flags & BCH_WRITE_sync) { - closure_sync(&op->cl); - bch2_nocow_write_done(&op->cl.work); - } else { -@@ -1407,7 +1426,7 @@ static void __bch2_write(struct bch_write_op *op) - - if (unlikely(op->opts.nocow && c->opts.nocow_enabled)) { - bch2_nocow_write(op); -- if (op->flags & BCH_WRITE_SUBMITTED) -+ if (op->flags & BCH_WRITE_submitted) - goto out_nofs_restore; - } - again: -@@ -1437,7 +1456,7 @@ static void __bch2_write(struct bch_write_op *op) - ret = bch2_trans_run(c, lockrestart_do(trans, - bch2_alloc_sectors_start_trans(trans, - op->target, -- op->opts.erasure_code && !(op->flags & BCH_WRITE_CACHED), -+ op->opts.erasure_code && !(op->flags & BCH_WRITE_cached), - op->write_point, - &op->devs_have, - op->nr_replicas, -@@ -1460,16 +1479,16 @@ static void __bch2_write(struct bch_write_op *op) - bch2_alloc_sectors_done_inlined(c, wp); - err: +@@ -1462,14 +1481,14 @@ static void __bch2_write(struct bch_write_op *op) if (ret <= 0) { -- op->flags |= BCH_WRITE_SUBMITTED; -- + op->flags |= BCH_WRITE_SUBMITTED; + - if (ret < 0) { - if (!(op->flags & BCH_WRITE_ALLOC_NOWAIT)) - bch_err_inum_offset_ratelimited(c, @@ -17062,10 +15693,8 @@ index 96720adcfee0..92abc239599d 100644 - "%s(): %s error: %s", __func__, - op->flags & BCH_WRITE_MOVE ? "move" : "user", - bch2_err_str(ret)); -+ op->flags |= BCH_WRITE_submitted; -+ + if (unlikely(ret < 0)) { -+ if (!(op->flags & BCH_WRITE_alloc_nowait)) { ++ if (!(op->flags & BCH_WRITE_ALLOC_NOWAIT)) { + struct printbuf buf = PRINTBUF; + bch2_write_op_error(&buf, op); + prt_printf(&buf, "%s(): %s", __func__, bch2_err_str(ret)); @@ -17075,47 +15704,7 @@ index 96720adcfee0..92abc239599d 100644 op->error = ret; break; } -@@ -1495,14 +1514,14 @@ static void __bch2_write(struct bch_write_op *op) - * synchronously here if we weren't able to submit all of the IO at - * once, as that signals backpressure to the caller. - */ -- if ((op->flags & BCH_WRITE_SYNC) || -- (!(op->flags & BCH_WRITE_SUBMITTED) && -- !(op->flags & BCH_WRITE_IN_WORKER))) { -+ if ((op->flags & BCH_WRITE_sync) || -+ (!(op->flags & BCH_WRITE_submitted) && -+ !(op->flags & BCH_WRITE_in_worker))) { - bch2_wait_on_allocator(c, &op->cl); - - __bch2_write_index(op); - -- if (!(op->flags & BCH_WRITE_SUBMITTED)) -+ if (!(op->flags & BCH_WRITE_submitted)) - goto again; - bch2_write_done(&op->cl); - } else { -@@ -1523,8 +1542,8 @@ static void bch2_write_data_inline(struct bch_write_op *op, unsigned data_len) - - memset(&op->failed, 0, sizeof(op->failed)); - -- op->flags |= BCH_WRITE_WROTE_DATA_INLINE; -- op->flags |= BCH_WRITE_SUBMITTED; -+ op->flags |= BCH_WRITE_wrote_data_inline; -+ op->flags |= BCH_WRITE_submitted; - - bch2_check_set_feature(op->c, BCH_FEATURE_inline_data); - -@@ -1587,20 +1606,19 @@ CLOSURE_CALLBACK(bch2_write) - BUG_ON(!op->write_point.v); - BUG_ON(bkey_eq(op->pos, POS_MAX)); - -- if (op->flags & BCH_WRITE_ONLY_SPECIFIED_DEVS) -- op->flags |= BCH_WRITE_ALLOC_NOWAIT; -+ if (op->flags & BCH_WRITE_only_specified_devs) -+ op->flags |= BCH_WRITE_alloc_nowait; - - op->nr_replicas_required = min_t(unsigned, op->nr_replicas_required, op->nr_replicas); - op->start_time = local_clock(); +@@ -1595,12 +1614,11 @@ CLOSURE_CALLBACK(bch2_write) bch2_keylist_init(&op->insert_keys, op->inline_keys); wbio_init(bio)->put_bio = false; @@ -17133,73 +15722,21 @@ index 96720adcfee0..92abc239599d 100644 op->error = -EIO; goto err; } -@@ -1610,7 +1628,7 @@ CLOSURE_CALLBACK(bch2_write) - goto err; - } - -- if (!(op->flags & BCH_WRITE_MOVE) && -+ if (!(op->flags & BCH_WRITE_move) && - !bch2_write_ref_tryget(c, BCH_WRITE_REF_write)) { - op->error = -BCH_ERR_erofs_no_writes; - goto err; diff --git a/fs/bcachefs/io_write.h b/fs/bcachefs/io_write.h -index 5400ce94ee57..02cca52be0bd 100644 +index 5400ce94ee57..b4626013abc8 100644 --- a/fs/bcachefs/io_write.h +++ b/fs/bcachefs/io_write.h -@@ -20,22 +20,23 @@ static inline void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw +@@ -20,6 +20,8 @@ static inline void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw void bch2_submit_wbio_replicas(struct bch_write_bio *, struct bch_fs *, enum bch_data_type, const struct bkey_i *, bool); +void bch2_write_op_error(struct printbuf *out, struct bch_write_op *op); + #define BCH_WRITE_FLAGS() \ -- x(ALLOC_NOWAIT) \ -- x(CACHED) \ -- x(DATA_ENCODED) \ -- x(PAGES_STABLE) \ -- x(PAGES_OWNED) \ -- x(ONLY_SPECIFIED_DEVS) \ -- x(WROTE_DATA_INLINE) \ -- x(FROM_INTERNAL) \ -- x(CHECK_ENOSPC) \ -- x(SYNC) \ -- x(MOVE) \ -- x(IN_WORKER) \ -- x(SUBMITTED) \ -- x(IO_ERROR) \ -- x(CONVERT_UNWRITTEN) -+ x(alloc_nowait) \ -+ x(cached) \ -+ x(data_encoded) \ -+ x(pages_stable) \ -+ x(pages_owned) \ -+ x(only_specified_devs) \ -+ x(wrote_data_inline) \ -+ x(check_enospc) \ -+ x(sync) \ -+ x(move) \ -+ x(in_worker) \ -+ x(submitted) \ -+ x(io_error) \ -+ x(convert_unwritten) - - enum __bch_write_flags { - #define x(f) __BCH_WRITE_##f, -diff --git a/fs/bcachefs/io_write_types.h b/fs/bcachefs/io_write_types.h -index 6e878a6f2f0b..3ef6df9145ef 100644 ---- a/fs/bcachefs/io_write_types.h -+++ b/fs/bcachefs/io_write_types.h -@@ -64,7 +64,7 @@ struct bch_write_op { - struct bpos pos; - struct bversion version; - -- /* For BCH_WRITE_DATA_ENCODED: */ -+ /* For BCH_WRITE_data_encoded: */ - struct bch_extent_crc_unpacked crc; - - struct write_point_specifier write_point; + x(ALLOC_NOWAIT) \ + x(CACHED) \ diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c -index 2dc0d60c1745..cb2c3722f674 100644 +index 2dc0d60c1745..24c294d4634e 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -113,11 +113,10 @@ journal_seq_to_buf(struct journal *j, u64 seq) @@ -17241,18 +15778,38 @@ index 2dc0d60c1745..cb2c3722f674 100644 /* Close out old buffer: */ buf->data->u64s = cpu_to_le32(old.cur_entry_offset); -@@ -373,6 +381,10 @@ static int journal_entry_open(struct journal *j) +@@ -311,6 +319,16 @@ void bch2_journal_halt(struct journal *j) + spin_unlock(&j->lock); + } + ++void bch2_journal_halt_locked(struct journal *j) ++{ ++ lockdep_assert_held(&j->lock); ++ ++ __journal_entry_close(j, JOURNAL_ENTRY_ERROR_VAL, true); ++ if (!j->err_seq) ++ j->err_seq = journal_cur_seq(j); ++ journal_wake(j); ++} ++ + static bool journal_entry_want_write(struct journal *j) + { + bool ret = !journal_entry_is_open(j) || +@@ -373,6 +391,13 @@ static int journal_entry_open(struct journal *j) if (nr_unwritten_journal_entries(j) == ARRAY_SIZE(j->buf)) return JOURNAL_ERR_max_in_flight; -+ if (bch2_fs_fatal_err_on(journal_cur_seq(j) >= JOURNAL_SEQ_MAX, -+ c, "cannot start: journal seq overflow")) ++ if (journal_cur_seq(j) >= JOURNAL_SEQ_MAX) { ++ bch_err(c, "cannot start: journal seq overflow"); ++ if (bch2_fs_emergency_read_only_locked(c)) ++ bch_err(c, "fatal error - emergency read only"); + return JOURNAL_ERR_insufficient_devices; /* -EROFS */ ++ } + BUG_ON(!j->cur_entry_sectors); buf->expires = -@@ -588,6 +600,16 @@ static int __journal_res_get(struct journal *j, struct journal_res *res, +@@ -588,6 +613,16 @@ static int __journal_res_get(struct journal *j, struct journal_res *res, : -BCH_ERR_journal_res_get_blocked; } @@ -17269,7 +15826,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 /* * Essentially the entry function to the journaling code. When bcachefs is doing * a btree insert, it calls this function to get the current journal write. -@@ -599,17 +621,31 @@ static int __journal_res_get(struct journal *j, struct journal_res *res, +@@ -599,17 +634,31 @@ static int __journal_res_get(struct journal *j, struct journal_res *res, * btree node write locks. */ int bch2_journal_res_get_slowpath(struct journal *j, struct journal_res *res, @@ -17303,7 +15860,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 struct printbuf buf = PRINTBUF; bch2_journal_debug_to_text(&buf, j); bch_err(c, "Journal stuck? Waited for 10 seconds...\n%s", -@@ -664,7 +700,7 @@ void bch2_journal_entry_res_resize(struct journal *j, +@@ -664,7 +713,7 @@ void bch2_journal_entry_res_resize(struct journal *j, * @seq: seq to flush * @parent: closure object to wait with * Returns: 1 if @seq has already been flushed, 0 if @seq is being flushed, @@ -17312,7 +15869,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 * * Like bch2_journal_wait_on_seq, except that it triggers a write immediately if * necessary -@@ -687,7 +723,7 @@ int bch2_journal_flush_seq_async(struct journal *j, u64 seq, +@@ -687,7 +736,7 @@ int bch2_journal_flush_seq_async(struct journal *j, u64 seq, /* Recheck under lock: */ if (j->err_seq && seq >= j->err_seq) { @@ -17321,7 +15878,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 goto out; } -@@ -714,7 +750,7 @@ int bch2_journal_flush_seq_async(struct journal *j, u64 seq, +@@ -714,7 +763,7 @@ int bch2_journal_flush_seq_async(struct journal *j, u64 seq, * livelock: */ sched_annotate_sleep(); @@ -17330,7 +15887,15 @@ index 2dc0d60c1745..cb2c3722f674 100644 if (ret) return ret; -@@ -794,10 +830,11 @@ int bch2_journal_flush(struct journal *j) +@@ -747,6 +796,7 @@ int bch2_journal_flush_seq_async(struct journal *j, u64 seq, + } + + buf->must_flush = true; ++ j->flushing_seq = max(j->flushing_seq, seq); + + if (parent && !closure_wait(&buf->wait, parent)) + BUG(); +@@ -794,10 +844,11 @@ int bch2_journal_flush(struct journal *j) } /* @@ -17344,7 +15909,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 { struct bch_fs *c = container_of(j, struct bch_fs, journal); u64 unwritten_seq; -@@ -806,15 +843,15 @@ bool bch2_journal_noflush_seq(struct journal *j, u64 seq) +@@ -806,15 +857,15 @@ bool bch2_journal_noflush_seq(struct journal *j, u64 seq) if (!(c->sb.features & (1ULL << BCH_FEATURE_journal_no_flush))) return false; @@ -17363,7 +15928,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 unwritten_seq++) { struct journal_buf *buf = journal_seq_to_buf(j, unwritten_seq); -@@ -831,19 +868,14 @@ bool bch2_journal_noflush_seq(struct journal *j, u64 seq) +@@ -831,19 +882,14 @@ bool bch2_journal_noflush_seq(struct journal *j, u64 seq) return ret; } @@ -17387,7 +15952,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 buf->must_flush = true; if (!buf->flush_time) { -@@ -856,27 +888,70 @@ int bch2_journal_meta(struct journal *j) +@@ -856,27 +902,70 @@ int bch2_journal_meta(struct journal *j) return bch2_journal_flush_seq(j, res.seq, TASK_UNINTERRUPTIBLE); } @@ -17461,7 +16026,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 { struct journal_buf *ret = NULL; -@@ -893,13 +968,17 @@ static struct journal_buf *__bch2_next_write_buffer_flush_journal_buf(struct jou +@@ -893,13 +982,17 @@ static struct journal_buf *__bch2_next_write_buffer_flush_journal_buf(struct jou struct journal_buf *buf = j->buf + idx; if (buf->need_flush_to_write_buffer) { @@ -17483,7 +16048,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 ? ERR_PTR(-EAGAIN) : buf; break; -@@ -912,11 +991,17 @@ static struct journal_buf *__bch2_next_write_buffer_flush_journal_buf(struct jou +@@ -912,11 +1005,17 @@ static struct journal_buf *__bch2_next_write_buffer_flush_journal_buf(struct jou return ret; } @@ -17503,7 +16068,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 return ret; } -@@ -945,19 +1030,17 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, +@@ -945,19 +1044,17 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, } for (nr_got = 0; nr_got < nr_want; nr_got++) { @@ -17533,7 +16098,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 ret = bch2_trans_run(c, bch2_trans_mark_metadata_bucket(trans, ca, ob[nr_got]->bucket, BCH_DATA_journal, -@@ -967,9 +1050,9 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, +@@ -967,9 +1064,9 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, bch_err_msg(c, ret, "marking new journal buckets"); break; } @@ -17545,7 +16110,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 } if (!nr_got) -@@ -1009,8 +1092,7 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, +@@ -1009,8 +1106,7 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, if (ret) goto err_unblock; @@ -17555,7 +16120,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 /* Commit: */ if (c) -@@ -1044,9 +1126,8 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, +@@ -1044,9 +1140,8 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, bu[i], BCH_DATA_free, 0, BTREE_TRIGGER_transactional)); err_free: @@ -17567,7 +16132,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 kfree(new_bucket_seq); kfree(new_buckets); -@@ -1193,7 +1274,7 @@ void bch2_fs_journal_stop(struct journal *j) +@@ -1193,7 +1288,7 @@ void bch2_fs_journal_stop(struct journal *j) * Always write a new journal entry, to make sure the clock hands are up * to date (and match the superblock) */ @@ -17576,7 +16141,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 journal_quiesce(j); cancel_delayed_work_sync(&j->write_work); -@@ -1217,6 +1298,11 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq) +@@ -1217,6 +1312,11 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq) bool had_entries = false; u64 last_seq = cur_seq, nr, seq; @@ -17588,7 +16153,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 genradix_for_each_reverse(&c->journal_entries, iter, _i) { i = *_i; -@@ -1474,6 +1560,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) +@@ -1474,6 +1574,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) case JOURNAL_ENTRY_CLOSED_VAL: prt_printf(out, "closed\n"); break; @@ -17598,7 +16163,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 default: prt_printf(out, "%u/%u\n", s.cur_entry_offset, j->cur_entry_u64s); break; -@@ -1499,6 +1588,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) +@@ -1499,6 +1602,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) printbuf_indent_sub(out, 2); for_each_member_device_rcu(c, ca, &c->rw_devs[BCH_DATA_journal]) { @@ -17608,7 +16173,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 struct journal_device *ja = &ca->journal; if (!test_bit(ca->dev_idx, c->rw_devs[BCH_DATA_journal].d)) -@@ -1508,6 +1600,7 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) +@@ -1508,6 +1614,7 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) continue; prt_printf(out, "dev %u:\n", ca->dev_idx); @@ -17616,7 +16181,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 printbuf_indent_add(out, 2); prt_printf(out, "nr\t%u\n", ja->nr); prt_printf(out, "bucket size\t%u\n", ca->mi.bucket_size); -@@ -1519,6 +1612,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) +@@ -1519,6 +1626,8 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) printbuf_indent_sub(out, 2); } @@ -17625,7 +16190,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 rcu_read_unlock(); --out->atomic; -@@ -1530,54 +1625,3 @@ void bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) +@@ -1530,54 +1639,3 @@ void bch2_journal_debug_to_text(struct printbuf *out, struct journal *j) __bch2_journal_debug_to_text(out, j); spin_unlock(&j->lock); } @@ -17681,7 +16246,7 @@ index 2dc0d60c1745..cb2c3722f674 100644 - seq++; -} diff --git a/fs/bcachefs/journal.h b/fs/bcachefs/journal.h -index 2762be6f9814..dccddd5420ad 100644 +index 2762be6f9814..107f7f901cd9 100644 --- a/fs/bcachefs/journal.h +++ b/fs/bcachefs/journal.h @@ -285,7 +285,8 @@ static inline void bch2_journal_buf_put(struct journal *j, unsigned idx, u64 seq @@ -17722,7 +16287,7 @@ index 2762be6f9814..dccddd5420ad 100644 if (ret) return ret; out: -@@ -403,7 +405,7 @@ void bch2_journal_flush_async(struct journal *, struct closure *); +@@ -403,15 +405,16 @@ void bch2_journal_flush_async(struct journal *, struct closure *); int bch2_journal_flush_seq(struct journal *, u64, unsigned); int bch2_journal_flush(struct journal *); @@ -17731,7 +16296,8 @@ index 2762be6f9814..dccddd5420ad 100644 int bch2_journal_meta(struct journal *); void bch2_journal_halt(struct journal *); -@@ -411,7 +413,7 @@ void bch2_journal_halt(struct journal *); ++void bch2_journal_halt_locked(struct journal *); + static inline int bch2_journal_error(struct journal *j) { return j->reservations.cur_entry_offset == JOURNAL_ENTRY_ERROR_VAL @@ -17740,7 +16306,7 @@ index 2762be6f9814..dccddd5420ad 100644 } struct bch_dev; -@@ -424,12 +426,10 @@ static inline void bch2_journal_set_replay_done(struct journal *j) +@@ -424,12 +427,10 @@ static inline void bch2_journal_set_replay_done(struct journal *j) void bch2_journal_unblock(struct journal *); void bch2_journal_block(struct journal *); @@ -18632,7 +17198,7 @@ index ec84c3345281..0a73d7134e1c 100644 + #endif /* _BCACHEFS_JOURNAL_RECLAIM_H */ diff --git a/fs/bcachefs/journal_types.h b/fs/bcachefs/journal_types.h -index 19183fcf7ad7..3ba433a48eb8 100644 +index 19183fcf7ad7..a198a81d7478 100644 --- a/fs/bcachefs/journal_types.h +++ b/fs/bcachefs/journal_types.h @@ -9,6 +9,9 @@ @@ -18691,6 +17257,14 @@ index 19183fcf7ad7..3ba433a48eb8 100644 struct delayed_work write_work; struct workqueue_struct *wq; +@@ -231,6 +237,7 @@ struct journal { + /* seq, last_seq from the most recent journal entry successfully written */ + u64 seq_ondisk; + u64 flushed_seq_ondisk; ++ u64 flushing_seq; + u64 last_seq_ondisk; + u64 err_seq; + u64 last_empty_seq; diff --git a/fs/bcachefs/logged_ops.c b/fs/bcachefs/logged_ops.c index 60e00702d1a4..75f27ec26f85 100644 --- a/fs/bcachefs/logged_ops.c @@ -18772,7 +17346,7 @@ index e6a7d8241bb8..f31a6cf1514c 100644 void bch2_lru_pos_to_text(struct printbuf *, struct bpos); diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c -index 0ef4a86850bb..ff787d3d50d2 100644 +index 0ef4a86850bb..c493ea625553 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -21,6 +21,8 @@ @@ -18784,61 +17358,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 #include "replicas.h" #include "snapshot.h" #include "super-io.h" -@@ -72,11 +74,7 @@ struct moving_io { - unsigned read_sectors; - unsigned write_sectors; - -- struct bch_read_bio rbio; -- - struct data_update write; -- /* Must be last since it is variable size */ -- struct bio_vec bi_inline_vecs[]; - }; - - static void move_free(struct moving_io *io) -@@ -86,13 +84,12 @@ static void move_free(struct moving_io *io) - if (io->b) - atomic_dec(&io->b->count); - -- bch2_data_update_exit(&io->write); -- - mutex_lock(&ctxt->lock); - list_del(&io->io_list); - wake_up(&ctxt->wait); - mutex_unlock(&ctxt->lock); - -+ bch2_data_update_exit(&io->write); - kfree(io); - } - -@@ -112,7 +109,7 @@ static void move_write_done(struct bch_write_op *op) - - static void move_write(struct moving_io *io) - { -- if (unlikely(io->rbio.bio.bi_status || io->rbio.hole)) { -+ if (unlikely(io->write.rbio.bio.bi_status || io->write.rbio.hole)) { - move_free(io); - return; - } -@@ -130,7 +127,7 @@ static void move_write(struct moving_io *io) - atomic_add(io->write_sectors, &io->write.ctxt->write_sectors); - atomic_inc(&io->write.ctxt->write_ios); - -- bch2_data_update_read_done(&io->write, io->rbio.pick.crc); -+ bch2_data_update_read_done(&io->write); - } - - struct moving_io *bch2_moving_ctxt_next_pending_write(struct moving_context *ctxt) -@@ -143,7 +140,7 @@ struct moving_io *bch2_moving_ctxt_next_pending_write(struct moving_context *ctx - - static void move_read_endio(struct bio *bio) - { -- struct moving_io *io = container_of(bio, struct moving_io, rbio.bio); -+ struct moving_io *io = container_of(bio, struct moving_io, write.rbio.bio); - struct moving_context *ctxt = io->write.ctxt; - - atomic_sub(io->read_sectors, &ctxt->read_sectors); -@@ -196,6 +193,13 @@ void bch2_moving_ctxt_exit(struct moving_context *ctxt) +@@ -196,6 +198,13 @@ void bch2_moving_ctxt_exit(struct moving_context *ctxt) list_del(&ctxt->list); mutex_unlock(&c->moving_context_lock); @@ -18852,91 +17372,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 bch2_trans_put(ctxt->trans); memset(ctxt, 0, sizeof(*ctxt)); } -@@ -249,11 +253,6 @@ int bch2_move_extent(struct moving_context *ctxt, - { - struct btree_trans *trans = ctxt->trans; - struct bch_fs *c = trans->c; -- struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); -- struct moving_io *io; -- const union bch_extent_entry *entry; -- struct extent_ptr_decoded p; -- unsigned sectors = k.k->size, pages; - int ret = -ENOMEM; - - trace_move_extent2(c, k, &io_opts, &data_opts); -@@ -276,13 +275,7 @@ int bch2_move_extent(struct moving_context *ctxt, - */ - bch2_trans_unlock(trans); - -- /* write path might have to decompress data: */ -- bkey_for_each_ptr_decode(k.k, ptrs, p, entry) -- sectors = max_t(unsigned, sectors, p.crc.uncompressed_size); -- -- pages = DIV_ROUND_UP(sectors, PAGE_SECTORS); -- io = kzalloc(sizeof(struct moving_io) + -- sizeof(struct bio_vec) * pages, GFP_KERNEL); -+ struct moving_io *io = kzalloc(sizeof(struct moving_io), GFP_KERNEL); - if (!io) - goto err; - -@@ -291,29 +284,13 @@ int bch2_move_extent(struct moving_context *ctxt, - io->read_sectors = k.k->size; - io->write_sectors = k.k->size; - -- bio_init(&io->write.op.wbio.bio, NULL, io->bi_inline_vecs, pages, 0); -- bio_set_prio(&io->write.op.wbio.bio, -- IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); -- -- if (bch2_bio_alloc_pages(&io->write.op.wbio.bio, sectors << 9, -- GFP_KERNEL)) -- goto err_free; -- -- io->rbio.c = c; -- io->rbio.opts = io_opts; -- bio_init(&io->rbio.bio, NULL, io->bi_inline_vecs, pages, 0); -- io->rbio.bio.bi_vcnt = pages; -- bio_set_prio(&io->rbio.bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); -- io->rbio.bio.bi_iter.bi_size = sectors << 9; -- -- io->rbio.bio.bi_opf = REQ_OP_READ; -- io->rbio.bio.bi_iter.bi_sector = bkey_start_offset(k.k); -- io->rbio.bio.bi_end_io = move_read_endio; -- - ret = bch2_data_update_init(trans, iter, ctxt, &io->write, ctxt->wp, - io_opts, data_opts, iter->btree_id, k); - if (ret) -- goto err_free_pages; -+ goto err_free; -+ -+ io->write.rbio.bio.bi_end_io = move_read_endio; -+ bio_set_prio(&io->write.rbio.bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); - - io->write.op.end_io = move_write_done; - -@@ -347,18 +324,16 @@ int bch2_move_extent(struct moving_context *ctxt, - * ctxt when doing wakeup - */ - closure_get(&ctxt->cl); -- bch2_read_extent(trans, &io->rbio, -+ bch2_read_extent(trans, &io->write.rbio, - bkey_start_pos(k.k), - iter->btree_id, k, 0, -- BCH_READ_NODECODE| -- BCH_READ_LAST_FRAGMENT); -+ BCH_READ_data_update| -+ BCH_READ_last_fragment); - return 0; --err_free_pages: -- bio_free_pages(&io->write.op.wbio.bio); - err_free: - kfree(io); - err: -- if (ret == -BCH_ERR_data_update_done) -+ if (bch2_err_matches(ret, BCH_ERR_data_update_done)) - return 0; - - if (bch2_err_matches(ret, EROFS) || -@@ -379,34 +354,42 @@ int bch2_move_extent(struct moving_context *ctxt, +@@ -379,34 +388,42 @@ int bch2_move_extent(struct moving_context *ctxt, return ret; } @@ -18985,7 +17421,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 } ret = ret ?: trans_was_restarted(trans, restart_count); -@@ -415,43 +398,46 @@ struct bch_io_opts *bch2_move_get_io_opts(struct btree_trans *trans, +@@ -415,43 +432,46 @@ struct bch_io_opts *bch2_move_get_io_opts(struct btree_trans *trans, if (extent_k.k->p.snapshot) darray_for_each(io_opts->d, i) @@ -19053,7 +17489,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 } int bch2_move_ratelimit(struct moving_context *ctxt) -@@ -509,9 +495,15 @@ static int bch2_move_data_btree(struct moving_context *ctxt, +@@ -509,9 +529,15 @@ static int bch2_move_data_btree(struct moving_context *ctxt, struct per_snapshot_io_opts snapshot_io_opts; struct bch_io_opts *io_opts; struct bkey_buf sk; @@ -19070,7 +17506,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 int ret = 0, ret2; per_snapshot_io_opts_init(&snapshot_io_opts, c); -@@ -531,6 +523,8 @@ static int bch2_move_data_btree(struct moving_context *ctxt, +@@ -531,6 +557,8 @@ static int bch2_move_data_btree(struct moving_context *ctxt, bch2_ratelimit_reset(ctxt->rate); while (!bch2_move_ratelimit(ctxt)) { @@ -19079,7 +17515,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 bch2_trans_begin(trans); k = bch2_btree_iter_peek(&iter); -@@ -549,10 +543,36 @@ static int bch2_move_data_btree(struct moving_context *ctxt, +@@ -549,10 +577,36 @@ static int bch2_move_data_btree(struct moving_context *ctxt, if (ctxt->stats) ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos); @@ -19117,7 +17553,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 ret = PTR_ERR_OR_ZERO(io_opts); if (ret) continue; -@@ -568,12 +588,12 @@ static int bch2_move_data_btree(struct moving_context *ctxt, +@@ -568,7 +622,7 @@ static int bch2_move_data_btree(struct moving_context *ctxt, bch2_bkey_buf_reassemble(&sk, c, k); k = bkey_i_to_s_c(sk.k); @@ -19126,13 +17562,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 if (ret2) { if (bch2_err_matches(ret2, BCH_ERR_transaction_restart)) continue; - -- if (ret2 == -ENOMEM) { -+ if (bch2_err_matches(ret2, ENOMEM)) { - /* memory allocation failure, wait for some IO to finish */ - bch2_move_ctxt_wait_for_io(ctxt); - continue; -@@ -589,6 +609,7 @@ static int bch2_move_data_btree(struct moving_context *ctxt, +@@ -589,6 +643,7 @@ static int bch2_move_data_btree(struct moving_context *ctxt, bch2_btree_iter_advance(&iter); } @@ -19140,7 +17570,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 bch2_trans_iter_exit(trans, &iter); bch2_bkey_buf_exit(&sk, c); per_snapshot_io_opts_exit(&snapshot_io_opts); -@@ -654,16 +675,12 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -654,16 +709,12 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, struct bch_fs *c = trans->c; bool is_kthread = current->flags & PF_KTHREAD; struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); @@ -19160,7 +17590,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 int ret = 0; struct bch_dev *ca = bch2_dev_tryget(c, bucket.inode); -@@ -672,6 +689,8 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -672,6 +723,8 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, trace_bucket_evacuate(c, &bucket); @@ -19169,7 +17599,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 bch2_bkey_buf_init(&sk); /* -@@ -679,21 +698,13 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -679,21 +732,13 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, */ bch2_trans_begin(trans); @@ -19193,7 +17623,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 ret = bch2_btree_write_buffer_tryflush(trans); bch_err_msg(c, ret, "flushing btree write buffer"); if (ret) -@@ -705,18 +716,23 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -705,18 +750,23 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, bch2_trans_begin(trans); @@ -19223,7 +17653,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 ret = bkey_err(k); if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) continue; -@@ -728,7 +744,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -728,7 +778,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, bch2_bkey_buf_reassemble(&sk, c, k); k = bkey_i_to_s_c(sk.k); @@ -19232,7 +17662,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 if (ret) { bch2_trans_iter_exit(trans, &iter); continue; -@@ -738,14 +754,18 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -738,14 +788,18 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, data_opts.target = io_opts.background_target; data_opts.rewrite_ptrs = 0; @@ -19255,7 +17685,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 } i++; } -@@ -765,14 +785,15 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -765,14 +819,15 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, goto err; if (ctxt->stats) @@ -19274,7 +17704,7 @@ index 0ef4a86850bb..ff787d3d50d2 100644 if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) continue; if (ret) -@@ -796,15 +817,18 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, +@@ -796,15 +851,18 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, atomic64_add(sectors, &ctxt->stats->sectors_seen); atomic64_add(sectors, &ctxt->stats->sectors_moved); } @@ -19295,15 +17725,6 @@ index 0ef4a86850bb..ff787d3d50d2 100644 return ret; } -@@ -1158,7 +1182,7 @@ static void bch2_moving_ctxt_to_text(struct printbuf *out, struct bch_fs *c, str - - mutex_lock(&ctxt->lock); - list_for_each_entry(io, &ctxt->ios, io_list) -- bch2_write_op_to_text(out, &io->write.op); -+ bch2_data_update_inflight_to_text(out, &io->write); - mutex_unlock(&ctxt->lock); - - printbuf_indent_sub(out, 4); diff --git a/fs/bcachefs/move.h b/fs/bcachefs/move.h index 9baf3093a678..51e0505a8156 100644 --- a/fs/bcachefs/move.h @@ -19455,7 +17876,7 @@ index 0e2ee262fbd4..6772faf385a5 100644 bool bch2_opt_is_inode_opt(enum bch_opt_id id) diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h -index 23dda014e331..a182b5d454ba 100644 +index 23dda014e331..9d397fc2a1f0 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -16,7 +16,8 @@ extern const char * const bch2_version_upgrade_opts[]; @@ -19539,7 +17960,7 @@ index 23dda014e331..a182b5d454ba 100644 x(durability, u8, \ OPT_DEVICE|OPT_SB_FIELD_ONE_BIAS, \ OPT_UINT(0, BCH_REPLICAS_MAX), \ -@@ -624,14 +638,39 @@ struct bch_io_opts { +@@ -624,11 +638,22 @@ struct bch_io_opts { #define x(_name, _bits) u##_bits _name; BCH_INODE_OPTS() #undef x @@ -19564,23 +17985,6 @@ index 23dda014e331..a182b5d454ba 100644 } struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts); - bool bch2_opt_is_inode_opt(enum bch_opt_id); - -+/* rebalance opts: */ -+ -+static inline struct bch_extent_rebalance io_opts_to_rebalance_opts(struct bch_io_opts *opts) -+{ -+ return (struct bch_extent_rebalance) { -+ .type = BIT(BCH_EXTENT_ENTRY_rebalance), -+#define x(_name) \ -+ ._name = opts->_name, \ -+ ._name##_from_inode = opts->_name##_from_inode, -+ BCH_REBALANCE_OPTS() -+#undef x -+ }; -+}; -+ - #endif /* _BCACHEFS_OPTS_H */ diff --git a/fs/bcachefs/printbuf.h b/fs/bcachefs/printbuf.h index 1d570387b77f..d0dd398baa2b 100644 --- a/fs/bcachefs/printbuf.h @@ -19754,10 +18158,10 @@ index 40a20192eee8..bef2aa1b8bcd 100644 if (may_sleep && unlikely(process_finished_items(pending, p, flags))) diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c -index cd6647374353..90dbf04c07a1 100644 +index cd6647374353..d0a1f5cd5c2b 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c -@@ -24,6 +24,192 @@ +@@ -24,6 +24,190 @@ #include #include @@ -19858,12 +18262,10 @@ index cd6647374353..90dbf04c07a1 100644 + } + } +incompressible: -+ if (opts->background_target && -+ bch2_target_accepts_data(c, BCH_DATA_user, opts->background_target)) { ++ if (opts->background_target) + bkey_for_each_ptr_decode(k.k, ptrs, p, entry) + if (!p.ptr.cached && !bch2_dev_in_target(c, p.ptr.dev, opts->background_target)) + sectors += p.crc.compressed_size; -+ } + + return sectors; +} @@ -19877,7 +18279,7 @@ index cd6647374353..90dbf04c07a1 100644 + const struct bch_extent_rebalance *old = bch2_bkey_rebalance_opts(k); + + if (k.k->type == KEY_TYPE_reflink_v || bch2_bkey_ptrs_need_rebalance(c, opts, k)) { -+ struct bch_extent_rebalance new = io_opts_to_rebalance_opts(opts); ++ struct bch_extent_rebalance new = io_opts_to_rebalance_opts(c, opts); + return old == NULL || memcmp(old, &new, sizeof(new)); + } else { + return old != NULL; @@ -19900,7 +18302,7 @@ index cd6647374353..90dbf04c07a1 100644 + k.k->u64s += sizeof(*old) / sizeof(u64); + } + -+ *old = io_opts_to_rebalance_opts(opts); ++ *old = io_opts_to_rebalance_opts(c, opts); + } else { + if (old) + extent_entry_drop(k, (union bch_extent_entry *) old); @@ -19950,7 +18352,7 @@ index cd6647374353..90dbf04c07a1 100644 #define REBALANCE_WORK_SCAN_OFFSET (U64_MAX - 1) static const char * const bch2_rebalance_state_strs[] = { -@@ -33,7 +219,7 @@ static const char * const bch2_rebalance_state_strs[] = { +@@ -33,7 +217,7 @@ static const char * const bch2_rebalance_state_strs[] = { #undef x }; @@ -19959,7 +18361,7 @@ index cd6647374353..90dbf04c07a1 100644 { struct btree_iter iter; struct bkey_s_c k; -@@ -71,9 +257,8 @@ static int __bch2_set_rebalance_needs_scan(struct btree_trans *trans, u64 inum) +@@ -71,9 +255,8 @@ static int __bch2_set_rebalance_needs_scan(struct btree_trans *trans, u64 inum) int bch2_set_rebalance_needs_scan(struct bch_fs *c, u64 inum) { int ret = bch2_trans_commit_do(c, NULL, NULL, @@ -19971,7 +18373,7 @@ index cd6647374353..90dbf04c07a1 100644 rebalance_wakeup(c); return ret; } -@@ -121,6 +306,9 @@ static int bch2_bkey_clear_needs_rebalance(struct btree_trans *trans, +@@ -121,6 +304,9 @@ static int bch2_bkey_clear_needs_rebalance(struct btree_trans *trans, struct btree_iter *iter, struct bkey_s_c k) { @@ -19981,7 +18383,7 @@ index cd6647374353..90dbf04c07a1 100644 struct bkey_i *n = bch2_bkey_make_mut(trans, iter, &k, 0); int ret = PTR_ERR_OR_ZERO(n); if (ret) -@@ -134,32 +322,28 @@ static int bch2_bkey_clear_needs_rebalance(struct btree_trans *trans, +@@ -134,31 +320,27 @@ static int bch2_bkey_clear_needs_rebalance(struct btree_trans *trans, static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans, struct bpos work_pos, struct btree_iter *extent_iter, @@ -20015,14 +18417,12 @@ index cd6647374353..90dbf04c07a1 100644 - data_opts->rewrite_ptrs = - bch2_bkey_ptrs_need_rebalance(c, k, r->target, r->compression); - data_opts->target = r->target; -- data_opts->write_flags |= BCH_WRITE_ONLY_SPECIFIED_DEVS; + data_opts->rewrite_ptrs = bch2_bkey_ptrs_need_rebalance(c, io_opts, k); + data_opts->target = io_opts->background_target; -+ data_opts->write_flags |= BCH_WRITE_only_specified_devs; + data_opts->write_flags |= BCH_WRITE_ONLY_SPECIFIED_DEVS; if (!data_opts->rewrite_ptrs) { - /* -@@ -178,12 +362,28 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans, +@@ -178,12 +360,28 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans, if (trace_rebalance_extent_enabled()) { struct printbuf buf = PRINTBUF; @@ -20056,7 +18456,7 @@ index cd6647374353..90dbf04c07a1 100644 trace_rebalance_extent(c, buf.buf); printbuf_exit(&buf); -@@ -212,14 +412,10 @@ static int do_rebalance_extent(struct moving_context *ctxt, +@@ -212,14 +410,10 @@ static int do_rebalance_extent(struct moving_context *ctxt, bch2_bkey_buf_init(&sk); ret = bkey_err(k = next_rebalance_extent(trans, work_pos, @@ -20072,7 +18472,7 @@ index cd6647374353..90dbf04c07a1 100644 atomic64_add(k.k->size, &ctxt->stats->sectors_seen); /* -@@ -253,21 +449,9 @@ static bool rebalance_pred(struct bch_fs *c, void *arg, +@@ -253,20 +447,8 @@ static bool rebalance_pred(struct bch_fs *c, void *arg, struct bch_io_opts *io_opts, struct data_update_opts *data_opts) { @@ -20090,14 +18490,12 @@ index cd6647374353..90dbf04c07a1 100644 - - data_opts->rewrite_ptrs = bch2_bkey_ptrs_need_rebalance(c, k, target, compression); - data_opts->target = target; -- data_opts->write_flags |= BCH_WRITE_ONLY_SPECIFIED_DEVS; + data_opts->rewrite_ptrs = bch2_bkey_ptrs_need_rebalance(c, io_opts, k); + data_opts->target = io_opts->background_target; -+ data_opts->write_flags |= BCH_WRITE_only_specified_devs; + data_opts->write_flags |= BCH_WRITE_ONLY_SPECIFIED_DEVS; return data_opts->rewrite_ptrs != 0; } - -@@ -338,9 +522,9 @@ static int do_rebalance(struct moving_context *ctxt) +@@ -338,9 +520,9 @@ static int do_rebalance(struct moving_context *ctxt) BTREE_ITER_all_snapshots); while (!bch2_move_ratelimit(ctxt)) { @@ -20110,17 +18508,37 @@ index cd6647374353..90dbf04c07a1 100644 } diff --git a/fs/bcachefs/rebalance.h b/fs/bcachefs/rebalance.h -index 28a52638f16c..0a0821ab895d 100644 +index 28a52638f16c..62a3859d3823 100644 --- a/fs/bcachefs/rebalance.h +++ b/fs/bcachefs/rebalance.h -@@ -2,8 +2,18 @@ +@@ -2,8 +2,38 @@ #ifndef _BCACHEFS_REBALANCE_H #define _BCACHEFS_REBALANCE_H +#include "compress.h" +#include "disk_groups.h" ++#include "opts.h" #include "rebalance_types.h" ++static inline struct bch_extent_rebalance io_opts_to_rebalance_opts(struct bch_fs *c, ++ struct bch_io_opts *opts) ++{ ++ struct bch_extent_rebalance r = { ++ .type = BIT(BCH_EXTENT_ENTRY_rebalance), ++#define x(_name) \ ++ ._name = opts->_name, \ ++ ._name##_from_inode = opts->_name##_from_inode, ++ BCH_REBALANCE_OPTS() ++#undef x ++ }; ++ ++ if (r.background_target && ++ !bch2_target_accepts_data(c, BCH_DATA_user, r.background_target)) ++ r.background_target = 0; ++ ++ return r; ++}; ++ +u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *, struct bkey_s_c); +int bch2_bkey_set_needs_rebalance(struct bch_fs *, struct bch_io_opts *, struct bkey_i *); +int bch2_get_update_rebalance_opts(struct btree_trans *, @@ -20882,7 +19300,7 @@ index 94dc20ca2065..418557960ed6 100644 /* We normally enumerate recovery passes in the order we run them: */ enum bch_recovery_pass { diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c -index f457925fa362..93ba4f4e47ca 100644 +index f457925fa362..376fd0a6e868 100644 --- a/fs/bcachefs/reflink.c +++ b/fs/bcachefs/reflink.c @@ -15,6 +15,17 @@ @@ -21250,7 +19668,7 @@ index f457925fa362..93ba4f4e47ca 100644 s64 ret = 0; struct printbuf buf = PRINTBUF; -@@ -168,36 +379,14 @@ static s64 gc_trigger_reflink_p_segment(struct btree_trans *trans, +@@ -168,36 +379,16 @@ static s64 gc_trigger_reflink_p_segment(struct btree_trans *trans, *idx = r->offset; return 0; not_found: @@ -21266,6 +19684,8 @@ index f457925fa362..93ba4f4e47ca 100644 - ret = PTR_ERR_OR_ZERO(update); + if (flags & BTREE_TRIGGER_check_repair) { + ret = bch2_indirect_extent_missing_error(trans, p, *idx, next_idx, false); ++ if (ret == -BCH_ERR_missing_indirect_extent) ++ ret = 0; if (ret) goto err; - @@ -21289,7 +19709,7 @@ index f457925fa362..93ba4f4e47ca 100644 printbuf_exit(&buf); return ret; } -@@ -210,8 +399,8 @@ static int __trigger_reflink_p(struct btree_trans *trans, +@@ -210,8 +401,8 @@ static int __trigger_reflink_p(struct btree_trans *trans, struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k); int ret = 0; @@ -21300,7 +19720,7 @@ index f457925fa362..93ba4f4e47ca 100644 if (flags & BTREE_TRIGGER_transactional) { while (idx < end && !ret) -@@ -253,35 +442,7 @@ int bch2_trigger_reflink_p(struct btree_trans *trans, +@@ -253,35 +444,7 @@ int bch2_trigger_reflink_p(struct btree_trans *trans, return trigger_run_overwrite_then_insert(__trigger_reflink_p, trans, btree_id, level, old, new, flags); } @@ -21337,7 +19757,7 @@ index f457925fa362..93ba4f4e47ca 100644 static inline void check_indirect_extent_deleting(struct bkey_s new, -@@ -307,25 +468,6 @@ int bch2_trigger_reflink_v(struct btree_trans *trans, +@@ -307,25 +470,6 @@ int bch2_trigger_reflink_v(struct btree_trans *trans, return bch2_trigger_extent(trans, btree_id, level, old, new, flags); } @@ -21363,7 +19783,7 @@ index f457925fa362..93ba4f4e47ca 100644 int bch2_trigger_indirect_inline_data(struct btree_trans *trans, enum btree_id btree_id, unsigned level, struct bkey_s_c old, struct bkey_s new, -@@ -336,9 +478,12 @@ int bch2_trigger_indirect_inline_data(struct btree_trans *trans, +@@ -336,9 +480,12 @@ int bch2_trigger_indirect_inline_data(struct btree_trans *trans, return 0; } @@ -21377,7 +19797,7 @@ index f457925fa362..93ba4f4e47ca 100644 { struct bch_fs *c = trans->c; struct btree_iter reflink_iter = { NULL }; -@@ -358,6 +503,14 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, +@@ -358,6 +505,14 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, if (ret) goto err; @@ -21392,7 +19812,7 @@ index f457925fa362..93ba4f4e47ca 100644 r_v = bch2_trans_kmalloc(trans, sizeof(__le64) + bkey_bytes(&orig->k)); ret = PTR_ERR_OR_ZERO(r_v); if (ret) -@@ -394,7 +547,10 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, +@@ -394,7 +549,10 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, memset(&r_p->v, 0, sizeof(r_p->v)); #endif @@ -21404,7 +19824,7 @@ index f457925fa362..93ba4f4e47ca 100644 ret = bch2_trans_update(trans, extent_iter, &r_p->k_i, BTREE_UPDATE_internal_snapshot_node); -@@ -409,7 +565,7 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end) +@@ -409,7 +567,7 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end) struct bkey_s_c k; int ret; @@ -21413,7 +19833,7 @@ index f457925fa362..93ba4f4e47ca 100644 if (bkey_extent_is_unwritten(k)) continue; -@@ -426,7 +582,8 @@ s64 bch2_remap_range(struct bch_fs *c, +@@ -426,7 +584,8 @@ s64 bch2_remap_range(struct bch_fs *c, subvol_inum dst_inum, u64 dst_offset, subvol_inum src_inum, u64 src_offset, u64 remap_sectors, @@ -21423,7 +19843,7 @@ index f457925fa362..93ba4f4e47ca 100644 { struct btree_trans *trans; struct btree_iter dst_iter, src_iter; -@@ -439,6 +596,8 @@ s64 bch2_remap_range(struct bch_fs *c, +@@ -439,6 +598,8 @@ s64 bch2_remap_range(struct bch_fs *c, struct bpos src_want; u64 dst_done = 0; u32 dst_snapshot, src_snapshot; @@ -21432,7 +19852,7 @@ index f457925fa362..93ba4f4e47ca 100644 int ret = 0, ret2 = 0; if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_reflink)) -@@ -520,7 +679,8 @@ s64 bch2_remap_range(struct bch_fs *c, +@@ -520,7 +681,8 @@ s64 bch2_remap_range(struct bch_fs *c, src_k = bkey_i_to_s_c(new_src.k); ret = bch2_make_extent_indirect(trans, &src_iter, @@ -21442,7 +19862,7 @@ index f457925fa362..93ba4f4e47ca 100644 if (ret) continue; -@@ -533,11 +693,15 @@ s64 bch2_remap_range(struct bch_fs *c, +@@ -533,11 +695,15 @@ s64 bch2_remap_range(struct bch_fs *c, struct bkey_i_reflink_p *dst_p = bkey_reflink_p_init(new_dst.k); @@ -21460,7 +19880,7 @@ index f457925fa362..93ba4f4e47ca 100644 } else { BUG(); } -@@ -547,7 +711,7 @@ s64 bch2_remap_range(struct bch_fs *c, +@@ -547,7 +713,7 @@ s64 bch2_remap_range(struct bch_fs *c, min(src_k.k->p.offset - src_want.offset, dst_end.offset - dst_iter.pos.offset)); @@ -21469,7 +19889,7 @@ index f457925fa362..93ba4f4e47ca 100644 bch2_extent_update(trans, dst_inum, &dst_iter, new_dst.k, &disk_res, new_i_size, i_sectors_delta, -@@ -591,3 +755,97 @@ s64 bch2_remap_range(struct bch_fs *c, +@@ -591,3 +757,97 @@ s64 bch2_remap_range(struct bch_fs *c, return dst_done ?: ret ?: ret2; } @@ -21891,7 +20311,7 @@ index 8767c33c2b51..14f6b6a5fb38 100644 struct upgrade_downgrade_entry { u64 recovery_passes; diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h -index 9feb6739f77a..ea0a18364751 100644 +index 9feb6739f77a..b86ec013d7d7 100644 --- a/fs/bcachefs/sb-errors_format.h +++ b/fs/bcachefs/sb-errors_format.h @@ -5,9 +5,8 @@ @@ -21974,7 +20394,7 @@ index 9feb6739f77a..ea0a18364751 100644 x(lru_entry_at_time_0, 129, FSCK_AUTOFIX) \ x(lru_entry_to_invalid_bucket, 130, FSCK_AUTOFIX) \ x(lru_entry_bad, 131, FSCK_AUTOFIX) \ -@@ -167,14 +168,15 @@ enum bch_fsck_flags { +@@ -167,20 +168,21 @@ enum bch_fsck_flags { x(ptr_to_incorrect_stripe, 151, 0) \ x(ptr_gen_newer_than_bucket_gen, 152, 0) \ x(ptr_too_stale, 153, 0) \ @@ -21992,6 +20412,14 @@ index 9feb6739f77a..ea0a18364751 100644 x(ptr_crc_nonce_mismatch, 162, 0) \ x(ptr_stripe_redundant, 163, 0) \ x(reservation_key_nr_replicas_invalid, 164, 0) \ +- x(reflink_v_refcount_wrong, 165, 0) \ ++ x(reflink_v_refcount_wrong, 165, FSCK_AUTOFIX) \ + x(reflink_v_pos_bad, 292, 0) \ +- x(reflink_p_to_missing_reflink_v, 166, 0) \ ++ x(reflink_p_to_missing_reflink_v, 166, FSCK_AUTOFIX) \ + x(reflink_refcount_underflow, 293, 0) \ + x(stripe_pos_bad, 167, 0) \ + x(stripe_val_size_bad, 168, 0) \ @@ -209,6 +211,7 @@ enum bch_fsck_flags { x(bkey_in_missing_snapshot, 190, 0) \ x(inode_pos_inode_nonzero, 191, 0) \ @@ -23356,7 +21784,7 @@ index ec2b1feea520..55a4ac7bf220 100644 + #endif /* _BCACHEFS_STR_HASH_H */ diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c -index 80e5efaff524..e3d0475232e5 100644 +index 80e5efaff524..b7b96283c316 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c @@ -207,7 +207,7 @@ int bch2_check_subvol_children(struct bch_fs *c) @@ -23420,7 +21848,7 @@ index 80e5efaff524..e3d0475232e5 100644 for_each_btree_key_commit(trans, iter, BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_prefetch, k, NULL, NULL, BCH_TRANS_COMMIT_no_enospc, -@@ -411,26 +409,56 @@ static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_d +@@ -411,26 +409,61 @@ static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_d */ static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid) { @@ -23451,19 +21879,24 @@ index 80e5efaff524..e3d0475232e5 100644 + bch2_bkey_get_iter_typed(trans, &snapshot_iter, + BTREE_ID_snapshots, POS(0, snapid), + 0, snapshot); -+ ret = bkey_err(subvol); ++ ret = bkey_err(snapshot); + bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, + "missing snapshot %u", snapid); + if (ret) + goto err; -+ -+ u32 treeid = le32_to_cpu(snapshot.v->tree); - ret = bch2_btree_delete_at(trans, &iter, 0) ?: ++ u32 treeid = le32_to_cpu(snapshot.v->tree); ++ + struct bkey_s_c_snapshot_tree snapshot_tree = + bch2_bkey_get_iter_typed(trans, &snapshot_tree_iter, + BTREE_ID_snapshot_trees, POS(0, treeid), + 0, snapshot_tree); ++ ret = bkey_err(snapshot_tree); ++ bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, ++ "missing snapshot tree %u", treeid); ++ if (ret) ++ goto err; + + if (le32_to_cpu(snapshot_tree.v->master_subvol) == subvolid) { + struct bkey_i_snapshot_tree *snapshot_tree_mut = @@ -23487,7 +21920,7 @@ index 80e5efaff524..e3d0475232e5 100644 return ret; } -@@ -675,7 +703,7 @@ static int __bch2_fs_upgrade_for_subvolumes(struct btree_trans *trans) +@@ -675,7 +708,7 @@ static int __bch2_fs_upgrade_for_subvolumes(struct btree_trans *trans) /* set bi_subvol on root inode */ int bch2_fs_upgrade_for_subvolumes(struct bch_fs *c) { @@ -23842,7 +22275,7 @@ index fadd364e2802..f1ab4f943720 100644 void __bch2_sb_field_to_text(struct printbuf *, struct bch_sb *, struct bch_sb_field *); diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c -index a6ed9a0bf1c7..d97ea7bd1171 100644 +index a6ed9a0bf1c7..6d97d412fed9 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -290,7 +290,7 @@ static void __bch2_fs_read_only(struct bch_fs *c) @@ -23854,7 +22287,25 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 test_bit(BCH_FS_clean_shutdown, &c->flags) ? "" : "un", c->journal.seq_ondisk); -@@ -441,6 +441,8 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) +@@ -411,6 +411,17 @@ bool bch2_fs_emergency_read_only(struct bch_fs *c) + return ret; + } + ++bool bch2_fs_emergency_read_only_locked(struct bch_fs *c) ++{ ++ bool ret = !test_and_set_bit(BCH_FS_emergency_ro, &c->flags); ++ ++ bch2_journal_halt_locked(&c->journal); ++ bch2_fs_read_only_async(c); ++ ++ wake_up(&bch2_read_only_wait); ++ return ret; ++} ++ + static int bch2_fs_read_write_late(struct bch_fs *c) + { + int ret; +@@ -441,6 +452,8 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) { int ret; @@ -23863,7 +22314,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 if (test_bit(BCH_FS_initial_gc_unfixed, &c->flags)) { bch_err(c, "cannot go rw, unfixed btree errors"); return -BCH_ERR_erofs_unfixed_errors; -@@ -561,6 +563,7 @@ static void __bch2_fs_free(struct bch_fs *c) +@@ -561,6 +574,7 @@ static void __bch2_fs_free(struct bch_fs *c) bch2_io_clock_exit(&c->io_clock[WRITE]); bch2_io_clock_exit(&c->io_clock[READ]); bch2_fs_compress_exit(c); @@ -23871,7 +22322,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 bch2_journal_keys_put_initial(c); bch2_find_btree_nodes_exit(&c->found_btree_nodes); BUG_ON(atomic_read(&c->journal_keys.ref)); -@@ -584,7 +587,6 @@ static void __bch2_fs_free(struct bch_fs *c) +@@ -584,7 +598,6 @@ static void __bch2_fs_free(struct bch_fs *c) #endif kfree(rcu_dereference_protected(c->disk_groups, 1)); kfree(c->journal_seq_blacklist_table); @@ -23879,7 +22330,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 if (c->write_ref_wq) destroy_workqueue(c->write_ref_wq); -@@ -766,21 +768,17 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) +@@ -766,21 +779,17 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) refcount_set(&c->ro_ref, 1); init_waitqueue_head(&c->ro_ref_wait); @@ -23903,7 +22354,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 bch2_fs_allocator_background_init(c); bch2_fs_allocator_foreground_init(c); bch2_fs_rebalance_init(c); -@@ -809,9 +807,6 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) +@@ -809,9 +818,6 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) INIT_LIST_HEAD(&c->vfs_inodes_list); mutex_init(&c->vfs_inodes_lock); @@ -23913,7 +22364,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 c->journal.flush_write_time = &c->times[BCH_TIME_journal_flush_write]; c->journal.noflush_write_time = &c->times[BCH_TIME_journal_noflush_write]; c->journal.flush_seq_time = &c->times[BCH_TIME_journal_flush_seq]; -@@ -873,8 +868,6 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) +@@ -873,8 +879,6 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) (btree_blocks(c) + 1) * 2 * sizeof(struct sort_iter_set); @@ -23922,7 +22373,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 if (!(c->btree_update_wq = alloc_workqueue("bcachefs", WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_UNBOUND, 512)) || !(c->btree_io_complete_wq = alloc_workqueue("bcachefs_btree_io", -@@ -901,9 +894,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) +@@ -901,9 +905,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) !(c->online_reserved = alloc_percpu(u64)) || mempool_init_kvmalloc_pool(&c->btree_bounce_pool, 1, c->opts.btree_node_size) || @@ -23933,7 +22384,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 ret = -BCH_ERR_ENOMEM_fs_other_alloc; goto err; } -@@ -917,6 +908,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) +@@ -917,6 +919,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) bch2_fs_btree_cache_init(c) ?: bch2_fs_btree_key_cache_init(&c->btree_key_cache) ?: bch2_fs_btree_interior_update_init(c) ?: @@ -23941,7 +22392,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 bch2_fs_buckets_waiting_for_journal_init(c) ?: bch2_fs_btree_write_buffer_init(c) ?: bch2_fs_subvolumes_init(c) ?: -@@ -1033,9 +1025,12 @@ int bch2_fs_start(struct bch_fs *c) +@@ -1033,9 +1036,12 @@ int bch2_fs_start(struct bch_fs *c) bch2_dev_allocator_add(c, ca); bch2_recalc_capacity(c); @@ -23954,7 +22405,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 if (ret) goto err; -@@ -1120,12 +1115,12 @@ static int bch2_dev_in_fs(struct bch_sb_handle *fs, +@@ -1120,12 +1126,12 @@ static int bch2_dev_in_fs(struct bch_sb_handle *fs, prt_bdevname(&buf, fs->bdev); prt_char(&buf, ' '); @@ -23969,7 +22420,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 prt_newline(&buf); if (!opts->no_splitbrain_check) -@@ -1198,7 +1193,7 @@ static void bch2_dev_free(struct bch_dev *ca) +@@ -1198,7 +1204,7 @@ static void bch2_dev_free(struct bch_dev *ca) free_percpu(ca->io_done); bch2_dev_buckets_free(ca); @@ -23978,7 +22429,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 bch2_time_stats_quantiles_exit(&ca->io_latency[WRITE]); bch2_time_stats_quantiles_exit(&ca->io_latency[READ]); -@@ -1309,8 +1304,6 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, +@@ -1309,8 +1315,6 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, init_completion(&ca->ref_completion); init_completion(&ca->io_ref_completion); @@ -23987,7 +22438,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 INIT_WORK(&ca->io_error_work, bch2_io_error_work); bch2_time_stats_quantiles_init(&ca->io_latency[READ]); -@@ -1337,7 +1330,7 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, +@@ -1337,7 +1341,7 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, if (percpu_ref_init(&ca->io_ref, bch2_dev_io_ref_complete, PERCPU_REF_INIT_DEAD, GFP_KERNEL) || @@ -23996,7 +22447,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 bch2_dev_buckets_alloc(c, ca) || !(ca->io_done = alloc_percpu(*ca->io_done))) goto err; -@@ -1366,7 +1359,6 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) +@@ -1366,7 +1370,6 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) { struct bch_member member = bch2_sb_member_get(c->disk_sb.sb, dev_idx); struct bch_dev *ca = NULL; @@ -24004,7 +22455,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 if (bch2_fs_init_fault("dev_alloc")) goto err; -@@ -1378,10 +1370,8 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) +@@ -1378,10 +1381,8 @@ static int bch2_dev_alloc(struct bch_fs *c, unsigned dev_idx) ca->fs = c; bch2_dev_attach(c, ca, dev_idx); @@ -24016,7 +22467,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 return -BCH_ERR_ENOMEM_dev_alloc; } -@@ -1751,11 +1741,6 @@ int bch2_dev_add(struct bch_fs *c, const char *path) +@@ -1751,11 +1752,6 @@ int bch2_dev_add(struct bch_fs *c, const char *path) if (ret) goto err; @@ -24028,7 +22479,7 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 down_write(&c->state_lock); mutex_lock(&c->sb_lock); -@@ -1806,11 +1791,14 @@ int bch2_dev_add(struct bch_fs *c, const char *path) +@@ -1806,11 +1802,14 @@ int bch2_dev_add(struct bch_fs *c, const char *path) if (ret) goto err_late; @@ -24046,10 +22497,16 @@ index a6ed9a0bf1c7..d97ea7bd1171 100644 return 0; diff --git a/fs/bcachefs/super.h b/fs/bcachefs/super.h -index dada09331d2e..fa6d52216510 100644 +index dada09331d2e..04f8287eff5c 100644 --- a/fs/bcachefs/super.h +++ b/fs/bcachefs/super.h -@@ -34,16 +34,6 @@ void bch2_fs_read_only(struct bch_fs *); +@@ -29,21 +29,12 @@ int bch2_dev_resize(struct bch_fs *, struct bch_dev *, u64); + struct bch_dev *bch2_dev_lookup(struct bch_fs *, const char *); + + bool bch2_fs_emergency_read_only(struct bch_fs *); ++bool bch2_fs_emergency_read_only_locked(struct bch_fs *); + void bch2_fs_read_only(struct bch_fs *); + int bch2_fs_read_write(struct bch_fs *); int bch2_fs_read_write_early(struct bch_fs *); @@ -24354,7 +22811,7 @@ index fb5c1543e52f..6c6469814637 100644 0, k, 0)); diff --git a/fs/bcachefs/trace.h b/fs/bcachefs/trace.h -index 5597b9d6297f..56a5a7fbc0fd 100644 +index 5597b9d6297f..c1b51009edf6 100644 --- a/fs/bcachefs/trace.h +++ b/fs/bcachefs/trace.h @@ -199,6 +199,30 @@ DECLARE_EVENT_CLASS(bio, @@ -24388,7 +22845,35 @@ index 5597b9d6297f..56a5a7fbc0fd 100644 /* fs.c: */ TRACE_EVENT(bch2_sync_fs, TP_PROTO(struct super_block *sb, int wait), -@@ -848,8 +872,8 @@ TRACE_EVENT(move_data, +@@ -703,7 +727,7 @@ DEFINE_EVENT(fs_str, bucket_alloc_fail, + TP_ARGS(c, str) + ); + +-TRACE_EVENT(discard_buckets, ++DECLARE_EVENT_CLASS(discard_buckets_class, + TP_PROTO(struct bch_fs *c, u64 seen, u64 open, + u64 need_journal_commit, u64 discarded, const char *err), + TP_ARGS(c, seen, open, need_journal_commit, discarded, err), +@@ -735,6 +759,18 @@ TRACE_EVENT(discard_buckets, + __entry->err) + ); + ++DEFINE_EVENT(discard_buckets_class, discard_buckets, ++ TP_PROTO(struct bch_fs *c, u64 seen, u64 open, ++ u64 need_journal_commit, u64 discarded, const char *err), ++ TP_ARGS(c, seen, open, need_journal_commit, discarded, err) ++); ++ ++DEFINE_EVENT(discard_buckets_class, discard_buckets_fast, ++ TP_PROTO(struct bch_fs *c, u64 seen, u64 open, ++ u64 need_journal_commit, u64 discarded, const char *err), ++ TP_ARGS(c, seen, open, need_journal_commit, discarded, err) ++); ++ + TRACE_EVENT(bucket_invalidate, + TP_PROTO(struct bch_fs *c, unsigned dev, u64 bucket, u32 sectors), + TP_ARGS(c, dev, bucket, sectors), +@@ -848,8 +884,8 @@ TRACE_EVENT(move_data, TRACE_EVENT(evacuate_bucket, TP_PROTO(struct bch_fs *c, struct bpos *bucket, unsigned sectors, unsigned bucket_size, @@ -24399,7 +22884,7 @@ index 5597b9d6297f..56a5a7fbc0fd 100644 TP_STRUCT__entry( __field(dev_t, dev ) -@@ -857,7 +881,6 @@ TRACE_EVENT(evacuate_bucket, +@@ -857,7 +893,6 @@ TRACE_EVENT(evacuate_bucket, __field(u64, bucket ) __field(u32, sectors ) __field(u32, bucket_size ) @@ -24407,7 +22892,7 @@ index 5597b9d6297f..56a5a7fbc0fd 100644 __field(int, ret ) ), -@@ -867,45 +890,42 @@ TRACE_EVENT(evacuate_bucket, +@@ -867,45 +902,42 @@ TRACE_EVENT(evacuate_bucket, __entry->bucket = bucket->offset; __entry->sectors = sectors; __entry->bucket_size = bucket_size; @@ -24467,7 +22952,7 @@ index 5597b9d6297f..56a5a7fbc0fd 100644 ); TRACE_EVENT(copygc_wait, -@@ -1316,6 +1336,12 @@ TRACE_EVENT(trans_restart_key_cache_key_realloced, +@@ -1316,6 +1348,12 @@ TRACE_EVENT(trans_restart_key_cache_key_realloced, __entry->new_u64s) ); @@ -24480,7 +22965,7 @@ index 5597b9d6297f..56a5a7fbc0fd 100644 TRACE_EVENT(path_downgrade, TP_PROTO(struct btree_trans *trans, unsigned long caller_ip, -@@ -1352,10 +1378,21 @@ TRACE_EVENT(path_downgrade, +@@ -1352,10 +1390,21 @@ TRACE_EVENT(path_downgrade, __entry->pos_snapshot) ); @@ -24506,7 +22991,7 @@ index 5597b9d6297f..56a5a7fbc0fd 100644 ); TRACE_EVENT(write_buffer_flush, -@@ -1414,6 +1451,24 @@ TRACE_EVENT(write_buffer_flush_slowpath, +@@ -1414,6 +1463,24 @@ TRACE_EVENT(write_buffer_flush_slowpath, TP_printk("%zu/%zu", __entry->slowpath, __entry->total) ); diff --git a/sys-kernel/hardened-kernel/hardened-kernel-6.12.10.ebuild b/sys-kernel/hardened-kernel/hardened-kernel-6.12.12.ebuild similarity index 93% rename from sys-kernel/hardened-kernel/hardened-kernel-6.12.10.ebuild rename to sys-kernel/hardened-kernel/hardened-kernel-6.12.12.ebuild index e9b1a73..c6354b6 100644 --- a/sys-kernel/hardened-kernel/hardened-kernel-6.12.10.ebuild +++ b/sys-kernel/hardened-kernel/hardened-kernel-6.12.12.ebuild @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Gentoo Authors +# Copyright 2020-2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 @@ -10,8 +10,10 @@ inherit kernel-build toolchain-funcs MY_P=linux-${PV%.*} GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 3 )) -CONFIG_VER=6.12.1-gentoo -GENTOO_CONFIG_VER=g14 +# https://koji.fedoraproject.org/koji/packageinfo?packageID=8 +# forked to https://github.com/projg2/fedora-kernel-config-for-gentoo +CONFIG_VER=6.12.8-gentoo +GENTOO_CONFIG_VER=g15 HARDENED_PATCH_VER="${PV}-hardened1" GENPATCHES_EXCLUDE="1500_XATTR_USER_PREFIX.patch 1510_fs-enable-link-security-restrictions-by-default.patch @@ -99,7 +101,7 @@ src_prepare() { ) default - sed -i "s@\-hardened1@@g" Makefile || die + #sed -i "s@\-hardened1@@g" Makefile || die local biendian=false @@ -113,7 +115,7 @@ src_prepare() { ;; esac - local myversion="-hardened" + local myversion="-gentoo-dist" echo "CONFIG_LOCALVERSION=\"${myversion}\"" > "${T}"/version.config || die local dist_conf_path="${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"