From a644c132bde2d79c1199ea118048cf76eebb61e2 Mon Sep 17 00:00:00 2001 From: kernel-patches-daemon Date: Mon, 6 Jul 2026 08:28:38 +0000 Subject: [PATCH 1/4] adding ci files --- .github/dependabot.yml | 12 + .github/workflows/run-blktests.yml | 124 +++++++++++ CODE_OF_CONDUCT.md | 134 ++++++++++++ LICENSE | 339 +++++++++++++++++++++++++++++ LICENSES/GPL-2.0-or-later.txt | 339 +++++++++++++++++++++++++++++ README.md | 11 + 6 files changed, 959 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/run-blktests.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 LICENSE create mode 100644 LICENSES/GPL-2.0-or-later.txt create mode 100644 README.md diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..90e6b32b57671 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2026 Western Digital Corporation or its affiliates. +# +# Authors: Dennis Maisenbacher (dennis.maisenbacher@wdc.com) + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/run-blktests.yml b/.github/workflows/run-blktests.yml new file mode 100644 index 0000000000000..4413dc4e215d4 --- /dev/null +++ b/.github/workflows/run-blktests.yml @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2025 Western Digital Corporation or its affiliates. +# +# Authors: Dennis Maisenbacher (dennis.maisenbacher@wdc.com) + +name: Run blktests + +on: + pull_request: + +concurrency: + group: ci-test-${{ github.ref_name }} + +env: + KERNEL_REF: "${{ github.event.pull_request.head.sha }}" + KERNEL_TREE: "https://github.com/${{ github.repository }}" + +#This workflow requires an actions-runner-controllers (ARC) to be active. +#The k8s cluster of this ARC needs KubeVirt to be installed. +jobs: + build-and-test-kernel: + #This step runs in a container in the k8s cluster + runs-on: arc-vm-linux-blktests + steps: + - name: Checkout blktests-ci + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + with: + repository: linux-blktests/blktests-ci + path: blktests-ci + + - name: Build kernel and package it into a containerimage + run: | + cd blktests-ci/playbooks/roles/kernel-builder-k8s-job/templates + docker build \ + --build-arg KERNEL_TREE=${KERNEL_TREE} \ + --build-arg KERNEL_REF=${KERNEL_REF} \ + -t linux-kernel-containerdisk \ + -f Dockerfile.linux-kernel-containerdisk . 2>&1 | tee build.log + #Setting KERNEL_VERSION var which is latern needed for notifying the VM what kernel to pick up + cat build.log | grep KERNEL_VERSION | awk '{print $3}' | grep KERNEL_VERSION >> $GITHUB_ENV + + - name: Push the new Fedora containerimage with the freshly build kernel + run: | + docker tag linux-kernel-containerdisk registry-service.docker-registry.svc.cluster.local/linux-kernel-containerdisk:${KERNEL_VERSION} + docker push registry-service.docker-registry.svc.cluster.local/linux-kernel-containerdisk:${KERNEL_VERSION} + + - name: Run in VM + uses: ./blktests-ci/.github/actions/kubevirt-action + with: + host_devices: "nvme-wdc-zn540,nvme-wdc-sn640" + kernel_version: ${{ env.KERNEL_VERSION }} + vm_artifact_upload_dir: blktests/results + run_cmds: | + #Print VM debug info + uname -a + cat /etc/os-release + lsblk + + #Install build dependencies for blktests + sudo dnf install -y gcc \ + clang \ + make \ + util-linux \ + llvm \ + gawk \ + fio \ + udev \ + kmod \ + coreutils \ + gcc \ + gzip \ + e2fsprogs \ + xfsprogs \ + f2fs-tools \ + btrfs-progs \ + device-mapper-multipath \ + blktrace \ + kernel-headers \ + liburing \ + liburing-devel \ + nbd \ + device-mapper \ + ktls-utils \ + dosfstools \ + bc \ + libnl3-cli \ + cryptsetup \ + sg3_utils \ + pciutils \ + unzip \ + jq \ + nvme-cli \ + git \ + wget \ + pkgconf \ + libudev-devel + + git clone https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git + cd mdadm + git checkout d764c4829947923142a83251296d04edaee7d2f7 + make -j$(nproc) + sudo make install + + cd - + git clone https://github.com/linux-blktests/blktests.git + + cd blktests + git checkout ci + make + + #ATTENTION! This section formats all available NVMe devices. Be careful when changing the `runs-on` tag! + #This step runs in a VM with the previously compiled kernel in the k8s cluster + + ./contrib/run_ci https://github.com/linux-blktests/blktests-ci-conditions/raw/main + + # Mark blktests completion for KPD report + echo "KPD: blktests completed" + + # Output failures for KPD report + test -f all_failures && echo "KPD: Failures:" && cat all_failures + + test -f all_failures && exit 1 + exit 0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000..4edb70c22d479 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,134 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +opensource@wdc.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000..d159169d10508 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/LICENSES/GPL-2.0-or-later.txt b/LICENSES/GPL-2.0-or-later.txt new file mode 100644 index 0000000000000..d159169d10508 --- /dev/null +++ b/LICENSES/GPL-2.0-or-later.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..339ce7da25ed4 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ + + +# blktests-kpd-ci +This is a collection of GitHub actions workflow scripts for Continuous +Integration (CI) of Linux kernel using blktests. The scripts are intended to be +triggered by [Kernel Patches Daemon](https://github.com/kernel-patches/kernel-patches-daemon). +To use the scripts, specify this repository and the main branch as "ci_repo" and +"ci_branch" parameters respectively in the Kernel Patches Daemon config file. From 9bd67993ac4945f2e326ad995c553df0b40843c5 Mon Sep 17 00:00:00 2001 From: Leonid Ravich Date: Mon, 15 Jun 2026 11:14:57 +0000 Subject: [PATCH 2/4] crypto: skcipher - add per-request data_unit_size with auto-splitting Add a data_unit_size field to struct skcipher_request that lets a caller submit several data units (typically 512..4096-byte sectors) sharing one starting IV in a single request. Algorithms derive each data unit's IV from the caller-supplied IV by treating it as a 128-bit little-endian counter and adding the data-unit index, which matches the layout produced by dm-crypt's plain64 IV mode and by typical inline-encryption hardware. This mirrors the data_unit_size concept already exposed by struct blk_crypto_config for inline encryption. The crypto API auto-splits a multi-data-unit request into per-DU sub-requests when the underlying algorithm does not advertise CRYPTO_ALG_SKCIPHER_NATIVE_MULTI_DU (a type-specific cra_flags bit, defined in crypto/internal/skcipher.h). A consumer sets data_unit_size and submits: a native driver handles all units in one pass, otherwise the core splits transparently. The split derives per-DU IVs as a 128-bit LE counter, so this is correct only for algorithms using that IV convention (e.g. XTS with plain64-style IVs); callers are responsible for that match, as they already are for the IV itself. skcipher_request_set_tfm() resets the field to 0 so a request reused from a pool or stack defaults to single-data-unit semantics; callers that want batching set it explicitly via skcipher_request_set_data_unit_size() after configuring the tfm. crypto_skcipher_encrypt()/decrypt() call crypto_skcipher_validate_multi_du() before any algorithm dispatch. data_unit_size must be a power of two when non-zero (realistic sizes are 512..4096, letting the per-DU loop and the cryptlen alignment check use a mask instead of a divide) and cryptlen a positive multiple of it; a malformed geometry is rejected with -EINVAL. A target that cannot do multi-DU - ivsize != SKCIPHER_MDU_IVSIZE (16), an lskcipher, or an async algorithm without the native flag - is rejected with -EOPNOTSUPP so a caller can fall back. Async is excluded because the splitter dispatches synchronously: an -EINPROGRESS return would leave later units unsubmitted while the driver still owned the request's scatterlists and IV. The check gates the native path too, so algorithms never see a malformed multi-DU request. No in-tree algorithm sets CRYPTO_ALG_SKCIPHER_NATIVE_MULTI_DU yet; subsequent patches add the testmgr coverage and the dm-crypt consumer. Signed-off-by: Leonid Ravich --- crypto/skcipher.c | 132 +++++++++++++++++++++++++++++ include/crypto/internal/skcipher.h | 10 +++ include/crypto/skcipher.h | 28 ++++++ 3 files changed, 170 insertions(+) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 617e840432b17..c0100ab0caa82 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -432,15 +433,139 @@ int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, } EXPORT_SYMBOL_GPL(crypto_skcipher_setkey); +/* IV size for the 128-bit LE-counter multi-data-unit convention. */ +#define SKCIPHER_MDU_IVSIZE 16 + +static inline void skcipher_iv_inc_le128(u8 *iv) +{ + __le64 lo_le, hi_le; + u64 lo; + + memcpy(&lo_le, iv, 8); + memcpy(&hi_le, iv + 8, 8); + lo = le64_to_cpu(lo_le) + 1; + lo_le = cpu_to_le64(lo); + memcpy(iv, &lo_le, 8); + if (unlikely(lo == 0)) { + hi_le = cpu_to_le64(le64_to_cpu(hi_le) + 1); + memcpy(iv + 8, &hi_le, 8); + } +} + +/* + * Dispatch a multi-data-unit request as one single-DU sub-request per + * unit. Each unit's IV is the caller's IV plus the unit index, taken + * as a 128-bit little-endian counter. A pair of scatter_walks advances + * through src/dst in a single linear pass (O(entries + units)); building + * each sub-request's view with scatterwalk_ffwd() would instead rescan + * from the head every unit, i.e. O(units^2). + */ +static int skcipher_split_data_units(struct skcipher_request *req, + int (*body)(struct skcipher_request *)) +{ + const unsigned int du = req->data_unit_size; + const unsigned int total = req->cryptlen; + struct scatterlist *orig_src = req->src; + struct scatterlist *orig_dst = req->dst; + bool inplace = orig_src == orig_dst; + struct scatter_walk src_walk, dst_walk; + struct scatterlist src_sg[2], dst_sg[2]; + u8 iv_orig[SKCIPHER_MDU_IVSIZE]; + u8 iv_work[SKCIPHER_MDU_IVSIZE]; + unsigned int off; + int err = 0; + + memcpy(iv_orig, req->iv, sizeof(iv_orig)); + memcpy(iv_work, iv_orig, sizeof(iv_orig)); + + sg_init_table(src_sg, 2); + scatterwalk_start(&src_walk, orig_src); + if (!inplace) { + sg_init_table(dst_sg, 2); + scatterwalk_start(&dst_walk, orig_dst); + } + + /* Stop the per-DU body from re-entering the splitter. */ + req->data_unit_size = 0; + req->src = src_sg; + req->dst = inplace ? src_sg : dst_sg; + + for (off = 0; off < total; off += du) { + req->cryptlen = du; + scatterwalk_get_sglist(&src_walk, src_sg); + scatterwalk_skip(&src_walk, du); + if (!inplace) { + scatterwalk_get_sglist(&dst_walk, dst_sg); + scatterwalk_skip(&dst_walk, du); + } + + err = body(req); + if (err) + break; + + skcipher_iv_inc_le128(iv_work); + memcpy(req->iv, iv_work, sizeof(iv_work)); + } + + /* Caller-visible IV is the starting IV regardless of outcome. */ + memcpy(req->iv, iv_orig, sizeof(iv_orig)); + req->src = orig_src; + req->dst = orig_dst; + req->cryptlen = total; + req->data_unit_size = du; + return err; +} + +static int crypto_skcipher_validate_multi_du(struct skcipher_request *req) +{ + const unsigned int du = req->data_unit_size; + struct crypto_skcipher *tfm; + struct skcipher_alg *alg; + u32 cra_flags; + + if (likely(!du)) + return 0; + if (!is_power_of_2(du) || du < SKCIPHER_MDU_IVSIZE) + return -EINVAL; + if (!req->cryptlen || (req->cryptlen & (du - 1))) + return -EINVAL; + + tfm = crypto_skcipher_reqtfm(req); + alg = crypto_skcipher_alg(tfm); + + /* lskcipher's *_sg path doesn't honour data_unit_size. */ + if (alg->co.base.cra_type != &crypto_skcipher_type) + return -EOPNOTSUPP; + + /* Capability mismatch, not a malformed request: report -EOPNOTSUPP. */ + if (crypto_skcipher_ivsize(tfm) != SKCIPHER_MDU_IVSIZE) + return -EOPNOTSUPP; + + /* The auto-splitter is sync-only; native drivers own async dispatch. */ + cra_flags = alg->co.base.cra_flags; + if ((cra_flags & CRYPTO_ALG_ASYNC) && + !(cra_flags & CRYPTO_ALG_SKCIPHER_NATIVE_MULTI_DU)) + return -EOPNOTSUPP; + + return 0; +} + int crypto_skcipher_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); + int err; if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) return -ENOKEY; + err = crypto_skcipher_validate_multi_du(req); + if (err) + return err; if (alg->co.base.cra_type != &crypto_skcipher_type) return crypto_lskcipher_encrypt_sg(req); + if (req->data_unit_size && + !(alg->co.base.cra_flags & CRYPTO_ALG_SKCIPHER_NATIVE_MULTI_DU)) + return skcipher_split_data_units(req, alg->encrypt); return alg->encrypt(req); } EXPORT_SYMBOL_GPL(crypto_skcipher_encrypt); @@ -449,11 +574,18 @@ int crypto_skcipher_decrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); + int err; if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) return -ENOKEY; + err = crypto_skcipher_validate_multi_du(req); + if (err) + return err; if (alg->co.base.cra_type != &crypto_skcipher_type) return crypto_lskcipher_decrypt_sg(req); + if (req->data_unit_size && + !(alg->co.base.cra_flags & CRYPTO_ALG_SKCIPHER_NATIVE_MULTI_DU)) + return skcipher_split_data_units(req, alg->decrypt); return alg->decrypt(req); } EXPORT_SYMBOL_GPL(crypto_skcipher_decrypt); diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index a965b6aabf616..4c826f3bc715f 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -21,6 +21,16 @@ */ #define CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE CRYPTO_ALG_OPTIONAL_KEY +/* + * Set by an skcipher that handles skcipher_request::data_unit_size > 0 + * natively in one pass; otherwise the API splits the request. Lives in + * the type-specific 0xff000000 cra_flags range. A native driver must + * derive per-DU IVs as a 128-bit LE counter and leave @iv at the + * caller-supplied starting value on return, success or error, matching + * the auto-splitter so the two paths are observably identical. + */ +#define CRYPTO_ALG_SKCIPHER_NATIVE_MULTI_DU 0x01000000 + struct aead_request; struct rtattr; diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index 4efe2ca8c4d10..ced1fae08147d 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -31,6 +31,11 @@ struct scatterlist; /** * struct skcipher_request - Symmetric key cipher request * @cryptlen: Number of bytes to encrypt or decrypt + * @data_unit_size: Size in bytes of each data unit, or 0 for a + * single-data-unit request (the default). When non-zero, + * must be a power of two, @cryptlen must be a positive + * multiple of it, and per-DU IVs are derived from @iv as a + * 128-bit little-endian counter. * @iv: Initialisation Vector * @src: Source SG list * @dst: Destination SG list @@ -39,6 +44,7 @@ struct scatterlist; */ struct skcipher_request { unsigned int cryptlen; + unsigned int data_unit_size; u8 *iv; @@ -225,6 +231,7 @@ struct lskcipher_alg { struct skcipher_request *name = \ (((struct skcipher_request *)__##name##_desc)->base.tfm = \ crypto_sync_skcipher_tfm((_tfm)), \ + ((struct skcipher_request *)__##name##_desc)->data_unit_size = 0, \ (void *)__##name##_desc) /** @@ -819,6 +826,8 @@ static inline void skcipher_request_set_tfm(struct skcipher_request *req, struct crypto_skcipher *tfm) { req->base.tfm = crypto_skcipher_tfm(tfm); + /* Reused requests default to single-data-unit. */ + req->data_unit_size = 0; } static inline void skcipher_request_set_sync_tfm(struct skcipher_request *req, @@ -937,5 +946,24 @@ static inline void skcipher_request_set_crypt( req->iv = iv; } +/** + * skcipher_request_set_data_unit_size() - submit as multiple data units + * @req: request handle + * @data_unit_size: data-unit size in bytes (power of two), or 0 to disable + * + * Process @req as @cryptlen / @data_unit_size data units sharing one starting + * @iv, with per-DU IVs derived as a 128-bit little-endian counter. @cryptlen + * must be a positive multiple of @data_unit_size, else the encrypt/decrypt + * call returns -EINVAL; a target that cannot do multi-DU (ivsize != 16, an + * lskcipher, or async without native support) returns -EOPNOTSUPP. Unlike + * the single-DU path, @iv is preserved across the call regardless of outcome. + */ +static inline void +skcipher_request_set_data_unit_size(struct skcipher_request *req, + unsigned int data_unit_size) +{ + req->data_unit_size = data_unit_size; +} + #endif /* _CRYPTO_SKCIPHER_H */ From 843d21bad370859777bc8a83fea07f3bf4cfedfa Mon Sep 17 00:00:00 2001 From: Leonid Ravich Date: Mon, 15 Jun 2026 11:14:58 +0000 Subject: [PATCH 3/4] crypto: testmgr - test for multi-data-unit dispatch Add a test that runs on every skcipher with ivsize == 16. It encrypts random plaintext two ways and compares: 1. one batched request with skcipher_request_set_data_unit_size() set, over a deliberately fragmented scatterlist whose entries do not align to the data-unit size (so per-DU views cross SG entries and exercise the scatter_walk cursor), and 2. an independent reference of N single-DU requests with IVs walked as a 128-bit LE counter, matching the convention documented in skcipher_request_set_data_unit_size(). The two must produce byte-identical ciphertext; this pins the IV convention rather than only checking encrypt/decrypt symmetry. The batched ciphertext is then round-tripped back to plaintext, and the caller IV is checked unchanged. Iterates over typical data unit sizes (512, 1024, 2048, 4096). Algorithms the validator rejects for multi-DU return -EOPNOTSUPP on the first call and skip cleanly; a genuine mismatch returns -EBADMSG so it cannot be confused with a skip. Signed-off-by: Leonid Ravich --- crypto/testmgr.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4958211fbfa93..cb5e583b9c4e7 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3210,6 +3210,194 @@ static int test_skcipher(int enc, const struct cipher_test_suite *suite, return 0; } +/* Increment a 16-byte IV as a little-endian 128-bit counter. */ +static void test_mdu_iv_inc(u8 iv[16]) +{ + int i; + + for (i = 0; i < 16; i++) + if (++iv[i]) + break; +} + +/* + * Encrypt one du_size block with a plain single-DU request; used to + * build an independent reference for the batched dispatch. + */ +static int test_mdu_ref_encrypt(struct crypto_skcipher *tfm, const u8 *in, + u8 *out, unsigned int du_size, const u8 iv[16]) +{ + struct skcipher_request *req; + struct scatterlist sg_in, sg_out; + DECLARE_CRYPTO_WAIT(wait); + u8 ivbuf[16]; + int err; + + req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + return -ENOMEM; + memcpy(ivbuf, iv, 16); + memcpy(out, in, du_size); + sg_init_one(&sg_in, out, du_size); + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &wait); + skcipher_request_set_crypt(req, &sg_in, &sg_in, du_size, ivbuf); + err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); + skcipher_request_free(req); + return err; +} + +/* + * Build a deliberately fragmented SG over @buf: entries that do not + * align to du_size, so the splitter's per-DU views cross SG entries + * and exercise the scatter_walk cursor. + */ +static void test_mdu_sg_fragment(struct scatterlist *sg, unsigned int nents, + u8 *buf, unsigned int total) +{ + unsigned int chunk = total / nents; + unsigned int off = 0, i; + + sg_init_table(sg, nents); + for (i = 0; i < nents; i++) { + unsigned int len = (i == nents - 1) ? total - off : chunk; + + sg_set_buf(&sg[i], buf + off, len); + off += len; + } +} + +/* + * Multi-DU test: verify the batched dispatch produces byte-identical + * ciphertext to an independent N x single-DU reference with per-DU IVs + * walked as a 128-bit LE counter (pins the IV convention, not just + * enc/dec symmetry), over a fragmented SG, then round-trips. Real + * mismatches return -EBADMSG; ineligible algorithms skip via the + * validator's -EOPNOTSUPP. + */ +#define TEST_MDU_NR_UNITS 4 +#define TEST_MDU_NR_FRAGS 5 +static int test_skcipher_multi_du_one(struct crypto_skcipher *tfm, + unsigned int du_size) +{ + const char *driver = crypto_skcipher_driver_name(tfm); + const unsigned int total = du_size * TEST_MDU_NR_UNITS; + struct skcipher_request *req = NULL; + struct scatterlist sg[TEST_MDU_NR_FRAGS]; + DECLARE_CRYPTO_WAIT(wait); + u8 iv_orig[16], iv_work[16], iv_ref[16]; + u8 *plain = NULL, *buf = NULL, *ref = NULL; + unsigned int u; + int err; + + plain = kmalloc(total, GFP_KERNEL); + buf = kmalloc(total, GFP_KERNEL); + ref = kmalloc(total, GFP_KERNEL); + req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!plain || !buf || !ref || !req) { + err = -ENOMEM; + goto out; + } + + get_random_bytes(plain, total); + get_random_bytes(iv_orig, sizeof(iv_orig)); + + /* Reference: per-DU single requests with LE128-walked IVs. */ + memcpy(iv_ref, iv_orig, sizeof(iv_orig)); + for (u = 0; u < TEST_MDU_NR_UNITS; u++) { + err = test_mdu_ref_encrypt(tfm, plain + u * du_size, + ref + u * du_size, du_size, iv_ref); + /* First single-DU call reveals an ineligible algorithm. */ + if (err == -EOPNOTSUPP && u == 0) + goto out; + if (err) { + pr_err("alg: skcipher: %s multi-DU ref encrypt failed (du=%u): %d\n", + driver, du_size, err); + goto out; + } + test_mdu_iv_inc(iv_ref); + } + + /* Batched: one request over a fragmented SG. */ + memcpy(buf, plain, total); + memcpy(iv_work, iv_orig, sizeof(iv_orig)); + test_mdu_sg_fragment(sg, TEST_MDU_NR_FRAGS, buf, total); + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &wait); + skcipher_request_set_crypt(req, sg, sg, total, iv_work); + skcipher_request_set_data_unit_size(req, du_size); + err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); + if (err == -EOPNOTSUPP) + goto out; + if (err) { + pr_err("alg: skcipher: %s multi-DU encrypt failed (du=%u): %d\n", + driver, du_size, err); + goto out; + } + if (memcmp(buf, ref, total) != 0) { + pr_err("alg: skcipher: %s multi-DU ciphertext differs from single-DU reference (du=%u)\n", + driver, du_size); + err = -EBADMSG; + goto out; + } + /* req->iv must be unchanged after multi-DU dispatch. */ + if (memcmp(iv_work, iv_orig, sizeof(iv_orig)) != 0) { + pr_err("alg: skcipher: %s multi-DU encrypt mutated caller IV (du=%u)\n", + driver, du_size); + err = -EBADMSG; + goto out; + } + + /* Round-trip the batched ciphertext back to plaintext. */ + test_mdu_sg_fragment(sg, TEST_MDU_NR_FRAGS, buf, total); + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &wait); + skcipher_request_set_crypt(req, sg, sg, total, iv_work); + skcipher_request_set_data_unit_size(req, du_size); + err = crypto_wait_req(crypto_skcipher_decrypt(req), &wait); + if (err) { + pr_err("alg: skcipher: %s multi-DU decrypt failed (du=%u): %d\n", + driver, du_size, err); + goto out; + } + if (memcmp(buf, plain, total) != 0) { + pr_err("alg: skcipher: %s multi-DU round-trip mismatch (du=%u)\n", + driver, du_size); + err = -EBADMSG; + } + +out: + skcipher_request_free(req); + kfree(ref); + kfree(buf); + kfree(plain); + return err; +} + +static int test_skcipher_multi_du(struct crypto_skcipher *tfm) +{ + static const unsigned int du_sizes[] = { 512, 1024, 2048, 4096 }; + unsigned int j; + int err; + + if (crypto_skcipher_ivsize(tfm) != 16) + return 0; + + for (j = 0; j < ARRAY_SIZE(du_sizes); j++) { + err = test_skcipher_multi_du_one(tfm, du_sizes[j]); + /* Ineligible algorithms skip; real failures propagate. */ + if (err == -EOPNOTSUPP) + return 0; + if (err) + return err; + cond_resched(); + } + return 0; +} + static int alg_test_skcipher(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { @@ -3258,6 +3446,10 @@ static int alg_test_skcipher(const struct alg_test_desc *desc, if (err) goto out; + err = test_skcipher_multi_du(tfm); + if (err) + goto out; + err = test_skcipher_vs_generic_impl(desc->generic_driver, req, tsgls); out: free_cipher_test_sglists(tsgls); From 606abefc2aac5a26df49b40b5c1bbfc6960b17dc Mon Sep 17 00:00:00 2001 From: Leonid Ravich Date: Mon, 15 Jun 2026 11:14:59 +0000 Subject: [PATCH 4/4] dm crypt: batch all sectors of a bio per crypto request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submit one skcipher request per bio with skcipher_request_set_data_unit_size(req, cc->sector_size) instead of issuing one request per sector. This removes per-sector overhead in the crypto API hot path: request allocation, callback dispatch, completion handling, and SG setup. The optimisation is enabled automatically at table load when all of the following hold: - the cipher is non-aead (i.e. skcipher), sync, tfms_count 1; - the IV mode advertises sector_iv_le128, i.e. its per-sector IV advances as a 128-bit LE counter, matching the convention documented in skcipher_request_set_data_unit_size(). Only plain64 sets it today (its 64-bit LE counter extends correctly); plain is excluded as its 32-bit counter wraps differently across a 2^32-sector boundary; - ivsize is 16 (the core rejects other sizes with -EOPNOTSUPP); - the iv_gen_ops->post() hook is unset; - dm-integrity is not stacked (no integrity tag or integrity IV). The cipher driver does not need to advertise anything: the crypto API auto-splits multi-data-unit requests for drivers that cannot handle them natively, so dm-crypt sees the same fast batched submission contract regardless of the underlying driver. A new CRYPT_MULTI_DATA_UNIT cipher_flag, set once at construction time, gates the multi-data-unit dispatch. The existing per-sector path in crypt_convert_block_skcipher() is unchanged; the new crypt_convert_block_skcipher_multi() is reached from a small dispatch in crypt_convert() and shares the same backlog/-EBUSY/ -EINPROGRESS flow control with the per-sector path. Heap-allocated scatterlists are stashed in dm_crypt_request and freed in crypt_free_req_skcipher() to avoid races between the synchronous-success free path and async-completion reuse from the request pool. On scatterlist allocation failure the helper returns -EAGAIN, and the core returns -EOPNOTSUPP if a driver turns out unable to do multi-DU; crypt_convert() handles both by clearing its local multi_du flag and falling back to the per-sector path for the rest of the current crypt_convert() invocation, ensuring forward progress on the swap-out-to-dm-crypt path even under total memory exhaustion (the per-sector path uses only cc->req_pool, a mempool with reservoir set up at table-load time, and the inline dmreq->sg_in[]/sg_out[] arrays — no allocation that could fail). Verified end-to-end with a byte-equivalence test: encrypted output of plain64 dm-crypt with the multi-data-unit path matches output of the single-data-unit path bit-for-bit over a 256 MB device, with xts-aes-aesni driving the auto-split path. Signed-off-by: Leonid Ravich --- drivers/md/dm-crypt.c | 215 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 8 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 608b617fb817f..bfb98dd876d72 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -101,6 +101,9 @@ struct dm_crypt_request { struct scatterlist sg_in[4]; struct scatterlist sg_out[4]; u64 iv_sector; + /* Multi-data-unit SG arrays, NULL when sg_in[]/sg_out[] suffice. */ + struct scatterlist *sg_in_ext; + struct scatterlist *sg_out_ext; }; struct crypt_config; @@ -115,6 +118,12 @@ struct crypt_iv_operations { struct dm_crypt_request *dmreq); void (*post)(struct crypt_config *cc, u8 *iv, struct dm_crypt_request *dmreq); + /* + * The per-sector IV advances as a 128-bit LE counter, so a bio's + * consecutive sectors share one starting IV and can be batched into + * a single skcipher request via data_unit_size. + */ + bool sector_iv_le128; }; struct iv_benbi_private { @@ -151,6 +160,7 @@ enum cipher_flags { CRYPT_IV_LARGE_SECTORS, /* Calculate IV from sector_size, not 512B sectors */ CRYPT_ENCRYPT_PREPROCESS, /* Must preprocess data for encryption (elephant) */ CRYPT_KEY_MAC_SIZE_SET, /* The integrity_key_size option was used */ + CRYPT_MULTI_DATA_UNIT, /* Batch all sectors of a bio per crypto request */ }; /* @@ -1018,7 +1028,8 @@ static const struct crypt_iv_operations crypt_iv_plain_ops = { }; static const struct crypt_iv_operations crypt_iv_plain64_ops = { - .generator = crypt_iv_plain64_gen + .generator = crypt_iv_plain64_gen, + .sector_iv_le128 = true, }; static const struct crypt_iv_operations crypt_iv_plain64be_ops = { @@ -1426,12 +1437,126 @@ static int crypt_convert_block_skcipher(struct crypt_config *cc, return r; } +/* + * Submit all remaining sectors of the current bio in one skcipher request. + * Same return convention as crypt_convert_block_skcipher() except for + * -EAGAIN, which the caller must treat as "disable multi-DU and re-enter + * the per-sector path" so swap-out-to-dm-crypt always makes forward + * progress on the mempool reserve. + */ +static int crypt_convert_block_skcipher_multi(struct crypt_config *cc, + struct convert_context *ctx, + struct skcipher_request *req, + unsigned int *out_processed) +{ + const unsigned int sector_size = cc->sector_size; + const gfp_t gfp = GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN; + unsigned int total = ctx->iter_in.bi_size; + unsigned int n_sg_in = 0, n_sg_out = 0; + struct dm_crypt_request *dmreq = dmreq_of_req(cc, req); + struct scatterlist *sg_in = NULL, *sg_out = NULL; + struct bvec_iter iter_in, iter_out; + struct bio_vec bv; + u8 *iv, *org_iv; + int r; + + if (WARN_ON_ONCE(ctx->iter_in.bi_size != ctx->iter_out.bi_size)) + return -EIO; + if (unlikely(total & (sector_size - 1))) + return -EIO; + + iter_in = ctx->iter_in; + iter_in.bi_size = total; + __bio_for_each_bvec(bv, ctx->bio_in, iter_in, iter_in) + n_sg_in++; + + iter_out = ctx->iter_out; + iter_out.bi_size = total; + __bio_for_each_bvec(bv, ctx->bio_out, iter_out, iter_out) + n_sg_out++; + + sg_in = kmalloc_array(n_sg_in, sizeof(*sg_in), gfp); + sg_out = (ctx->bio_in == ctx->bio_out) ? sg_in : + kmalloc_array(n_sg_out, sizeof(*sg_out), gfp); + if (!sg_in || !sg_out) { + kfree(sg_in); + if (sg_out != sg_in) + kfree(sg_out); + return -EAGAIN; + } + + sg_init_table(sg_in, n_sg_in); + { + unsigned int i = 0; + + iter_in = ctx->iter_in; + iter_in.bi_size = total; + __bio_for_each_bvec(bv, ctx->bio_in, iter_in, iter_in) + sg_set_page(&sg_in[i++], bv.bv_page, bv.bv_len, + bv.bv_offset); + } + + if (sg_out != sg_in) { + unsigned int i = 0; + + sg_init_table(sg_out, n_sg_out); + iter_out = ctx->iter_out; + iter_out.bi_size = total; + __bio_for_each_bvec(bv, ctx->bio_out, iter_out, iter_out) + sg_set_page(&sg_out[i++], bv.bv_page, bv.bv_len, + bv.bv_offset); + } + + dmreq->iv_sector = ctx->cc_sector; + if (test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags)) + dmreq->iv_sector >>= cc->sector_shift; + dmreq->ctx = ctx; + + iv = iv_of_dmreq(cc, dmreq); + org_iv = org_iv_of_dmreq(cc, dmreq); + r = cc->iv_gen_ops->generator(cc, org_iv, dmreq); + if (r < 0) + goto out_free_sg; + memcpy(iv, org_iv, cc->iv_size); + + dmreq->sg_in_ext = sg_in; + dmreq->sg_out_ext = (sg_out == sg_in) ? NULL : sg_out; + + skcipher_request_set_crypt(req, sg_in, sg_out, total, iv); + skcipher_request_set_data_unit_size(req, sector_size); + + if (bio_data_dir(ctx->bio_in) == WRITE) + r = crypto_skcipher_encrypt(req); + else + r = crypto_skcipher_decrypt(req); + + /* + * Sync error: kcryptd_async_done won't run, so free the SG + * arrays here. Async returns (-EINPROGRESS, -EBUSY) hand + * ownership to the completion callback. + */ + if (r && r != -EINPROGRESS && r != -EBUSY) + goto out_free_sg; + + *out_processed = total; + return r; + +out_free_sg: + kfree(sg_in); + if (sg_out != sg_in) + kfree(sg_out); + dmreq->sg_in_ext = NULL; + dmreq->sg_out_ext = NULL; + return r; +} + static void kcryptd_async_done(void *async_req, int error); static int crypt_alloc_req_skcipher(struct crypt_config *cc, struct convert_context *ctx) { unsigned int key_index = ctx->cc_sector & (cc->tfms_count - 1); + struct dm_crypt_request *dmreq; if (!ctx->r.req) { ctx->r.req = mempool_alloc(&cc->req_pool, in_interrupt() ? GFP_ATOMIC : GFP_NOIO); @@ -1441,6 +1566,11 @@ static int crypt_alloc_req_skcipher(struct crypt_config *cc, skcipher_request_set_tfm(ctx->r.req, cc->cipher_tfm.tfms[key_index]); + /* Multi-DU SG arrays are owned by the helper that allocates them. */ + dmreq = dmreq_of_req(cc, ctx->r.req); + dmreq->sg_in_ext = NULL; + dmreq->sg_out_ext = NULL; + /* * Use REQ_MAY_BACKLOG so a cipher driver internally backlogs * requests if driver request queue is full. @@ -1487,6 +1617,12 @@ static void crypt_free_req_skcipher(struct crypt_config *cc, struct skcipher_request *req, struct bio *base_bio) { struct dm_crypt_io *io = dm_per_bio_data(base_bio, cc->per_bio_data_size); + struct dm_crypt_request *dmreq = dmreq_of_req(cc, req); + + kfree(dmreq->sg_in_ext); + dmreq->sg_in_ext = NULL; + kfree(dmreq->sg_out_ext); + dmreq->sg_out_ext = NULL; if ((struct skcipher_request *)(io + 1) != req) mempool_free(req, &cc->req_pool); @@ -1515,7 +1651,9 @@ static void crypt_free_req(struct crypt_config *cc, void *req, struct bio *base_ static blk_status_t crypt_convert(struct crypt_config *cc, struct convert_context *ctx, bool atomic, bool reset_pending) { - unsigned int sector_step = cc->sector_size >> SECTOR_SHIFT; + const unsigned int sector_step = cc->sector_size >> SECTOR_SHIFT; + bool multi_du = test_bit(CRYPT_MULTI_DATA_UNIT, &cc->cipher_flags); + unsigned int processed; int r; /* @@ -1536,8 +1674,13 @@ static blk_status_t crypt_convert(struct crypt_config *cc, atomic_inc(&ctx->cc_pending); + processed = cc->sector_size; if (crypt_integrity_aead(cc)) r = crypt_convert_block_aead(cc, ctx, ctx->r.req_aead, ctx->tag_offset); + else if (multi_du) + r = crypt_convert_block_skcipher_multi(cc, ctx, + ctx->r.req, + &processed); else r = crypt_convert_block_skcipher(cc, ctx, ctx->r.req, ctx->tag_offset); @@ -1559,8 +1702,19 @@ static blk_status_t crypt_convert(struct crypt_config *cc, * exit and continue processing in a workqueue */ ctx->r.req = NULL; - ctx->tag_offset++; - ctx->cc_sector += sector_step; + if (!multi_du) { + ctx->tag_offset++; + ctx->cc_sector += sector_step; + } else { + bio_advance_iter(ctx->bio_in, + &ctx->iter_in, + processed); + bio_advance_iter(ctx->bio_out, + &ctx->iter_out, + processed); + ctx->cc_sector += + processed >> SECTOR_SHIFT; + } return BLK_STS_DEV_RESOURCE; } } else { @@ -1574,19 +1728,41 @@ static blk_status_t crypt_convert(struct crypt_config *cc, */ case -EINPROGRESS: ctx->r.req = NULL; - ctx->tag_offset++; - ctx->cc_sector += sector_step; + if (!multi_du) { + ctx->tag_offset++; + ctx->cc_sector += sector_step; + } else { + bio_advance_iter(ctx->bio_in, &ctx->iter_in, + processed); + bio_advance_iter(ctx->bio_out, &ctx->iter_out, + processed); + ctx->cc_sector += processed >> SECTOR_SHIFT; + } continue; /* * The request was already processed (synchronously). */ case 0: atomic_dec(&ctx->cc_pending); - ctx->cc_sector += sector_step; - ctx->tag_offset++; + if (!multi_du) { + ctx->cc_sector += sector_step; + ctx->tag_offset++; + } else { + bio_advance_iter(ctx->bio_in, &ctx->iter_in, + processed); + bio_advance_iter(ctx->bio_out, &ctx->iter_out, + processed); + ctx->cc_sector += processed >> SECTOR_SHIFT; + } if (!atomic) cond_resched(); continue; + /* Multi-DU rejected (no memory or sync-only mismatch): fall back. */ + case -EAGAIN: + case -EOPNOTSUPP: + atomic_dec(&ctx->cc_pending); + multi_du = false; + continue; /* * There was a data integrity error. */ @@ -3063,6 +3239,29 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key) } } + /* + * Enable multi-data-unit batching only when per-DU IVs can be + * derived from one starting IV as a 128-bit LE counter, matching + * skcipher_request_set_data_unit_size(). Only IV modes flagged + * sector_iv_le128 qualify (plain64; not plain, whose 32-bit counter + * wraps differently across a 2^32-sector boundary). ivsize must be + * 16 (the core rejects otherwise) and the cipher must be sync, + * single-tfm, no integrity, no per-sector post() hook. The driver + * advertises nothing: the core auto-splits for drivers that lack + * native support. + */ + if (!crypt_integrity_aead(cc) && cc->tfms_count == 1 && + cc->iv_gen_ops && cc->iv_gen_ops->sector_iv_le128 && + !cc->iv_gen_ops->post && + !cc->integrity_tag_size && !cc->integrity_iv_size && + crypto_skcipher_ivsize(any_tfm(cc)) == 16 && + !(crypto_skcipher_alg(any_tfm(cc))->base.cra_flags & + CRYPTO_ALG_ASYNC)) { + set_bit(CRYPT_MULTI_DATA_UNIT, &cc->cipher_flags); + DMINFO("Using multi-data-unit crypto offload (du=%u)", + cc->sector_size); + } + /* wipe the kernel key payload copy */ if (cc->key_string) memset(cc->key, 0, cc->key_size * sizeof(u8));