Compare commits

..

106 Commits

Author SHA1 Message Date
Tony Hutter 6c3c5fcfbe Tag zfs-2.1.5
META file and changelog updated.

Signed-off-by: Tony Hutter <hutter2@llnl.gov>
2022-06-21 17:00:34 -07:00
Matthew Thode 6e954130d4 Remove install of zfs-load-module.service for dracut
The zfs-load-module.service service is not currently provided by
the OpenZFS repository so we cannot safely assume it exists.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matthew Thode <mthode@mthode.org>
Closes #13574
2022-06-21 10:53:46 -07:00
Ryan Moeller 403d4bc66e FreeBSD: Silence clang unused-but-set-variable
Quick and dirty build fix for warnings being treated as errors.

Signed-off-by: Ryan Moeller <ryan@iXsystems.com>
2022-06-15 11:27:28 -07:00
Alexander Motin 6ff89fe126 Improve sorted scan memory accounting
Since we use two B-trees q_exts_by_size and q_exts_by_addr, we should
count 2x sizeof (range_seg_gap_t) per node.  And since average B-tree
memory efficiency is about 75%, we should increase it to 3x.

Previous code under-counted up to 30% of the memory usage.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored-By: iXsystems, Inc.
Closes #13537
2022-06-15 11:23:49 -07:00
Rich Ercolani cc565f557b Corrected edge case in uncompressed ARC->L2ARC handling
I genuinely don't know why this didn't come up before,
but adding the LZ4 early abort pointed out this flaw,
in which we're allocating a buffer of one size, and
then telling the compressor that we're handing it buffers
of a different size, which may be Very Different - say,
allocating 512b and then telling it the inputs are 128k.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Amanakis <gamanakis@gmail.com>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #13375
2022-06-14 18:10:21 -07:00
Alexander Motin 338188562b Remove wrong assertion in log spacemap
It is typical, but not generally true that if log summary has more
blocks it must also have unflushed metaslabs.  Normally with metaslabs
flushed in order it works, but there are known exceptions, such as
device removal or metaslab being loaded during its flush attempt.

Before 600a02b884 if spa_flush_metaslabs() hit loading metaslab it
usually stopped (unless memlimit is also exceeded), but now it may
flush more metaslabs, just skipping that particular one.  This
increased chances of assertion to fire when the skipped metaslab is
flushed on next iteration if all other metaslabs in that summary
entry are already flushed out of order.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored-By: iXsystems, Inc.
Closes #13486 
Closes #13513
2022-06-06 16:57:56 -07:00
Ryan Moeller 1fdd768d7f libzfs: Fail making a dataset handle gracefully
When a dataset is in the process of being received it gets marked as
inconsistent and should not be used.  We should check for this when
opening a dataset handle in libzfs and return with an appropriate error
set, rather than hitting an abort because of the incomplete data.

zfs_open() passes errno to zfs_standard_error() after observing
make_dataset_handle() fail, which ends up aborting if errno is 0.
Set errno before returning where we know it has not been set already.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <freqlabs@FreeBSD.org>
Closes #13077
2022-06-06 16:57:51 -07:00
наб 56eed508d4 libzfs: mount: don't leak mnt_param_t if mnt_func fails
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12968
2022-06-06 16:57:46 -07:00
Rich Ercolani 271241187b Reject zfs send -RI with nonexistent fromsnap
Right now, zfs send -I dataset@nonexistent dataset@existent fails, but
zfs send -RI dataset@nonexistent dataset@existent does not.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #12574
Closes #12575
2022-06-06 16:57:41 -07:00
Brian Behlendorf fc18fa92c8 Linux 5.18 compat: META
Update the META file to reflect compatibility with the 5.18 kernel.

Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13527
2022-06-01 14:24:49 -07:00
Brian Behlendorf db530f6aa0 autoconf: AC_MSG_CHECKING consistency
Make the wording more consistent for the kernel AC_MSG_CHECKING
output (e.g. "checking whether ...".).  Additionally, group some
of the VFS interface checks with the others.  No functional change.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Attila Fülöp <attila@fueloep.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13529
2022-06-01 14:24:49 -07:00
Brian Behlendorf 1c4e6a312c Linux 5.19 compat: asm/fpu/internal.h
As of the Linux 5.19 kernel the asm/fpu/internal.h header was
entirely removed.  It has been effectively empty since the 5.16
kernel and provides no required functionality.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Attila Fülöp <attila@fueloep.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13529
2022-06-01 14:24:49 -07:00
Brian Behlendorf 69430e39e3 Linux 5.19 compat: zap_flags_t conflict
As of the Linux 5.19 kernel an identically named zap_flags_t typedef
is declared in the include/linux/mm_types.h linux header.  Sadly,
the inclusion of this header cannot be easily avoided.  To resolve
the conflict a #define is used to remap the name in the OpenZFS
sources when building against the Linux kernel.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Brian Behlendorf ee84970d4f Linux 5.19 compat: bdev_start_io_acct() / bdev_end_io_acct()
As of the Linux 5.19 kernel the disk_*_io_acct() helper functions
have been replaced by the bdev_*_io_acct() functions.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Brian Behlendorf fec407fb69 Linux 5.19 compat: aops->read_folio()
As of the Linux 5.19 kernel the readpage() address space operation
has been replaced by read_folio().

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Brian Behlendorf 7ae5ea8864 Linux 5.19 compat: blkdev_issue_secure_erase()
Linux 5.19 commit torvalds/linux@44abff2c0 splits the secure
erase functionality from the blkdev_issue_discard() function.
The blkdev_issue_secure_erase() must now be issued to issue
a secure erase.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Brian Behlendorf 048301b6dc Linux 5.19 compat: bdev_max_secure_erase_sectors()
Linux 5.19 commit torvalds/linux@44abff2c0 removed the
blk_queue_secure_erase() helper function.  The preferred
interface is to now use the bdev_max_secure_erase_sectors()
function to check for discard support.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Brian Behlendorf 9ce5eb18ef Linux 5.19 compat: bdev_max_discard_sectors()
Linux 5.19 commit torvalds/linux@70200574cc removed the
blk_queue_discard() helper function.  The preferred interface
is to now use the bdev_max_discard_sectors() function to check
for discard support.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Brian Behlendorf 5a639f0802 Linux 5.18 compat: bio_alloc()
As for the Linux 5.18 kernel bio_alloc() expects a block_device struct
as an argument.  This removes the need for the bio_set_dev() compatibility
code for 5.18 and newer kernels.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13515
2022-06-01 14:24:49 -07:00
Ryan Moeller 090bda59e3 Silence unused-but-set-variable warning
This was breaking the kmod port build on FreeBSD with Clang 13.

Use the same trick as we do for ASSERT() to make DNODE_VERIFY() use
its parameter at compile time without actually using it at run time
in non-debug builds.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <ryan@iXsystems.com>
Closes #13507
2022-05-27 09:19:37 -07:00
heeplr 2458c7e63a zed: support subject as header in zed_notify_email()
Some minimal MUAs don't support passing the subjects as cmdline option.
This commit checks if "@SUBJECT@" is missing in ZED_EMAIL_OPTS and then
prepends a subject header to the notification message.
Also set a default for ${subject}.

Reviewed-by: Ahelenia Ziemia<C5><84>ska <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Daniel Hiepler <d-git@coderdu.de>
Closes #13440
2022-05-27 09:19:37 -07:00
Umer Saleem 0a688b2345 rpm: Keep debug symbols if configured with '--enable-debuginfo'
Do not strip debug information from packages if '--enable-debuginfo' is
configured.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Umer Saleem <usaleem@ixsystems.com>
Closes #13500
2022-05-27 09:19:37 -07:00
Ryan Moeller fde66e583d FreeBSD: libspl: Add locking around statfs globals
Makes getmntent and getmntany thread-safe for external consumers of
libzfs zpool_disable_datasets, zfs_iter_mounted, libzfs_mnttab_update,
libzfs_mnttab_find.

Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <freqlabs@FreeBSD.org>
Closes #13484
2022-05-27 09:19:37 -07:00
Brian Behlendorf ed16dd7635 Standardize RHEL version check in packages
This is a follow up to 3c35662299 which standardizes how the RHEL
version check is done.  This simpler "0%{?rhel}" check is used
elsewhere in the packages so we do the same here.

Reviewed-by: Neal Gompa <ngompa@datto.com>
Reviewed-by: Rich Ercolani <rincebrain@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13501
2022-05-27 09:19:37 -07:00
Rich Ercolani 5d9c527536 Modified ncompress requirement in RPM to exclude RHEL9
The bug this was working around is no longer present.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #13480
Closes #13490
2022-05-27 09:19:37 -07:00
Brian Behlendorf 5d534f1371 zed: Take no action on scrub/resilver checksum errors
When scrubbing/resilvering a pool it can be counter productive to
cancel the scan and kick of a replace operation to a hot spare
when encountering checksum errors.  In this case, the best course
of action is to allow the scrub/resilver to complete as quickly
as possible and to keep the vdevs fully online if possible.

Realistically, this is less of an issue for a RAIDZ since a
traditional resilver must be used and checksums will be verified.
However, this is not the case for a mirror or dRAID pool which is
sequentially resilvered and checksum verification is deferred
until after the replace operation completes.

Regardless, we apply this policy to all pool types since it's
a good idea for all vdevs.  Degrading additional vdevs has the
potential to make a bad situation worse.  Note the checksum
errors will still be reported as both an event and by
`zpool status`.  This change only prevents the ZED from
proactively taking any action.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13499
2022-05-27 09:19:37 -07:00
Mark Johnston 4184b78be1 zdb: Fix handling of nul termination in symlink targets
The SA attribute containing the symlink target does not include a nul
terminator, so when printing the target zdb would sometimes include
garbage at the end of the string.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Mark Johnston <markj@FreeBSD.org>
Closes #13482
2022-05-27 09:19:37 -07:00
наб 96c7c63994 automake: don't install /e/d/zfs or /e/z/zfs-functions +x
Closes #13496
Backport-of: #13503
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
2022-05-25 14:57:09 -07:00
Savyasachee Jha 115e059818 Multiple dracut module install script cleanups
- Replaced intances of `dracut_install` with `inst_simple`
- Removed calls to `test -x mark_hostonly` because the function is an
inbuilt dracut function
- Removed redundant installation of `systemd-ask-password` and
`systemd-tty-ask-password-agent` because they are already installed by
the systemd module. There is no need to install them again
- Removed multiple calls to the `mark_hostonly` function because the
`inst_simple` has a command-line switch for it
- Cleaned up the installation of the `zpool.cache`, `vdev_id.conf` and
`hostid` files to make the logic easier to follow
- Cleaned up and simplified the systemd service installation logic by
invoking systemctl instead of creating symlinks manually
- Replaced various hard-coded paths with dracut equivalents to better
conform with expected dracut behaviour
- Removed redundant call to `mkdir` (`inst_simple` creates the parent
directory if it does not exist on the destination initrd)

Reviewed-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Andrew J. Hesford <ajh@sideband.org>
Signed-off-by: Savyasachee Jha <hi@savyasacheejha.com>
Closes #13010
2022-05-25 11:09:23 -07:00
Savyasachee Jha 4252517f5f Remove absolute paths to udev rules and binaries for dracut
Since dracut functions can locate both udev rules and binaries, there is
no point in keeping absolute paths in the module setup script. It also
breaks the --sysroot option in dracut. This commit removes mentions to
absolute paths for binaries and udev rules.

Reviewed-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Andrew J. Hesford <ajh@sideband.org>
Signed-off-by: Savyasachee Jha <hi@savyasacheejha.com>
Closes #13010
2022-05-25 11:09:23 -07:00
Savyasachee Jha ebbfc6cb85 Make dracut fail if essential files cannot be installed
Dracut will now fail in initramfs generation if essential files cannot
be installed.

Reviewed-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Andrew J. Hesford <ajh@sideband.org>
Signed-off-by: Savyasachee Jha <hi@savyasacheejha.com>
Closes #13010
2022-05-25 11:09:23 -07:00
Savyasachee Jha 0671f72706 Make better use of dracut functions when building initramfs
Setting up the module involves multiple redundant calls to a bunch of
dracut functions wheich can be combined into one. Additionally, the mass
of code required to load libgcc_s.so* can be replaced with one dracut
function. This has the additional effect of removing errors involving
the non-installation of libgcc_s.so* which are seen on debian bullseye
when using version 2.1.2-1~bpo11+1 from the backports repository.

The systemd binaries are separated out into their own `dracut_install`
function call so they do not get pulled in when dracut does not load the
systemd module.

Reviewed-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Andrew J. Hesford <ajh@sideband.org>
Signed-off-by: Savyasachee Jha <hi@savyasacheejha.com>
Closes #13010
2022-05-25 11:09:23 -07:00
Coleman Kane 05147319b0 Fix compiler warnings about zero-length arrays in inline bitops
The compiler appears to be expanding the unused NULL pointer into a
zero-length array via the inline bitops code. When -Werror=array-bounds
is used, this causes a build failure. Recommended solution is allocate
temporary structures, fill with zeros (to avoid uninitialized data use
warnings), and pass the pointer to those to the inline calls.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Coleman Kane <ckane@colemankane.org>
Closes #13463 
Closes #13465
2022-05-20 10:33:24 -07:00
Brian Behlendorf 0112bc2312 Add missing AC_MSG_RESULT(no) to configure
When the HAVE_IOPS_MKDIR_USERNS check fails output result
as required.
 
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13454
2022-05-20 10:33:24 -07:00
hping b28c0c4bf8 abd_os: remove redundant refcount creation for abd_children
Refcount creation for abd_zero_scatter->abd_children is redundant in
abd_alloc_zero_scatter, as it has been done in abd_init_struct.

In addition, abd_children is undefined when ZFS_DEBUG is disabled, the
reference of abd_children in abd_alloc_zero_scatter breaks build of
libzpool when ZFS_DEBUG is disabled.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Brian Atkinson <batkinson@lanl.gov>
Signed-off-by: Ping Huang <huangping@smartx.com>
Closes #13429
2022-05-20 10:33:24 -07:00
Aidan Harris eee389ba2e Fix functions without a prototype
clang-15 emits the following error message for functions without
a prototype:

fs/zfs/os/linux/spl/spl-kmem-cache.c:1423:27: error:
  a function declaration without a prototype is deprecated
  in all versions of C [-Werror,-Wstrict-prototypes]

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Aidan Harris <me@aidanharr.is>
Closes #13421
2022-05-20 10:33:24 -07:00
Mateusz Guzik 2c5c8bb0a6 FreeBSD: use zero_region instead of allocating a dedicated page
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Brian Atkinson <batkinson@lanl.gov>
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Closes #13406
2022-05-20 10:33:24 -07:00
szubersk 756c3e085b autoconf: Fail when __copy_from_user_inatomic is a non-GPL symbol
A followup to 849c14e048
Fix https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1009242

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: szubersk <szuberskidamian@gmail.com>
Closes #13389
2022-05-20 10:33:24 -07:00
Damian Szuberski 13b1f336d3 PPC get_user workaround
Linux 5.12 PPC 5.12 get_user() and __copy_from_user_inatomic()
inline helpers very indirectly include a reference to the GPL'd
array mmu_feature_keys[] and fails to build. Workaround this by
using copy_from_user() and throwing EFAULT for any calls to
__copy_from_user_inatomic(). This is a workaround until a fix
for Linux commit 7613f5a66becfd0e43a0f34de8518695888f5458
"powerpc/64s/kuap: Use mmu_has_feature()" is fully addressed.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Authored-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: szubersk <szuberskidamian@gmail.com>
Closes #11958
Closes #12590
Closes #13367
2022-05-20 10:33:24 -07:00
Brian Atkinson 60fc173251 Adding ZERO_PAGE detection
On some architectures ZERO_PAGE is unavailable because it references
a GPL exported symbol of empty_zero_page. Originally e08b993 removed
the call to PAGE_ZERO(0) for assignment to the abd_zero_page. However,
a simple check can be done to avoid a kernel allocation and free for
the abd_zero_page if ZERO_PAGE is available.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Brian Atkinson <batkinson@lanl.gov>
Closes #13199
2022-05-20 10:33:24 -07:00
Damian Szuberski 3bb068d4d5 autoconf: Pretend CONFIG_MODULES is always on
- Unconditionally inject `CONFIG_MODULES` make variable
  and `#define CONFIG_MODULES` to Kbuild in `ZFS_LINUX_COMPILE`
  autoconf function to emulate loadable kernel modules support.
  This allows OpenZFS to perform Linux checks despite
  `CONFIG_MODULES=n` in the actual Linux config.

- Add `ZFS_AC_KERNEL_CONFIG_MODULES` check which encompasses
  the logic from `ZFS_AC_KERNEL_TEST_MODULE` with additional
  diagnostic messages to the user

- Removed `ZFS_AC_KERNEL_TEST_MODULE` as it merely duplicates
  every check in `ZFS_AC_KERNEL_CONFIG_DEFINED`

- Moved `ZFS_AC_MODULE_SYMVERS` after `ZFS_AC_KERNEL_CONFIG_DEFINED`
  so the user has a chance to see the proper diagnostic from the
  steps before.

A workaround for Linux's

```
commit 3e3005df73b535cb849cf4ec8075d6aa3c460f68
Author: Masahiro Yamada <masahiroy@kernel.org>
Date:   Wed Mar 31 22:38:03 2021 +0900

kbuild: unify modules(_install) for in-tree and external modules

If you attempt to build or install modules ('make modules(_install)'
with CONFIG_MODULES disabled, you will get a clear error message, but
nothing for external module builds.

Factor out the modules and modules_install rules into the common part,
so you will get the same error message when you try to build external
modules with CONFIG_MODULES=n.

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
```

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: szubersk <szuberskidamian@gmail.com>
Closes #10832
Closes #13361
2022-05-20 10:33:24 -07:00
Damian Szuberski 210b33109d Strengthen Linux kernel capabilities detection
- Add `CONFIG_BLOCK` Linux config requirement to
  `ZFS_AC_KERNEL_CONFIG_DEFINED`. OpenZFS won't compile without
  that block device support due to large amount of functional
  dependencies on it.

- Remove dependency on `groups_alloc()` in
  `ZFS_AC_KERNEL_SRC_GROUP_INFO_GID` to circumvent the missing stub
  in Linux 4.X kernel headers.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: szubersk <szuberskidamian@gmail.com>
Closes #13351
2022-05-20 10:33:24 -07:00
Richard Laager 1d54deb42f zvol_wait: Ignore locked zvols
"When an encrypted zvol is locked the zfs-volume-wait service does not
start.  The /sbin/zvol_wait should not wait for links when the volume
has property keystatus=unavailable."
-- https://bugs.launchpad.net/ubuntu/+source/zfs-linux/+bug/1888405

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Damian Szuberski <szuberskidamian@gmail.com>
Thanks: James Dingwall <james-launchpad@dingwall.me.uk>
Signed-off-by: Richard Laager <rlaager@wiktel.com>
Closes #10662
2022-05-20 10:33:24 -07:00
Ka Ho Ng 1f31889046 FreeBSD: Implement hole-punching support
This adds supports for hole-punching facilities in the FreeBSD kernel
starting from __FreeBSD_version 1400032.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ka Ho Ng <khng@FreeBSD.org>
Sponsored-by: The FreeBSD Foundation
Closes #12458
2022-05-17 11:15:29 -07:00
наб 1467a1bb33 module: zstd: check we don't leak symbols; regenerate symbol map
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Rich Ercolani <rincebrain@gmail.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12988
Closes #13209
(cherry picked from commit 6ef00196db)
2022-05-16 15:48:21 -07:00
наб 2a64eeb6c7 man: zpool-import.8: -d -or -c
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13437
2022-05-10 13:36:37 -07:00
Brian Behlendorf bb29f1eb38 Reduce dbuf_find() lock contention
Holding a dbuf is a common operation which can become highly contended
in dbuf_find() when acquiring the dbuf hash mutex.  This is particularly
true on Linux when reading/writing volumes since by default up to 32
threads from the zvol_taskq may be taking a hold of the same dbuf.
This should also be observable on FreeBSD as long as there are enough
processes accessing the volume concurrently.

This is further aggregrated by the fact that only the block id will
be unique when calculating the dbuf hash for a single volume.  The
objset id, object id, and level will be the same for data blocks.
This has been observed to result in a somehwat less than uniform hash
distribution and a longer than expected max hash chain depth (~20)
on a large memory system (256 GB) using volumes.

This commit improves the siutation by switching the hash mutex to
an rwlock to allow concurrent lookups, and increasing DBUF_RWLOCKS
from 2048 to 8192 to further reduce the odds of a hash collision.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13405
2022-05-06 12:02:45 -07:00
наб 1184df6b93 contrib: dracut: remove getargbool polyfill
It was originally released in dracut 008 in February 2011;
we can probably drop it now

Upstream-commit: 47a02e3972
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 1781ee703b Add dracut.zfs.7
Thorough documentation with a dracut.bootup(7)-style flowchart,
dracut.cmdline(7)-style cmdline listing,
and per-file docs like the old README

Upstream-commit: e3fc330d6c
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 0947096044 contrib: dracut: zfs-needshutdown: don't list
Upstream-commit: 1cc9cc2f89
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб a0e81a4074 contrib: dracut: zfs-{rollback,snapshot}-bootfs: order after key loading
This fixes at least one race I got with an encrypted root

Upstream-commit: 6ebdb0b20d
Upstream-commit: b8d9679f36
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб fc41be5a8d contrib: dracut: don't require essentials to be under the same encroot
Upstream-commit: 30c6dce7f7
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 059a563810 contrib: dracut: inline single-use import_pool, move single-use ask_for_password
Also don't set ROOTFS_MOUNTED; the final mention was removed in dracut
011 from July 2011

Upstream-commit: eaf1e06045
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 5c97f76f5a contrib: dracut: zfs-lib: remove find_bootfs
Upstream-commit: dac0b0785a
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 5c0aa409ed contrib: dracut: zfs-lib: simplify ask_for_password
The only user is mount-zfs.sh (non-systemd systems),
so reduce it to what it needs

Upstream-commit: 5d31169d7c
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 71a1d8e5dc contrib; dracut: flatten zfs-load-key, simplify zfs-env-bootfs
Upstream-commit: fec2c613a4
Upstream-change: drop 90zfs/module-setup.sh.in cleanups that don't apply
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 0864c29e7c contrib; dracut: centralise root= parsing, actually support root=s
So far, everything parsed root= manually, which meant that while
zfs-parse.sh was updated, and supposedly supported + -> ' ' conversion,
it meant nothing

Instead, centralise parsing, and allow:
  root=
  root=zfs
  root=zfs:
  root=zfs:AUTO

  root=ZFS=data/set
  root=zfs:data/set
  root=zfs:ZFS=data/set (as a side-effect; allowed but undocumented)

  rootfstype=zfs AND root=data/set <=> root=data/set
  rootfstype=zfs AND root=         <=> root=zfs:AUTO

So rootfstype=zfs /also/ behaves as expected, and + decoding works

Upstream-commit: 245529d85f
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб b551725df4 contrib: dracut: parse-zfs: stop pretending we support FILESYSTEM=
It was added in the original ae26d0465a ("Add dracut support") commit
in 2011, and was then broken a bit later with the advent of
dracut-zfs-generator, or maybe earlier as part of other churn

Either way, it's broken, and has been in 2.0+ as well, and no-one
complained. Stop pretending we support it at all

Upstream-commit: 2c74617bcf
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб ae054e690e contrib: dracut: parse-zfs: drop initqueue-finished for i/f
The switch was released in dracut 009 in March 2011,
we can safely get rid of the compatibility hook

Upstream-commit: 47636f5661
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13291
2022-05-06 12:01:48 -07:00
наб 0657247548 contrib/dracut: zfs-lib: export_all: replace with inline zpool export -a
07a3312f17, which introduced this in
October of 2014, didn't have zpool export -a available; we do

Upstream-commit: 6a41310c70
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13093
2022-05-06 12:01:48 -07:00
jokersus bc03fee94d Remove REMAKE_INITRD
The option has been deprecated in dkms and will break packaging in
future versions. See https://github.com/dell/dkms/commit/7114c62

Upstream-commit: b5c16861e9
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Amanakis <gamanakis@gmail.com>
Signed-off-by: jokersus <jokersus.cava@gmail.com>
Closes #12781
2022-05-06 11:32:45 -07:00
Rich Ercolani ce8ae064d2 Python 3.10 fixes, part 2
There was a fallback case I overlooked in the initial patch, with
a similarly imperfect version extractor.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #12045 
Closes #12673
2022-05-04 11:37:49 -07:00
Brian Behlendorf 4c9c96aba4 Silence unused-but-set-variable warnings
Clang 13.0.0 added support for `Wunused-but-set-parameter` and
`-Wunused-but-set-variable` which correctly detects two unused
variables in zstd resulting in a build failure.  This commit
annotates these instances accordingly.

  https://releases.llvm.org/13.0.1/tools/clang/docs/ReleaseNotes.html#id6

In FSE_createCTable(), malloc() is intentionally defined as NULL when
compiled in the kernel so the variable is unused.

  zstd/lib/compress/fse_compress.c:307:12: error: variable 'size'
  set but not used [-Werror,-Wunused-but-set-variable]

Additionally, in ZSTD_seqDecompressedSize() the assert is compiled
out similarly resulting in an unused variable.

  zstd/lib/compress/zstd_compress_superblock.c:412:12: error: variable
  'litLengthSum' set but not used [-Werror,-Wunused-but-set-variable]

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
2022-05-02 15:42:58 -07:00
наб ecec151c14 module: zfs: freebsd: fix unused, remove argsused
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12844
2022-05-02 15:42:58 -07:00
наб a4f582f0b6 FreeBSD: remove unused variable
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Issue #12899
2022-05-02 15:42:58 -07:00
наб 9e68b734b3 zvol: remove unused variable
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12917
2022-05-02 15:42:58 -07:00
наб a175fe82e6 fm: remove unused variables
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12917
2022-05-02 15:42:58 -07:00
наб b8e1366ee6 zvol: remove unused variable
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12917
2022-05-02 15:42:58 -07:00
наб 7536ad35ca module/zfs: vdev_removal: spa_vdev_remove_thread: remove unused variable
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12187
2022-05-02 15:42:58 -07:00
наб 986d64ccca module/zfs: vdev_indirect: vdev_indirect_repair: remove unused variable
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12187
2022-05-02 15:42:58 -07:00
наб 18e9268087 module/zfs: dbuf: dbuf_read_impl: remove unused variable
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12187
2022-05-02 15:42:58 -07:00
наб 4149e19dfc module/zfs: arc: arc_hdr_realloc_crypt: remove unused variables
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12187
2022-05-02 15:42:58 -07:00
наб 116d447fb5 libzfs: zfs_send: remove unused variable
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12187
2022-05-02 15:42:58 -07:00
наб a1a54b3e47 libzutil: zpool_find_config: remove unused variable
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #12187
2022-05-02 15:42:58 -07:00
Brian Behlendorf ce8d41ef75 Skip spacemaps reading in case of pool readonly import
The only zdb utility require to read metaslab-related data during
read-only pool import because of spacemaps validation. Add global
variable which will allow zdb read spacemaps in case of readonly
import mode.

Reviewed-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Fedor Uporov <fuporov.vstack@gmail.com>
Closes #9095
Closes #12687
2022-04-28 16:47:12 -07:00
наб c0ff5f1560 zfs: holds: dequadratify
Before:
  15  0m0.177s
  30  0m0.653s
  45  0m1.289s
  60  0m2.129s
  75  0m3.264s
  90  0m4.397s
  100 0m5.996s
  117 0m8.552s

After:
  30  0m0.053s
  117 0m0.125s

Upstream-commit: 2a70a09072
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13372
Closes #13373
2022-04-28 15:18:47 -07:00
Brian Behlendorf 49c1346c10 Linux 5.18 compat: replace __set_page_dirty_nobuffers
Replace __set_page_dirty_nobuffers with filemap_dirty_folio.

Upstream-commit: 6b1f86f8e9c7f9de7ca1cb987b2cf25e99b1ae3a
("Merge tag 'folio-5.18b' of
git://git.infradead.org/users/willy/pagecache ")

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Authored-by: Satadru Pramanik <satadru@gmail.com>
Signed-off-by: Satadru Pramanik <satadru@gmail.com>
Closes #13325
Closes #13380
2022-04-28 15:17:38 -07:00
Brian Behlendorf 71cd3726c0 Fix O_APPEND for Linux 3.15 and older kernels
When using a Linux kernel which predates the iov_iter interface the
O_APPEND flag should be applied in zpl_aio_write() via the call to
generic_write_checks().  The updated pos variable  was incorrectly
ignored resulting in the current offset being used.

This issue should only realistically impact the RHEL/CentOS 7.x
kernels which are based on Linux 3.10.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13370 
Closes #13377
2022-04-28 15:15:28 -07:00
наб 642426095a Linux 5.18 compat: kobj_type.default_attrs replaced with default_groups
Upstream-commit: cdb4f26a63c391317e335e6e683a614358e70aeb ("kobject:
 kobj_type: remove default_attrs")
Upstream-commit: 0cdda2edb3
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13357
2022-04-25 10:00:09 -07:00
Alexander Motin 972637dc06 FreeBSD: Fix translation from ABD to physical pages.
In hypothetical case of non-linear ABD with single segment, multiple
to page size but not aligned to it, vdev_geom_fill_unmap_cb() could
fill one page less into bio_ma array.

I am not sure it is expoitable, but better to be safe than sorry.

Reported-by: Mark Johnston <markj@FreeBSD.org>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
(cherry picked from commit 5352f85cddce44e82fb1c4caec3b333e3666d7fd)
2022-04-21 16:59:09 -07:00
Rich Ercolani c220771a47 Corrected oversight in ZERO_RANGE behavior
It turns out, no, in fact, ZERO_RANGE and PUNCH_HOLE do
have differing semantics in some ways - in particular,
one requires KEEP_SIZE, and the other does not.

Also added a zero-range test to catch this, corrected a flaw
that made the punch-hole test succeed vacuously, and a typo
in file_write.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #13329 
Closes #13338
2022-04-21 16:58:07 -07:00
наб 361dc138b1 Document zfs inherit -S's interaction with noninheritable properties
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Damian Szuberski <szuberskidamian@gmail.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Upstream-commit: 92295af800
Closes #11894
Closes #13335
2022-04-21 11:09:35 -07:00
Brian Behlendorf aa1c3c1d1d Linux 5.17 compat: GENHD_FL_EXT_DEVT / GENHD_FL_NO_PART_SCAN
As of the 5.17 kernel the GENHD_FL_EXT_DEVT flag has been removed
and the GENHD_FL_NO_PART_SCAN flag renamed GENHD_FL_NO_PART. Update
zvol_alloc() to set GENHD_FL_NO_PART for the newer kernels which
is sufficient.  The behavior for prior kernels remains unchanged.

1ebe2e5f ("block: remove GENHD_FL_EXT_DEVT")
46e7eac6 ("block: rename GENHD_FL_NO_PART_SCAN to GENHD_FL_NO_PART")

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13294
Closes #13297
2022-04-20 13:44:19 -07:00
Mark Johnston b7546f92ea FreeBSD: Return Mach error codes from VOP_(GET|PUT)PAGES
FreeBSD's memory management system uses its own error numbers and gets
confused when these VOPs return EIO.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reported-by: Peter Holm <pho@FreeBSD.org>
Signed-off-by: Mark Johnston <markj@FreeBSD.org>
Closes #13311
2022-04-19 10:42:54 -07:00
Mark Johnston e9cd90f6e5 FreeBSD: Parameterize ZFS_ENTER/ZFS_VERIFY_VP with an error code
For legacy reasons, a couple of VOPs have to return error numbers that
don't come from the usual errno namespace.  To handle the cases where
ZFS_ENTER or ZFS_VERIFY_ZP fail, we need to be able to override the
default error return value of EIO.  Extend the macros to permit this.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Mark Johnston <markj@FreeBSD.org>
Closes #13311
2022-04-19 10:42:54 -07:00
наб ff23ef0c99 libzfs: import: zpool_clear_label: actually fail if clearing l2arc header fails
Found with -Wunused-but-set-variable on Clang trunk

Upstream-commit: a4e0cee178
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13304
2022-04-15 14:16:59 -07:00
наб 1f4c79b1ce libzfs: sendrecv: always cancel progress thread in zfs_send_one()
This is in line with all the other uses of the progress thread

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #11560
Closes #13284
2022-04-11 15:48:46 -07:00
Riccardo Schirone 35ddd8ee2e Linux 5.18 compat: use address_space_operations->readahead
->readpages was removed and replaced by ->readahead. Define
zpl_readahead for kernels that don't have ->readpages.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Riccardo Schirone <rschirone91@gmail.com>
Closes #13278
2022-04-06 13:15:27 -07:00
Riccardo Schirone 10a9f5fc47 Linux 5.18 compat: blkg_tryget is moved to private headers
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Riccardo Schirone <rschirone91@gmail.com>
Closes #13278
2022-04-06 13:15:27 -07:00
наб 9f7f704507 Linux 5.18 compat: replace genhd.h with blkdev.h includes
blkdev.h includes genhd.h since dawn of upstream git, so this is
globally safe

Upstream-commit: 322cbb50de711814c42fb088f6d31901502c711a ("block:
 remove genhd.h")

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13251
2022-04-06 13:15:27 -07:00
наб 215a8255a9 Linux 5.18 compat: 4-argument bio_alloc()
bio_alloc(gfp_t gfp_mask, unsigned short nr_iovecs)

became

  bio_alloc(struct block_device *bdev, unsigned short nr_vecs,
            unsigned int opf, gfp_t gfp_mask)
passing NULL/0 continues previous behaviour

Upstream-commit: 07888c665b405b1cd3577ddebfeb74f4717a84c4 ("block:
 pass a block_device and opf to bio_alloc")

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Closes #13251
2022-04-06 13:15:27 -07:00
Ryan Moeller a5a28723bd FreeBSD: Use NDFREE_PNBUF if available
NDF_ONLY_PNBUF has been removed from FreeBSD in favor of NDFREE_PNBUF.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <freqlabs@FreeBSD.org>
Closes #13277
2022-04-06 10:29:53 -07:00
Brian Behlendorf 5a9994f5ae Export minimal zfs_refcount interfaces
Lustre makes light use of the zfs_refcount interfaces which
isn't a problem when using a non-debug build of OpenZFS. However,
when debugging is enabled the required symbols are not exported.

Reviewed-by: Olaf Faaland <faaland1@llnl.gov>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #12613
2022-04-06 10:29:00 -07:00
Brian Behlendorf 9f6943504a Default to zfs_dmu_offset_next_sync=1
Strict hole reporting was previously disabled by default as a
performance optimization.  However, this has lead to confusion
over the expected behavior and a variety of workarounds being
adopted by consumers of ZFS.  Change the default behavior to
always report holes and force the TXG sync.

Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Upstream-commit: 05b3eb6d23
Ref: #13261
Closes #12746
2022-04-01 09:59:47 -07:00
наб fe6f2651f5 etc/systemd/zfs-mount-generator: serialise, handle keylocation=http[s]://
* etc/systemd/zfs-mount-generator: serialise

The wins for a relatively normal workload are rather slim:
	real	0.02119s/0.00985s=2.15029x
	user	0.02130s/0.00346s=6.15560x
	sys	0.03858s/0.00643s=6.00062x

	wall-total	0.014518s/0.005925s=2.45009x
	wall-init	0.014518s/0.002457s=5.90684x
	wall-real	0.014518s/0.003467s=4.18668x

But this is a big win on machines with a lot of datasets and expensive
forks.

For example, the gain on a VM on my work laptop with 900+ legacy-mount
Docker datasets, the original gains from the C rewrite were
only five-fold:
	real    0.516s/0.102s=5.05882x
	user    0.237s/0.143s=1.65734x
	sys     0.287s/0.100s=2.87x

And this serial variant gains this back there as well:
	real    0.102s/0.008s=12.75x
	user    0.143s/0.007s=20.42857
	sys     0.100s/0.001s=100x

	wall-total	0.09717s/0.00319s=30.40255x
	wall-init	0.00203s/0.00200s=1.015941x
	wall-real	0.09513s/0.00118s=80.02043x

For a total of
	real    0.516s/0.008s=64.5x
	user    0.237s/0.007s=33.85714x
	sys     0.287s/0.001s=287x

Suggested-by: Richard Laager <rlaager@wiktel.com>

* etc/systemd/zfs-mount-generator: pull in network for keylocation=https

Also simplify RequiresMountsFor= handling
Ref: #11956

Reviewed-by: Richard Laager <rlaager@wiktel.com>
Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Upstream-commit: 4325de09cd
Closes #12138
2022-04-01 09:58:45 -07:00
наб 7fbb90feea libzfs: diff: stream_bytes: use fputc, %hho formats chars
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Rich Ercolani <rincebrain@gmail.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Upstream-commit: a72129edcb
Closes #12829
2022-04-01 09:58:45 -07:00
наб 5a21214be8 zfs, libzfs: diff: accept -h/ZFS_DIFF_NO_MANGLE, disabling path escaping
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Rich Ercolani <rincebrain@gmail.com>
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Upstream-commit: 344bbc82e7
Closes #12829
2022-04-01 09:58:45 -07:00
Tony Hutter 52bad4f23d Tag zfs-2.1.4
META file and changelog updated.

Signed-off-by: Tony Hutter <hutter2@llnl.gov>
2022-03-21 14:38:12 -07:00
Tony Hutter 2b8b89c6b3 zed: Fix mpath autoreplace on Centos 7
A prior commit included a udev check for MPATH_DEVICE_READY to
determine if a path was multipath when doing an autoreplace:

    f2f6c18 zed: Misc multipath autoreplace fixes

However, MPATH_DEVICE_READY is not provided by the older version of
udev that's on Centos 7 (it is on Centos 8).

This patch instead looks for 'mpath-' in the UUID, which works on
both Centos 7 and 8.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #13222
2022-03-18 06:54:48 -07:00
Tony Hutter 90abfdf8ee zed: Misc multipath autoreplace fixes
We recently had a case where our operators replaced a bad
multipathed disk, only to see it fail to autoreplace.  The
zed logs showed that the multipath replacement disk did not pass
the 'is_dm' test in zfs_process_add() even though it should have.
is_dm is set if there exists a sysfs entry for to the
underlying /dev/sd* paths for the multipath disk.  It's
possible this path didn't exist due to a race condition where
the sysfs paths weren't created at the time the udev event came
in to zed, but this was never verified.

This patch updates the check to look for udev properties that
indicate if the new autoreplace disk is an empty multipath disk,
rather than looking for the underlying sysfs entries. It also
adds in additional logging, and fixes a bug where zed allowed
you to use an already zfs-formatted disk from another pool
as a multipath auto-replacement disk.

Furthermore, while testing this patch, I also ran across a case
where a force-faulted disk did not have a ZPOOL_CONFIG_PHYS_PATH
entry in its config.  This prevented it from being autoreplaced.
I added additional logic to derive the PHYS_PATH from the PATH if
the PATH was a /dev/disk/by-vdev/ path.  For example, if PATH
was /dev/disk/by-vdev/L28, then PHYS_PATH would be L28.  This is
safe since by-vdev paths represent physical locations and do not
change between boots.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #13023
2022-03-18 06:54:48 -07:00
Brian Behlendorf 847d03060f Fix ACL checks for NFS kernel server
This PR changes ZFS ACL checks to evaluate
fsuid / fsgid rather than euid / egid to avoid
accidentally granting elevated permissions to
NFS clients.

Reviewed-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Andrew Walker <awalker@ixsystems.com>
Co-authored-by: Ryan Moeller <freqlabs@FreeBSD.org>
Signed-off-by: Ryan Moeller <freqlabs@FreeBSD.org>
Closes #13221
2022-03-20 21:21:18 -07:00
Brian Behlendorf 9e3619c535 Linux 5.16 compat: restore FSR and FSAVE
Commit 3b52ccd7d introduced a flaw where FSR and FSAVE are not restored
when using a Linux 5.16 kernel.  These instructions are only used when
XSAVE is not supported by the processor meaning only some systems will
encounter this issue.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Attila Fülöp <attila@fueloep.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #13210
Closes #13236
2022-03-19 12:48:28 -07:00
Kyle Evans 421750672b module: freebsd: avoid a taking a destroyed lock in zfs_zevent bits
At shutdown time, we drain all of the zevents and set the
ZEVENT_SHUTDOWN flag.  On FreeBSD, we may end up calling
zfs_zevent_destroy() after the zevent_lock has been destroyed while
the sysevent thread is winding down; we observe ESHUTDOWN, then back
out.

Events have already been drained, so just inline the kmem_free call in
sysevent_worker() to avoid the race, and document the assumption that
zfs_zevent_destroy doesn't do anything else useful at that point.

This fixes a panic that can occur at module unload time.

Reviewed-by: Ryan Moeller <freqlabs@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Kyle Evans <kevans@FreeBSD.org>
Closes #13220
2022-03-18 17:11:43 -07:00
Mateusz Guzik 275c756730 FreeBSD: add missing replay check to an assert in zfs_xvattr_set
Reviewed-by: Ryan Moeller <freqlabs@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Closes #13219
2022-03-18 17:11:43 -07:00
наб 0bebcbcf5e get_key_material_https: removed bogus free() call
The get_key_material_https() function error code path had a bogus
free() call, either resulting in double-free or free() of undefined
pointer.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ahelenia Ziemia<C5><84>ska <nabijaczleweli@nabijaczleweli.xyz>
Co-authored-by: Harry Sintonen <sintonen@iki.fi>
Signed-off-by: Harry Sintonen <sintonen@iki.fi>
Closes #13198
2022-03-17 10:22:13 -07:00
Ryan Moeller 7b215d93bc Fix module build with -Werror
This is a direct commit to zfs-2.1-release to fix release builds that
error out on an unused variable.  The issue is avoided on master by a
huge series of commits that change how the ASSERT macros work, but that
is not feasible to backport.

Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Igor Kozhukhov <igor@dilos.org>
Signed-off-by: Ryan Moeller <freqlabs@FreeBSD.org>
Closes #13194 
Closes #13196
2022-03-17 10:18:23 -07:00
133 changed files with 2558 additions and 1846 deletions
+2 -2
View File
@@ -1,10 +1,10 @@
Meta: 1
Name: zfs
Branch: 1.0
Version: 2.1.3
Version: 2.1.5
Release: 1
Release-Tags: relext
License: CDDL
Author: OpenZFS
Linux-Maximum: 5.16
Linux-Maximum: 5.18
Linux-Minimum: 3.10
+6 -1
View File
@@ -103,7 +103,7 @@ endif
endif
PHONY += codecheck
codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck
codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck zstdcheck
PHONY += checkstyle
checkstyle: codecheck commitcheck
@@ -120,6 +120,7 @@ cstyle:
-o -type f -name '*.[hc]' \
! -name 'zfs_config.*' ! -name '*.mod.c' \
! -name 'opt_global.h' ! -name '*_if*.h' \
! -name 'zstd_compat_wrapper.h' \
! -path './module/zstd/lib/*' \
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
@@ -173,6 +174,10 @@ vcscheck:
awk '{c++; print} END {if(c>0) exit 1}' ; \
fi
PHONY += zstdcheck
zstdcheck:
@$(MAKE) -C module/zstd checksymbols
PHONY += lint
lint: cppcheck paxcheck
+12 -1
View File
@@ -110,6 +110,7 @@ extern int zfs_recover;
extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit;
extern int zfs_vdev_async_read_max_active;
extern boolean_t spa_load_verify_dryrun;
extern boolean_t spa_mode_readable_spacemaps;
extern int zfs_reconstruct_indirect_combinations_max;
extern int zfs_btree_verify_intensity;
@@ -3124,13 +3125,18 @@ dump_znode_symlink(sa_handle_t *hdl)
{
int sa_symlink_size = 0;
char linktarget[MAXPATHLEN];
linktarget[0] = '\0';
int error;
error = sa_size(hdl, sa_attr_table[ZPL_SYMLINK], &sa_symlink_size);
if (error || sa_symlink_size == 0) {
return;
}
if (sa_symlink_size >= sizeof (linktarget)) {
(void) printf("symlink size %d is too large\n",
sa_symlink_size);
return;
}
linktarget[sa_symlink_size] = '\0';
if (sa_lookup(hdl, sa_attr_table[ZPL_SYMLINK],
&linktarget, sa_symlink_size) == 0)
(void) printf("\ttarget %s\n", linktarget);
@@ -8469,6 +8475,11 @@ main(int argc, char **argv)
*/
spa_load_verify_dryrun = B_TRUE;
/*
* ZDB should have ability to read spacemaps.
*/
spa_mode_readable_spacemaps = B_TRUE;
kernel_init(SPA_MODE_READ);
if (dump_all)
+20
View File
@@ -35,6 +35,7 @@
#include <sys/fs/zfs.h>
#include <sys/fm/protocol.h>
#include <sys/fm/fs/zfs.h>
#include <sys/zio.h>
#include "zfs_agents.h"
#include "fmd_api.h"
@@ -773,6 +774,8 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
char *failmode = NULL;
boolean_t checkremove = B_FALSE;
uint32_t pri = 0;
int32_t flags = 0;
/*
* If this is a checksum or I/O error, then toss it into the
@@ -795,6 +798,23 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
checkremove = B_TRUE;
} else if (fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM))) {
/*
* We ignore ereports for checksum errors generated by
* scrub/resilver I/O to avoid potentially further
* degrading the pool while it's being repaired.
*/
if (((nvlist_lookup_uint32(nvl,
FM_EREPORT_PAYLOAD_ZFS_ZIO_PRIORITY, &pri) == 0) &&
(pri == ZIO_PRIORITY_SCRUB ||
pri == ZIO_PRIORITY_REBUILD)) ||
((nvlist_lookup_int32(nvl,
FM_EREPORT_PAYLOAD_ZFS_ZIO_FLAGS, &flags) == 0) &&
(flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)))) {
fmd_hdl_debug(hdl, "ignoring '%s' for "
"scrub/resilver I/O", class);
return;
}
if (zcp->zc_data.zc_serd_checksum[0] == '\0') {
zfs_serd_name(zcp->zc_data.zc_serd_checksum,
pool_guid, vdev_guid, "checksum");
+163 -16
View File
@@ -183,14 +183,14 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
nvlist_t *nvroot, *newvd;
pendingdev_t *device;
uint64_t wholedisk = 0ULL;
uint64_t offline = 0ULL;
uint64_t offline = 0ULL, faulted = 0ULL;
uint64_t guid = 0ULL;
char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
char rawpath[PATH_MAX], fullpath[PATH_MAX];
char devpath[PATH_MAX];
int ret;
boolean_t is_dm = B_FALSE;
boolean_t is_sd = B_FALSE;
boolean_t is_mpath_wholedisk = B_FALSE;
uint_t c;
vdev_stat_t *vs;
@@ -211,15 +211,73 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
&enc_sysfs_path);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_OFFLINE, &offline);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_FAULTED, &faulted);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid);
if (offline)
return; /* don't intervene if it was taken offline */
/*
* Special case:
*
* We've seen times where a disk won't have a ZPOOL_CONFIG_PHYS_PATH
* entry in their config. For example, on this force-faulted disk:
*
* children[0]:
* type: 'disk'
* id: 0
* guid: 14309659774640089719
* path: '/dev/disk/by-vdev/L28'
* whole_disk: 0
* DTL: 654
* create_txg: 4
* com.delphix:vdev_zap_leaf: 1161
* faulted: 1
* aux_state: 'external'
* children[1]:
* type: 'disk'
* id: 1
* guid: 16002508084177980912
* path: '/dev/disk/by-vdev/L29'
* devid: 'dm-uuid-mpath-35000c500a61d68a3'
* phys_path: 'L29'
* vdev_enc_sysfs_path: '/sys/class/enclosure/0:0:1:0/SLOT 30 32'
* whole_disk: 0
* DTL: 1028
* create_txg: 4
* com.delphix:vdev_zap_leaf: 131
*
* If the disk's path is a /dev/disk/by-vdev/ path, then we can infer
* the ZPOOL_CONFIG_PHYS_PATH from the by-vdev disk name.
*/
if (physpath == NULL && path != NULL) {
/* If path begins with "/dev/disk/by-vdev/" ... */
if (strncmp(path, DEV_BYVDEV_PATH,
strlen(DEV_BYVDEV_PATH)) == 0) {
/* Set physpath to the char after "/dev/disk/by-vdev" */
physpath = &path[strlen(DEV_BYVDEV_PATH)];
}
}
is_dm = zfs_dev_is_dm(path);
/*
* We don't want to autoreplace offlined disks. However, we do want to
* replace force-faulted disks (`zpool offline -f`). Force-faulted
* disks have both offline=1 and faulted=1 in the nvlist.
*/
if (offline && !faulted) {
zed_log_msg(LOG_INFO, "%s: %s is offline, skip autoreplace",
__func__, path);
return;
}
is_mpath_wholedisk = is_mpath_whole_disk(path);
zed_log_msg(LOG_INFO, "zfs_process_add: pool '%s' vdev '%s', phys '%s'"
" wholedisk %d, %s dm (guid %llu)", zpool_get_name(zhp), path,
physpath ? physpath : "NULL", wholedisk, is_dm ? "is" : "not",
" %s blank disk, %s mpath blank disk, %s labeled, enc sysfs '%s', "
"(guid %llu)",
zpool_get_name(zhp), path,
physpath ? physpath : "NULL",
wholedisk ? "is" : "not",
is_mpath_wholedisk? "is" : "not",
labeled ? "is" : "not",
enc_sysfs_path,
(long long unsigned int)guid);
/*
@@ -253,8 +311,9 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, &newstate) == 0 &&
(newstate == VDEV_STATE_HEALTHY ||
newstate == VDEV_STATE_DEGRADED)) {
zed_log_msg(LOG_INFO, " zpool_vdev_online: vdev %s is %s",
fullpath, (newstate == VDEV_STATE_HEALTHY) ?
zed_log_msg(LOG_INFO,
" zpool_vdev_online: vdev '%s' ('%s') is "
"%s", fullpath, physpath, (newstate == VDEV_STATE_HEALTHY) ?
"HEALTHY" : "DEGRADED");
return;
}
@@ -271,11 +330,12 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
* vdev online to trigger a FMA fault by posting an ereport.
*/
if (!zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOREPLACE, NULL) ||
!(wholedisk || is_dm) || (physpath == NULL)) {
!(wholedisk || is_mpath_wholedisk) || (physpath == NULL)) {
(void) zpool_vdev_online(zhp, fullpath, ZFS_ONLINE_FORCEFAULT,
&newstate);
zed_log_msg(LOG_INFO, "Pool's autoreplace is not enabled or "
"not a whole disk for '%s'", fullpath);
"not a blank disk for '%s' ('%s')", fullpath,
physpath);
return;
}
@@ -287,7 +347,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
(void) snprintf(rawpath, sizeof (rawpath), "%s%s",
is_sd ? DEV_BYVDEV_PATH : DEV_BYPATH_PATH, physpath);
if (realpath(rawpath, devpath) == NULL && !is_dm) {
if (realpath(rawpath, devpath) == NULL && !is_mpath_wholedisk) {
zed_log_msg(LOG_INFO, " realpath: %s failed (%s)",
rawpath, strerror(errno));
@@ -303,12 +363,14 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
if ((vs->vs_state != VDEV_STATE_DEGRADED) &&
(vs->vs_state != VDEV_STATE_FAULTED) &&
(vs->vs_state != VDEV_STATE_CANT_OPEN)) {
zed_log_msg(LOG_INFO, " not autoreplacing since disk isn't in "
"a bad state (currently %d)", vs->vs_state);
return;
}
nvlist_lookup_string(vdev, "new_devid", &new_devid);
if (is_dm) {
if (is_mpath_wholedisk) {
/* Don't label device mapper or multipath disks. */
} else if (!labeled) {
/*
@@ -522,8 +584,11 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
* the dp->dd_compare value.
*/
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
strcmp(dp->dd_compare, path) != 0)
strcmp(dp->dd_compare, path) != 0) {
zed_log_msg(LOG_INFO, " %s: no match (%s != vdev %s)",
__func__, dp->dd_compare, path);
return;
}
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched %s on %s",
dp->dd_prop, path);
@@ -571,6 +636,8 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
ZPOOL_CONFIG_VDEV_TREE, &nvl);
zfs_iter_vdev(zhp, nvl, data);
}
} else {
zed_log_msg(LOG_INFO, "%s: no config\n", __func__);
}
/*
@@ -619,6 +686,72 @@ devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
return (data.dd_found);
}
/*
* Given a device identifier, find any vdevs with a matching by-vdev
* path. Normally we shouldn't need this as the comparison would be
* made earlier in the devphys_iter(). For example, if we were replacing
* /dev/disk/by-vdev/L28, normally devphys_iter() would match the
* ZPOOL_CONFIG_PHYS_PATH of "L28" from the old disk config to "L28"
* of the new disk config. However, we've seen cases where
* ZPOOL_CONFIG_PHYS_PATH was not in the config for the old disk. Here's
* an example of a real 2-disk mirror pool where one disk was force
* faulted:
*
* com.delphix:vdev_zap_top: 129
* children[0]:
* type: 'disk'
* id: 0
* guid: 14309659774640089719
* path: '/dev/disk/by-vdev/L28'
* whole_disk: 0
* DTL: 654
* create_txg: 4
* com.delphix:vdev_zap_leaf: 1161
* faulted: 1
* aux_state: 'external'
* children[1]:
* type: 'disk'
* id: 1
* guid: 16002508084177980912
* path: '/dev/disk/by-vdev/L29'
* devid: 'dm-uuid-mpath-35000c500a61d68a3'
* phys_path: 'L29'
* vdev_enc_sysfs_path: '/sys/class/enclosure/0:0:1:0/SLOT 30 32'
* whole_disk: 0
* DTL: 1028
* create_txg: 4
* com.delphix:vdev_zap_leaf: 131
*
* So in the case above, the only thing we could compare is the path.
*
* We can do this because we assume by-vdev paths are authoritative as physical
* paths. We could not assume this for normal paths like /dev/sda since the
* physical location /dev/sda points to could change over time.
*/
static boolean_t
by_vdev_path_iter(const char *by_vdev_path, const char *devid,
zfs_process_func_t func, boolean_t is_slice)
{
dev_data_t data = { 0 };
data.dd_compare = by_vdev_path;
data.dd_func = func;
data.dd_prop = ZPOOL_CONFIG_PATH;
data.dd_found = B_FALSE;
data.dd_islabeled = is_slice;
data.dd_new_devid = devid;
if (strncmp(by_vdev_path, DEV_BYVDEV_PATH,
strlen(DEV_BYVDEV_PATH)) != 0) {
/* by_vdev_path doesn't start with "/dev/disk/by-vdev/" */
return (B_FALSE);
}
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
return (data.dd_found);
}
/*
* Given a device identifier, find any vdevs with a matching devid.
* On Linux we can match devid directly which is always a whole disk.
@@ -683,15 +816,17 @@ guid_iter(uint64_t pool_guid, uint64_t vdev_guid, const char *devid,
static int
zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
{
char *devpath = NULL, *devid;
char *devpath = NULL, *devid = NULL;
uint64_t pool_guid = 0, vdev_guid = 0;
boolean_t is_slice;
/*
* Expecting a devid string and an optional physical location and guid
*/
if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid) != 0)
if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid) != 0) {
zed_log_msg(LOG_INFO, "%s: no dev identifier\n", __func__);
return (-1);
}
(void) nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devpath);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
@@ -707,6 +842,8 @@ zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
* 1. ZPOOL_CONFIG_DEVID (identifies the unique disk)
* 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location).
* 3. ZPOOL_CONFIG_GUID (identifies unique vdev).
* 4. ZPOOL_CONFIG_PATH for /dev/disk/by-vdev devices only (since
* by-vdev paths represent physical paths).
*/
if (devid_iter(devid, zfs_process_add, is_slice))
return (0);
@@ -717,6 +854,16 @@ zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,
is_slice);
if (devpath != NULL) {
/* Can we match a /dev/disk/by-vdev/ path? */
char by_vdev_path[MAXPATHLEN];
snprintf(by_vdev_path, sizeof (by_vdev_path),
"/dev/disk/by-vdev/%s", devpath);
if (by_vdev_path_iter(by_vdev_path, devid, zfs_process_add,
is_slice))
return (0);
}
return (0);
}
+17 -4
View File
@@ -224,6 +224,8 @@ zed_notify()
# ZED_EMAIL_OPTS. This undergoes the following keyword substitutions:
# - @ADDRESS@ is replaced with the space-delimited recipient email address(es)
# - @SUBJECT@ is replaced with the notification subject
# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification
#
#
# Arguments
# subject: notification subject
@@ -241,7 +243,7 @@ zed_notify()
#
zed_notify_email()
{
local subject="$1"
local subject="${1:-"ZED notification"}"
local pathname="${2:-"/dev/null"}"
: "${ZED_EMAIL_PROG:="mail"}"
@@ -262,12 +264,23 @@ zed_notify_email()
return 1
fi
ZED_EMAIL_OPTS="$(echo "${ZED_EMAIL_OPTS}" \
# construct cmdline options
ZED_EMAIL_OPTS_PARSED="$(echo "${ZED_EMAIL_OPTS}" \
| sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \
-e "s/@SUBJECT@/${subject}/g")"
# shellcheck disable=SC2086
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
# pipe message to email prog
# shellcheck disable=SC2086,SC2248
{
# no subject passed as option?
if [ "${ZED_EMAIL_OPTS%@SUBJECT@*}" = "${ZED_EMAIL_OPTS}" ] ; then
# inject subject header
printf "Subject: %s\n" "${subject}"
fi
# output message
cat "${pathname}"
} |
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS_PARSED} >/dev/null 2>&1
rv=$?
if [ "${rv}" -ne 0 ]; then
zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}"
+1
View File
@@ -30,6 +30,7 @@ ZED_EMAIL_ADDR="root"
# The string @SUBJECT@ will be replaced with the notification subject;
# this should be protected with quotes to prevent word-splitting.
# Email will only be sent if ZED_EMAIL_ADDR is defined.
# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification
#
#ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@"
+10
View File
@@ -215,6 +215,11 @@ zed_udev_monitor(void *arg)
if (type != NULL && type[0] != '\0' &&
strcmp(type, "disk") == 0 &&
part != NULL && part[0] != '\0') {
zed_log_msg(LOG_INFO,
"%s: skip %s since it has a %s partition already",
__func__,
udev_device_get_property_value(dev, "DEVNAME"),
part);
/* skip and wait for partition event */
udev_device_unref(dev);
continue;
@@ -229,6 +234,11 @@ zed_udev_monitor(void *arg)
sectors = udev_device_get_sysattr_value(dev, "size");
if (sectors != NULL &&
strtoull(sectors, NULL, 10) < MINIMUM_SECTORS) {
zed_log_msg(LOG_INFO,
"%s: %s sectors %s < %llu (minimum)",
__func__,
udev_device_get_property_value(dev, "DEVNAME"),
sectors, MINIMUM_SECTORS);
udev_device_unref(dev);
continue;
}
+5 -2
View File
@@ -6593,7 +6593,7 @@ zfs_do_holds(int argc, char **argv)
/*
* 1. collect holds data, set format options
*/
ret = zfs_for_each(argc, argv, flags, types, NULL, NULL, limit,
ret = zfs_for_each(1, argv + i, flags, types, NULL, NULL, limit,
holds_callback, &cb);
if (ret != 0)
++errors;
@@ -7672,7 +7672,7 @@ zfs_do_diff(int argc, char **argv)
int c;
struct sigaction sa;
while ((c = getopt(argc, argv, "FHt")) != -1) {
while ((c = getopt(argc, argv, "FHth")) != -1) {
switch (c) {
case 'F':
flags |= ZFS_DIFF_CLASSIFY;
@@ -7683,6 +7683,9 @@ zfs_do_diff(int argc, char **argv)
case 't':
flags |= ZFS_DIFF_TIMESTAMP;
break;
case 'h':
flags |= ZFS_DIFF_NO_MANGLE;
break;
default:
(void) fprintf(stderr,
gettext("invalid option '%c'\n"), optopt);
+6 -4
View File
@@ -28,15 +28,17 @@ filter_out_deleted_zvols() {
list_zvols() {
read -r default_volmode < /sys/module/zfs/parameters/zvol_volmode
zfs list -t volume -H -o \
name,volmode,receive_resume_token,redact_snaps |
while IFS=" " read -r name volmode token redacted; do # IFS=\t here!
name,volmode,receive_resume_token,redact_snaps,keystatus |
while IFS=" " read -r name volmode token redacted keystatus; do # IFS=\t here!
# /dev links are not created for zvols with volmode = "none"
# or for redacted zvols.
# /dev links are not created for zvols with volmode = "none",
# redacted zvols, or encrypted zvols for which the key has not
# been loaded.
[ "$volmode" = "none" ] && continue
[ "$volmode" = "default" ] && [ "$default_volmode" = "3" ] &&
continue
[ "$redacted" = "-" ] || continue
[ "$keystatus" = "unavailable" ] && continue
# We also ignore partially received zvols if it is
# not an incremental receive, as those won't even have a block
+1 -1
View File
@@ -224,7 +224,7 @@ EOD`
ac_python_version=$PYTHON_VERSION
else
ac_python_version=`$PYTHON -c "import sys; \
print (sys.version[[:3]])"`
print ('.'.join(sys.version.split('.')[[:2]]))"`
fi
fi
+2 -3
View File
@@ -3,16 +3,15 @@ dnl # 5.16 API change
dnl # add_disk grew a must-check return code
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_ADD_DISK], [
ZFS_LINUX_TEST_SRC([add_disk_ret], [
#include <linux/genhd.h>
#include <linux/blkdev.h>
], [
struct gendisk *disk = NULL;
int err = add_disk(disk);
err = err;
])
])
AC_DEFUN([ZFS_AC_KERNEL_ADD_DISK], [
AC_MSG_CHECKING([whether add_disk() returns int])
ZFS_LINUX_TEST_RESULT([add_disk_ret],
+38 -1
View File
@@ -464,7 +464,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_CGROUP_HEADER], [
])
AC_DEFUN([ZFS_AC_KERNEL_BLK_CGROUP_HEADER], [
AC_MSG_CHECKING([for existence of linux/blk-cgroup.h])
AC_MSG_CHECKING([whether linux/blk-cgroup.h exists])
ZFS_LINUX_TEST_RESULT([blk_cgroup_header],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_LINUX_BLK_CGROUP_HEADER, 1,
@@ -474,6 +474,41 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_CGROUP_HEADER], [
])
])
dnl #
dnl # Linux 5.18 API
dnl #
dnl # In 07888c665b405b1cd3577ddebfeb74f4717a84c4 ("block: pass a block_device and opf to bio_alloc")
dnl # bio_alloc(gfp_t gfp_mask, unsigned short nr_iovecs)
dnl # became
dnl # bio_alloc(struct block_device *bdev, unsigned short nr_vecs, unsigned int opf, gfp_t gfp_mask)
dnl # however
dnl # > NULL/0 can be passed, both for the
dnl # > passthrough case on a raw request_queue and to temporarily avoid
dnl # > refactoring some nasty code.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_ALLOC_4ARG], [
ZFS_LINUX_TEST_SRC([bio_alloc_4arg], [
#include <linux/bio.h>
],[
gfp_t gfp_mask = 0;
unsigned short nr_iovecs = 0;
struct block_device *bdev = NULL;
unsigned int opf = 0;
struct bio *__attribute__((unused)) allocated = bio_alloc(bdev, nr_iovecs, opf, gfp_mask);
])
])
AC_DEFUN([ZFS_AC_KERNEL_BIO_ALLOC_4ARG], [
AC_MSG_CHECKING([whether bio_alloc() wants 4 args])
ZFS_LINUX_TEST_RESULT([bio_alloc_4arg],[
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_BIO_ALLOC_4ARG], 1, [bio_alloc() takes 4 arguments])
],[
AC_MSG_RESULT(no)
])
])
AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
ZFS_AC_KERNEL_SRC_REQ
ZFS_AC_KERNEL_SRC_BIO_OPS
@@ -488,6 +523,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
ZFS_AC_KERNEL_SRC_BDEV_SUBMIT_BIO_RETURNS_VOID
ZFS_AC_KERNEL_SRC_BIO_SET_DEV_MACRO
ZFS_AC_KERNEL_SRC_BLK_CGROUP_HEADER
ZFS_AC_KERNEL_SRC_BIO_ALLOC_4ARG
])
AC_DEFUN([ZFS_AC_KERNEL_BIO], [
@@ -512,4 +548,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO], [
ZFS_AC_KERNEL_BIO_BDEV_DISK
ZFS_AC_KERNEL_BDEV_SUBMIT_BIO_RETURNS_VOID
ZFS_AC_KERNEL_BLK_CGROUP_HEADER
ZFS_AC_KERNEL_BIO_ALLOC_4ARG
])
+66 -22
View File
@@ -74,6 +74,8 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_UPDATE_READAHEAD], [
AC_DEFINE(HAVE_BLK_QUEUE_UPDATE_READAHEAD, 1,
[blk_queue_update_readahead() exists])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether disk_update_readahead() exists])
ZFS_LINUX_TEST_RESULT([disk_update_readahead], [
AC_MSG_RESULT(yes)
@@ -86,69 +88,111 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_UPDATE_READAHEAD], [
])
dnl #
dnl # 2.6.32 API,
dnl # blk_queue_discard()
dnl # 5.19: bdev_max_discard_sectors() available
dnl # 2.6.32: blk_queue_discard() available
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD], [
ZFS_LINUX_TEST_SRC([bdev_max_discard_sectors], [
#include <linux/blkdev.h>
],[
struct block_device *bdev __attribute__ ((unused)) = NULL;
unsigned int error __attribute__ ((unused));
error = bdev_max_discard_sectors(bdev);
])
ZFS_LINUX_TEST_SRC([blk_queue_discard], [
#include <linux/blkdev.h>
],[
struct request_queue *q __attribute__ ((unused)) = NULL;
struct request_queue r;
struct request_queue *q = &r;
int value __attribute__ ((unused));
memset(q, 0, sizeof(r));
value = blk_queue_discard(q);
])
])
AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_DISCARD], [
AC_MSG_CHECKING([whether blk_queue_discard() is available])
ZFS_LINUX_TEST_RESULT([blk_queue_discard], [
AC_MSG_CHECKING([whether bdev_max_discard_sectors() is available])
ZFS_LINUX_TEST_RESULT([bdev_max_discard_sectors], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BDEV_MAX_DISCARD_SECTORS, 1,
[bdev_max_discard_sectors() is available])
],[
ZFS_LINUX_TEST_ERROR([blk_queue_discard])
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether blk_queue_discard() is available])
ZFS_LINUX_TEST_RESULT([blk_queue_discard], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_QUEUE_DISCARD, 1,
[blk_queue_discard() is available])
],[
ZFS_LINUX_TEST_ERROR([blk_queue_discard])
])
])
])
dnl #
dnl # 4.8 API,
dnl # blk_queue_secure_erase()
dnl #
dnl # 2.6.36 - 4.7 API,
dnl # blk_queue_secdiscard()
dnl # 5.19: bdev_max_secure_erase_sectors() available
dnl # 4.8: blk_queue_secure_erase() available
dnl # 2.6.36: blk_queue_secdiscard() available
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE], [
ZFS_LINUX_TEST_SRC([bdev_max_secure_erase_sectors], [
#include <linux/blkdev.h>
],[
struct block_device *bdev __attribute__ ((unused)) = NULL;
unsigned int error __attribute__ ((unused));
error = bdev_max_secure_erase_sectors(bdev);
])
ZFS_LINUX_TEST_SRC([blk_queue_secure_erase], [
#include <linux/blkdev.h>
],[
struct request_queue *q __attribute__ ((unused)) = NULL;
struct request_queue r;
struct request_queue *q = &r;
int value __attribute__ ((unused));
memset(q, 0, sizeof(r));
value = blk_queue_secure_erase(q);
])
ZFS_LINUX_TEST_SRC([blk_queue_secdiscard], [
#include <linux/blkdev.h>
],[
struct request_queue *q __attribute__ ((unused)) = NULL;
struct request_queue r;
struct request_queue *q = &r;
int value __attribute__ ((unused));
memset(q, 0, sizeof(r));
value = blk_queue_secdiscard(q);
])
])
AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE], [
AC_MSG_CHECKING([whether blk_queue_secure_erase() is available])
ZFS_LINUX_TEST_RESULT([blk_queue_secure_erase], [
AC_MSG_CHECKING([whether bdev_max_secure_erase_sectors() is available])
ZFS_LINUX_TEST_RESULT([bdev_max_secure_erase_sectors], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_QUEUE_SECURE_ERASE, 1,
[blk_queue_secure_erase() is available])
AC_DEFINE(HAVE_BDEV_MAX_SECURE_ERASE_SECTORS, 1,
[bdev_max_secure_erase_sectors() is available])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether blk_queue_secdiscard() is available])
ZFS_LINUX_TEST_RESULT([blk_queue_secdiscard], [
AC_MSG_CHECKING([whether blk_queue_secure_erase() is available])
ZFS_LINUX_TEST_RESULT([blk_queue_secure_erase], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_QUEUE_SECDISCARD, 1,
[blk_queue_secdiscard() is available])
AC_DEFINE(HAVE_BLK_QUEUE_SECURE_ERASE, 1,
[blk_queue_secure_erase() is available])
],[
ZFS_LINUX_TEST_ERROR([blk_queue_secure_erase])
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether blk_queue_secdiscard() is available])
ZFS_LINUX_TEST_RESULT([blk_queue_secdiscard], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_QUEUE_SECDISCARD, 1,
[blk_queue_secdiscard() is available])
],[
ZFS_LINUX_TEST_ERROR([blk_queue_secure_erase])
])
])
])
])
+53
View File
@@ -294,6 +294,57 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BDEV_WHOLE], [
])
])
dnl #
dnl # 5.19 API: blkdev_issue_secure_erase()
dnl # 3.10 API: blkdev_issue_discard(..., BLKDEV_DISCARD_SECURE)
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE], [
ZFS_LINUX_TEST_SRC([blkdev_issue_secure_erase], [
#include <linux/blkdev.h>
],[
struct block_device *bdev = NULL;
sector_t sector = 0;
sector_t nr_sects = 0;
int error __attribute__ ((unused));
error = blkdev_issue_secure_erase(bdev,
sector, nr_sects, GFP_KERNEL);
])
ZFS_LINUX_TEST_SRC([blkdev_issue_discard_flags], [
#include <linux/blkdev.h>
],[
struct block_device *bdev = NULL;
sector_t sector = 0;
sector_t nr_sects = 0;
unsigned long flags = 0;
int error __attribute__ ((unused));
error = blkdev_issue_discard(bdev,
sector, nr_sects, GFP_KERNEL, flags);
])
])
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE], [
AC_MSG_CHECKING([whether blkdev_issue_secure_erase() is available])
ZFS_LINUX_TEST_RESULT([blkdev_issue_secure_erase], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLKDEV_ISSUE_SECURE_ERASE, 1,
[blkdev_issue_secure_erase() is available])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether blkdev_issue_discard() is available])
ZFS_LINUX_TEST_RESULT([blkdev_issue_discard_flags], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLKDEV_ISSUE_DISCARD, 1,
[blkdev_issue_discard() is available])
],[
ZFS_LINUX_TEST_ERROR([blkdev_issue_discard()])
])
])
])
dnl #
dnl # 5.13 API change
dnl # blkdev_get_by_path() no longer handles ERESTARTSYS
@@ -326,6 +377,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
ZFS_AC_KERNEL_SRC_BLKDEV_CHECK_DISK_CHANGE
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_CHECK_MEDIA_CHANGE
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_WHOLE
ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE
])
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
@@ -340,4 +392,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
ZFS_AC_KERNEL_BLKDEV_BDEV_CHECK_MEDIA_CHANGE
ZFS_AC_KERNEL_BLKDEV_BDEV_WHOLE
ZFS_AC_KERNEL_BLKDEV_GET_ERESTARTSYS
ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE
])
+86 -2
View File
@@ -19,19 +19,48 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEFINED], [
])
])
ZFS_AC_KERNEL_SRC_CONFIG_MODULES
ZFS_AC_KERNEL_SRC_CONFIG_BLOCK
ZFS_AC_KERNEL_SRC_CONFIG_DEBUG_LOCK_ALLOC
ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS
ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE
ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
AC_MSG_CHECKING([for kernel config option compatibility])
ZFS_LINUX_TEST_COMPILE_ALL([config])
AC_MSG_RESULT([done])
ZFS_AC_KERNEL_CONFIG_MODULES
ZFS_AC_KERNEL_CONFIG_BLOCK
ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC
ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
])
dnl #
dnl # Check CONFIG_BLOCK
dnl #
dnl # Verify the kernel has CONFIG_BLOCK support enabled.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_BLOCK], [
ZFS_LINUX_TEST_SRC([config_block], [
#if !defined(CONFIG_BLOCK)
#error CONFIG_BLOCK not defined
#endif
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_CONFIG_BLOCK], [
AC_MSG_CHECKING([whether CONFIG_BLOCK is defined])
ZFS_LINUX_TEST_RESULT([config_block], [
AC_MSG_RESULT([yes])
],[
AC_MSG_RESULT([no])
AC_MSG_ERROR([
*** This kernel does not include the required block device support.
*** Rebuild the kernel with CONFIG_BLOCK=y set.])
])
])
dnl #
@@ -72,6 +101,61 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC], [
])
])
dnl #
dnl # Check CONFIG_MODULES
dnl #
dnl # Verify the kernel has CONFIG_MODULES support enabled.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_MODULES], [
ZFS_LINUX_TEST_SRC([config_modules], [
#if !defined(CONFIG_MODULES)
#error CONFIG_MODULES not defined
#endif
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_CONFIG_MODULES], [
AC_MSG_CHECKING([whether CONFIG_MODULES is defined])
AS_IF([test "x$enable_linux_builtin" != xyes], [
ZFS_LINUX_TEST_RESULT([config_modules], [
AC_MSG_RESULT([yes])
],[
AC_MSG_RESULT([no])
AC_MSG_ERROR([
*** This kernel does not include the required loadable module
*** support!
***
*** To build OpenZFS as a loadable Linux kernel module
*** enable loadable module support by setting
*** `CONFIG_MODULES=y` in the kernel configuration and run
*** `make modules_prepare` in the Linux source tree.
***
*** If you don't intend to enable loadable kernel module
*** support, please compile OpenZFS as a Linux kernel built-in.
***
*** Prepare the Linux source tree by running `make prepare`,
*** use the OpenZFS `--enable-linux-builtin` configure option,
*** copy the OpenZFS sources into the Linux source tree using
*** `./copy-builtin <linux source directory>`,
*** set `CONFIG_ZFS=y` in the kernel configuration and compile
*** kernel as usual.
])
])
], [
ZFS_LINUX_TRY_COMPILE([], [], [
AC_MSG_RESULT([not needed])
],[
AC_MSG_RESULT([error])
AC_MSG_ERROR([
*** This kernel is unable to compile object files.
***
*** Please make sure you prepared the Linux source tree
*** by running `make prepare` there.
])
])
])
])
dnl #
dnl # Check CONFIG_TRIM_UNUSED_KSYMS
dnl #
+29
View File
@@ -0,0 +1,29 @@
dnl #
dnl # On certain architectures `__copy_from_user_inatomic`
dnl # is a GPL exported variable and cannot be used by OpenZFS.
dnl #
dnl #
dnl # Checking if `__copy_from_user_inatomic` is available.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC], [
ZFS_LINUX_TEST_SRC([__copy_from_user_inatomic], [
#include <linux/uaccess.h>
], [
int result __attribute__ ((unused)) = __copy_from_user_inatomic(NULL, NULL, 0);
], [], [ZFS_META_LICENSE])
])
AC_DEFUN([ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC], [
AC_MSG_CHECKING([whether __copy_from_user_inatomic is available])
ZFS_LINUX_TEST_RESULT([__copy_from_user_inatomic_license], [
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
AC_MSG_ERROR([
*** The `__copy_from_user_inatomic()` Linux kernel function is
*** incompatible with the CDDL license and will prevent the module
*** linking stage from succeeding. OpenZFS cannot be compiled.
])
])
])
+24 -7
View File
@@ -2,6 +2,9 @@ dnl #
dnl # Handle differences in kernel FPU code.
dnl #
dnl # Kernel
dnl # 5.19: The asm/fpu/internal.h header was removed, it has been
dnl # effectively empty since the 5.16 kernel.
dnl #
dnl # 5.16: XCR code put into asm/fpu/xcr.h
dnl # HAVE_KERNEL_FPU_XCR_HEADER
dnl #
@@ -33,21 +36,31 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU_HEADER], [
],[
AC_DEFINE(HAVE_KERNEL_FPU_API_HEADER, 1,
[kernel has asm/fpu/api.h])
AC_MSG_RESULT(asm/fpu/api.h)
AC_MSG_CHECKING([whether fpu/xcr header is available])
fpu_headers="asm/fpu/api.h"
ZFS_LINUX_TRY_COMPILE([
#include <linux/module.h>
#include <asm/fpu/xcr.h>
],[
],[
AC_DEFINE(HAVE_KERNEL_FPU_XCR_HEADER, 1,
[kernel has asm/fpu/xcr.h])
AC_MSG_RESULT(asm/fpu/xcr.h)
],[
AC_MSG_RESULT(no asm/fpu/xcr.h)
[kernel has asm/fpu/xcr.h])
fpu_headers="$fpu_headers asm/fpu/xcr.h"
])
ZFS_LINUX_TRY_COMPILE([
#include <linux/module.h>
#include <asm/fpu/internal.h>
],[
],[
AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL_HEADER, 1,
[kernel has asm/fpu/internal.h])
fpu_headers="$fpu_headers asm/fpu/internal.h"
])
AC_MSG_RESULT([$fpu_headers])
],[
AC_MSG_RESULT(i387.h & xcr.h)
AC_MSG_RESULT([i387.h & xcr.h])
])
])
@@ -93,7 +106,9 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
#include <linux/types.h>
#ifdef HAVE_KERNEL_FPU_API_HEADER
#include <asm/fpu/api.h>
#ifdef HAVE_KERNEL_FPU_INTERNAL_HEADER
#include <asm/fpu/internal.h>
#endif
#else
#include <asm/i387.h>
#include <asm/xcr.h>
@@ -130,7 +145,9 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
#include <linux/types.h>
#ifdef HAVE_KERNEL_FPU_API_HEADER
#include <asm/fpu/api.h>
#ifdef HAVE_KERNEL_FPU_INTERNAL_HEADER
#include <asm/fpu/internal.h>
#endif
#else
#include <asm/i387.h>
#include <asm/xcr.h>
+55 -28
View File
@@ -2,6 +2,19 @@ dnl #
dnl # Check for generic io accounting interface.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
ZFS_LINUX_TEST_SRC([bdev_io_acct], [
#include <linux/blkdev.h>
], [
struct block_device *bdev = NULL;
struct bio *bio = NULL;
unsigned long passed_time = 0;
unsigned long start_time;
start_time = bdev_start_io_acct(bdev, bio_sectors(bio),
bio_op(bio), passed_time);
bdev_end_io_acct(bdev, bio_op(bio), start_time);
])
ZFS_LINUX_TEST_SRC([disk_io_acct], [
#include <linux/blkdev.h>
], [
@@ -50,61 +63,75 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT], [
dnl #
dnl # 5.12 API,
dnl # 5.19 API,
dnl #
dnl # bio_start_io_acct() and bio_end_io_acct() became GPL-exported
dnl # so use disk_start_io_acct() and disk_end_io_acct() instead
dnl # disk_start_io_acct() and disk_end_io_acct() have been replaced by
dnl # bdev_start_io_acct() and bdev_end_io_acct().
dnl #
AC_MSG_CHECKING([whether generic disk_*_io_acct() are available])
ZFS_LINUX_TEST_RESULT([disk_io_acct], [
AC_MSG_CHECKING([whether generic bdev_*_io_acct() are available])
ZFS_LINUX_TEST_RESULT([bdev_io_acct], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_DISK_IO_ACCT, 1, [disk_*_io_acct() available])
AC_DEFINE(HAVE_BDEV_IO_ACCT, 1, [bdev_*_io_acct() available])
], [
AC_MSG_RESULT(no)
dnl #
dnl # 5.7 API,
dnl # 5.12 API,
dnl #
dnl # Added bio_start_io_acct() and bio_end_io_acct() helpers.
dnl # bio_start_io_acct() and bio_end_io_acct() became GPL-exported
dnl # so use disk_start_io_acct() and disk_end_io_acct() instead
dnl #
AC_MSG_CHECKING([whether generic bio_*_io_acct() are available])
ZFS_LINUX_TEST_RESULT([bio_io_acct], [
AC_MSG_CHECKING([whether generic disk_*_io_acct() are available])
ZFS_LINUX_TEST_RESULT([disk_io_acct], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BIO_IO_ACCT, 1, [bio_*_io_acct() available])
AC_DEFINE(HAVE_DISK_IO_ACCT, 1, [disk_*_io_acct() available])
], [
AC_MSG_RESULT(no)
dnl #
dnl # 4.14 API,
dnl # 5.7 API,
dnl #
dnl # generic_start_io_acct/generic_end_io_acct now require
dnl # request_queue to be provided. No functional changes,
dnl # but preparation for inflight accounting.
dnl # Added bio_start_io_acct() and bio_end_io_acct() helpers.
dnl #
AC_MSG_CHECKING([whether generic_*_io_acct wants 4 args])
ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_4args],
[generic_start_io_acct], [block/bio.c], [
AC_MSG_CHECKING([whether generic bio_*_io_acct() are available])
ZFS_LINUX_TEST_RESULT([bio_io_acct], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
[generic_*_io_acct() 4 arg available])
AC_DEFINE(HAVE_BIO_IO_ACCT, 1, [bio_*_io_acct() available])
], [
AC_MSG_RESULT(no)
dnl #
dnl # 3.19 API addition
dnl # 4.14 API,
dnl #
dnl # torvalds/linux@394ffa50 allows us to increment
dnl # iostat counters without generic_make_request().
dnl # generic_start_io_acct/generic_end_io_acct now require
dnl # request_queue to be provided. No functional changes,
dnl # but preparation for inflight accounting.
dnl #
AC_MSG_CHECKING(
[whether generic_*_io_acct wants 3 args])
ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_3args],
AC_MSG_CHECKING([whether generic_*_io_acct wants 4 args])
ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_4args],
[generic_start_io_acct], [block/bio.c], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
[generic_*_io_acct() 3 arg available])
AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
[generic_*_io_acct() 4 arg available])
], [
AC_MSG_RESULT(no)
dnl #
dnl # 3.19 API addition
dnl #
dnl # torvalds/linux@394ffa50 allows us to increment
dnl # iostat counters without generic_make_request().
dnl #
AC_MSG_CHECKING(
[whether generic_*_io_acct wants 3 args])
ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_3args],
[generic_start_io_acct], [block/bio.c], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
[generic_*_io_acct() 3 arg available])
], [
AC_MSG_RESULT(no)
])
])
])
])
+58
View File
@@ -0,0 +1,58 @@
dnl #
dnl # 5.17 API change,
dnl #
dnl # GENHD_FL_EXT_DEVT flag removed
dnl # GENHD_FL_NO_PART_SCAN renamed GENHD_FL_NO_PART
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_GENHD_FLAGS], [
ZFS_LINUX_TEST_SRC([genhd_fl_ext_devt], [
#include <linux/blkdev.h>
], [
int flags __attribute__ ((unused)) = GENHD_FL_EXT_DEVT;
])
ZFS_LINUX_TEST_SRC([genhd_fl_no_part], [
#include <linux/blkdev.h>
], [
int flags __attribute__ ((unused)) = GENHD_FL_NO_PART;
])
ZFS_LINUX_TEST_SRC([genhd_fl_no_part_scan], [
#include <linux/blkdev.h>
], [
int flags __attribute__ ((unused)) = GENHD_FL_NO_PART_SCAN;
])
])
AC_DEFUN([ZFS_AC_KERNEL_GENHD_FLAGS], [
AC_MSG_CHECKING([whether GENHD_FL_EXT_DEVT flag is available])
ZFS_LINUX_TEST_RESULT([genhd_fl_ext_devt], [
AC_MSG_RESULT(yes)
AC_DEFINE(ZFS_GENHD_FL_EXT_DEVT, GENHD_FL_EXT_DEVT,
[GENHD_FL_EXT_DEVT flag is available])
], [
AC_MSG_RESULT(no)
AC_DEFINE(ZFS_GENHD_FL_EXT_DEVT, 0,
[GENHD_FL_EXT_DEVT flag is not available])
])
AC_MSG_CHECKING([whether GENHD_FL_NO_PART flag is available])
ZFS_LINUX_TEST_RESULT([genhd_fl_no_part], [
AC_MSG_RESULT(yes)
AC_DEFINE(ZFS_GENHD_FL_NO_PART, GENHD_FL_NO_PART,
[GENHD_FL_NO_PART flag is available])
], [
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether GENHD_FL_NO_PART_SCAN flag is available])
ZFS_LINUX_TEST_RESULT([genhd_fl_no_part_scan], [
AC_MSG_RESULT(yes)
AC_DEFINE(ZFS_GENHD_FL_NO_PART, GENHD_FL_NO_PART_SCAN,
[GENHD_FL_NO_PART_SCAN flag is available])
], [
ZFS_LINUX_TEST_ERROR([GENHD_FL_NO_PART|GENHD_FL_NO_PART_SCAN])
])
])
])
+2 -2
View File
@@ -6,8 +6,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GROUP_INFO_GID], [
ZFS_LINUX_TEST_SRC([group_info_gid], [
#include <linux/cred.h>
],[
struct group_info *gi = groups_alloc(1);
gi->gid[0] = KGIDT_INIT(0);
struct group_info gi __attribute__ ((unused)) = {};
gi.gid[0] = KGIDT_INIT(0);
])
])
+2
View File
@@ -53,6 +53,8 @@ AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [
AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1,
[iops->mkdir() takes struct user_namespace*])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether iops->mkdir() takes umode_t])
ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
AC_MSG_RESULT(yes)
+1 -1
View File
@@ -15,7 +15,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT], [
])
AC_DEFUN([ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT], [
AC_MSG_CHECKING([folio_wait_bit() exists])
AC_MSG_CHECKING([whether folio_wait_bit() exists])
ZFS_LINUX_TEST_RESULT([pagemap_has_folio_wait_bit], [
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_PAGEMAP_FOLIO_WAIT_BIT, 1,
+25
View File
@@ -0,0 +1,25 @@
dnl #
dnl # Linux 5.18 removes address_space_operations ->readpages in favour of
dnl # ->readahead
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_READPAGES], [
ZFS_LINUX_TEST_SRC([vfs_has_readpages], [
#include <linux/fs.h>
static const struct address_space_operations
aops __attribute__ ((unused)) = {
.readpages = NULL,
};
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_VFS_READPAGES], [
AC_MSG_CHECKING([whether aops->readpages exists])
ZFS_LINUX_TEST_RESULT([vfs_has_readpages], [
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_VFS_READPAGES, 1,
[address_space_operations->readpages exists])
],[
AC_MSG_RESULT([no])
])
])
+2 -2
View File
@@ -8,14 +8,14 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_REVALIDATE_DISK], [
ZFS_LINUX_TEST_SRC([revalidate_disk_size], [
#include <linux/genhd.h>
#include <linux/blkdev.h>
], [
struct gendisk *disk = NULL;
(void) revalidate_disk_size(disk, false);
])
ZFS_LINUX_TEST_SRC([revalidate_disk], [
#include <linux/genhd.h>
#include <linux/blkdev.h>
], [
struct gendisk *disk = NULL;
(void) revalidate_disk(disk);
+5 -5
View File
@@ -84,7 +84,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
dnl #
dnl # 3.0 - 3.11 API change
dnl # ->shrink(struct shrinker *, struct shrink_control *sc)
dnl # cs->shrink(struct shrinker *, struct shrink_control *sc)
dnl #
AC_MSG_CHECKING([whether new 2-argument shrinker exists])
ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control], [
@@ -96,14 +96,14 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
dnl #
dnl # 3.12 API change,
dnl # ->shrink() is logically split in to
dnl # ->count_objects() and ->scan_objects()
dnl # cs->shrink() is logically split in to
dnl # cs->count_objects() and cs->scan_objects()
dnl #
AC_MSG_CHECKING([whether ->count_objects callback exists])
AC_MSG_CHECKING([whether cs->count_objects callback exists])
ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control_split], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, 1,
[->count_objects exists])
[cs->count_objects exists])
],[
ZFS_LINUX_TEST_ERROR([shrinker])
])
+37
View File
@@ -0,0 +1,37 @@
dnl #
dnl # Linux 5.2/5.18 API
dnl #
dnl # In cdb4f26a63c391317e335e6e683a614358e70aeb ("kobject: kobj_type: remove default_attrs")
dnl # struct kobj_type.default_attrs
dnl # was finally removed in favour of
dnl # struct kobj_type.default_groups
dnl #
dnl # This was added in aa30f47cf666111f6bbfd15f290a27e8a7b9d854 ("kobject: Add support for default attribute groups to kobj_type"),
dnl # if both are present (5.2-5.17), we prefer default_groups; they're otherwise equivalent
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_SYSFS_DEFAULT_GROUPS], [
ZFS_LINUX_TEST_SRC([sysfs_default_groups], [
#include <linux/kobject.h>
],[
struct kobj_type __attribute__ ((unused)) kt = {
.default_groups = (const struct attribute_group **)NULL };
])
])
AC_DEFUN([ZFS_AC_KERNEL_SYSFS_DEFAULT_GROUPS], [
AC_MSG_CHECKING([whether struct kobj_type.default_groups exists])
ZFS_LINUX_TEST_RESULT([sysfs_default_groups],[
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_SYSFS_DEFAULT_GROUPS], 1, [struct kobj_type has default_groups])
],[
AC_MSG_RESULT(no)
])
])
AC_DEFUN([ZFS_AC_KERNEL_SRC_SYSFS], [
ZFS_AC_KERNEL_SRC_SYSFS_DEFAULT_GROUPS
])
AC_DEFUN([ZFS_AC_KERNEL_SYSFS], [
ZFS_AC_KERNEL_SYSFS_DEFAULT_GROUPS
])
+30
View File
@@ -0,0 +1,30 @@
dnl #
dnl # Linux 5.18 uses filemap_dirty_folio in lieu of
dnl # ___set_page_dirty_nobuffers
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_FILEMAP_DIRTY_FOLIO], [
ZFS_LINUX_TEST_SRC([vfs_has_filemap_dirty_folio], [
#include <linux/pagemap.h>
#include <linux/writeback.h>
static const struct address_space_operations
aops __attribute__ ((unused)) = {
.dirty_folio = filemap_dirty_folio,
};
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_VFS_FILEMAP_DIRTY_FOLIO], [
dnl #
dnl # Linux 5.18 uses filemap_dirty_folio in lieu of
dnl # ___set_page_dirty_nobuffers
dnl #
AC_MSG_CHECKING([whether filemap_dirty_folio exists])
ZFS_LINUX_TEST_RESULT([vfs_has_filemap_dirty_folio], [
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_VFS_FILEMAP_DIRTY_FOLIO, 1,
[filemap_dirty_folio exists])
],[
AC_MSG_RESULT([no])
])
])
+2
View File
@@ -134,6 +134,8 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_IOV_ITER], [
AC_DEFINE(HAVE_IOV_ITER_FAULT_IN_READABLE, 1,
[iov_iter_fault_in_readable() is available])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether fault_in_iov_iter_readable() is available])
ZFS_LINUX_TEST_RESULT([fault_in_iov_iter_readable], [
AC_MSG_RESULT(yes)
+32
View File
@@ -0,0 +1,32 @@
dnl #
dnl # Linux 5.19 uses read_folio in lieu of readpage
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_READ_FOLIO], [
ZFS_LINUX_TEST_SRC([vfs_has_read_folio], [
#include <linux/fs.h>
static int
test_read_folio(struct file *file, struct folio *folio) {
(void) file; (void) folio;
return (0);
}
static const struct address_space_operations
aops __attribute__ ((unused)) = {
.read_folio = test_read_folio,
};
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_VFS_READ_FOLIO], [
dnl #
dnl # Linux 5.19 uses read_folio in lieu of readpage
dnl #
AC_MSG_CHECKING([whether read_folio exists])
ZFS_LINUX_TEST_RESULT([vfs_has_read_folio], [
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_VFS_READ_FOLIO, 1, [read_folio exists])
],[
AC_MSG_RESULT([no])
])
])
+1 -1
View File
@@ -23,7 +23,7 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_SET_PAGE_DIRTY_NOBUFFERS], [
dnl # Linux 5.14 change requires set_page_dirty() to be assigned
dnl # in address_space_operations()
dnl #
AC_MSG_CHECKING([__set_page_dirty_nobuffers exists])
AC_MSG_CHECKING([whether __set_page_dirty_nobuffers exists])
ZFS_LINUX_TEST_RESULT([vfs_has_set_page_dirty_nobuffers], [
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS, 1,
+27
View File
@@ -0,0 +1,27 @@
dnl #
dnl # ZERO_PAGE() is an alias for emtpy_zero_page. On certain architectures
dnl # this is a GPL exported variable.
dnl #
dnl #
dnl # Checking if ZERO_PAGE is exported GPL-only
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_ZERO_PAGE], [
ZFS_LINUX_TEST_SRC([zero_page], [
#include <asm/pgtable.h>
], [
struct page *p __attribute__ ((unused));
p = ZERO_PAGE(0);
], [], [ZFS_META_LICENSE])
])
AC_DEFUN([ZFS_AC_KERNEL_ZERO_PAGE], [
AC_MSG_CHECKING([whether ZERO_PAGE() is GPL-only])
ZFS_LINUX_TEST_RESULT([zero_page_license], [
AC_MSG_RESULT(no)
], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_ZERO_PAGE_GPL_ONLY, 1,
[ZERO_PAGE() is GPL-only])
])
])
+21 -28
View File
@@ -8,8 +8,8 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_QAT
dnl # Sanity checks for module building and CONFIG_* defines
ZFS_AC_KERNEL_TEST_MODULE
ZFS_AC_KERNEL_CONFIG_DEFINED
ZFS_AC_MODULE_SYMVERS
dnl # Sequential ZFS_LINUX_TRY_COMPILE tests
ZFS_AC_KERNEL_FPU_HEADER
@@ -61,6 +61,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_BIO
ZFS_AC_KERNEL_SRC_BLKDEV
ZFS_AC_KERNEL_SRC_BLK_QUEUE
ZFS_AC_KERNEL_SRC_GENHD_FLAGS
ZFS_AC_KERNEL_SRC_REVALIDATE_DISK
ZFS_AC_KERNEL_SRC_GET_DISK_RO
ZFS_AC_KERNEL_SRC_GENERIC_READLINK_GLOBAL
@@ -99,10 +100,14 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_SET_NLINK
ZFS_AC_KERNEL_SRC_SGET
ZFS_AC_KERNEL_SRC_LSEEK_EXECUTE
ZFS_AC_KERNEL_SRC_VFS_FILEMAP_DIRTY_FOLIO
ZFS_AC_KERNEL_SRC_VFS_READ_FOLIO
ZFS_AC_KERNEL_SRC_VFS_GETATTR
ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS
ZFS_AC_KERNEL_SRC_VFS_ITERATE
ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO
ZFS_AC_KERNEL_SRC_VFS_READPAGES
ZFS_AC_KERNEL_SRC_VFS_SET_PAGE_DIRTY_NOBUFFERS
ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE
ZFS_AC_KERNEL_SRC_VFS_GENERIC_WRITE_CHECKS
ZFS_AC_KERNEL_SRC_VFS_IOV_ITER
@@ -131,12 +136,14 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
ZFS_AC_KERNEL_SRC_SIGNAL_STOP
ZFS_AC_KERNEL_SRC_SIGINFO
ZFS_AC_KERNEL_SRC_SYSFS
ZFS_AC_KERNEL_SRC_SET_SPECIAL_STATE
ZFS_AC_KERNEL_SRC_VFS_SET_PAGE_DIRTY_NOBUFFERS
ZFS_AC_KERNEL_SRC_STANDALONE_LINUX_STDARG
ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
ZFS_AC_KERNEL_SRC_ADD_DISK
ZFS_AC_KERNEL_SRC_KTHREAD
ZFS_AC_KERNEL_SRC_ZERO_PAGE
ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
AC_MSG_CHECKING([for available kernel interfaces])
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
@@ -171,6 +178,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_BIO
ZFS_AC_KERNEL_BLKDEV
ZFS_AC_KERNEL_BLK_QUEUE
ZFS_AC_KERNEL_GENHD_FLAGS
ZFS_AC_KERNEL_REVALIDATE_DISK
ZFS_AC_KERNEL_GET_DISK_RO
ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL
@@ -209,10 +217,14 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_SET_NLINK
ZFS_AC_KERNEL_SGET
ZFS_AC_KERNEL_LSEEK_EXECUTE
ZFS_AC_KERNEL_VFS_FILEMAP_DIRTY_FOLIO
ZFS_AC_KERNEL_VFS_READ_FOLIO
ZFS_AC_KERNEL_VFS_GETATTR
ZFS_AC_KERNEL_VFS_FSYNC_2ARGS
ZFS_AC_KERNEL_VFS_ITERATE
ZFS_AC_KERNEL_VFS_DIRECT_IO
ZFS_AC_KERNEL_VFS_READPAGES
ZFS_AC_KERNEL_VFS_SET_PAGE_DIRTY_NOBUFFERS
ZFS_AC_KERNEL_VFS_RW_ITERATE
ZFS_AC_KERNEL_VFS_GENERIC_WRITE_CHECKS
ZFS_AC_KERNEL_VFS_IOV_ITER
@@ -241,12 +253,14 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_BIO_MAX_SEGS
ZFS_AC_KERNEL_SIGNAL_STOP
ZFS_AC_KERNEL_SIGINFO
ZFS_AC_KERNEL_SYSFS
ZFS_AC_KERNEL_SET_SPECIAL_STATE
ZFS_AC_KERNEL_VFS_SET_PAGE_DIRTY_NOBUFFERS
ZFS_AC_KERNEL_STANDALONE_LINUX_STDARG
ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
ZFS_AC_KERNEL_ADD_DISK
ZFS_AC_KERNEL_KTHREAD
ZFS_AC_KERNEL_ZERO_PAGE
ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
])
dnl #
@@ -435,8 +449,6 @@ AC_DEFUN([ZFS_AC_KERNEL], [
AC_SUBST(LINUX)
AC_SUBST(LINUX_OBJ)
AC_SUBST(LINUX_VERSION)
ZFS_AC_MODULE_SYMVERS
])
dnl #
@@ -531,27 +543,6 @@ AC_DEFUN([ZFS_AC_QAT], [
])
])
dnl #
dnl # Basic toolchain sanity check.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_TEST_MODULE], [
AC_MSG_CHECKING([whether modules can be built])
ZFS_LINUX_TRY_COMPILE([], [], [
AC_MSG_RESULT([yes])
],[
AC_MSG_RESULT([no])
if test "x$enable_linux_builtin" != xyes; then
AC_MSG_ERROR([
*** Unable to build an empty module.
])
else
AC_MSG_ERROR([
*** Unable to build an empty module.
*** Please run 'make scripts' inside the kernel source tree.])
fi
])
])
dnl #
dnl # ZFS_LINUX_CONFTEST_H
dnl #
@@ -654,8 +645,10 @@ AC_DEFUN([ZFS_LINUX_COMPILE], [
build kernel modules with LLVM/CLANG toolchain])
AC_TRY_COMMAND([
KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6"
make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC} ${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM} -C $LINUX_OBJ $ARCH_UM
M=$PWD/$1 >$1/build.log 2>&1])
make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC}
${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM}
CONFIG_MODULES=y CFLAGS_MODULE=-DCONFIG_MODULES
-C $LINUX_OBJ $ARCH_UM M=$PWD/$1 >$1/build.log 2>&1])
AS_IF([AC_TRY_COMMAND([$2])], [$3], [$4])
])
+4
View File
@@ -323,6 +323,10 @@ AC_DEFUN([ZFS_AC_RPM], [
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "$(DEBUG_KMEM_TRACKING_ZFS) 1"'
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "$(ASAN_ZFS) 1"'
AS_IF([test "x$enable_debuginfo" = xyes], [
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "__strip /bin/true"'
])
RPM_DEFINE_UTIL=' --define "_initconfdir $(initconfdir)"'
dnl # Make the next three RPM_DEFINE_UTIL additions conditional, since
+1 -3
View File
@@ -1,14 +1,12 @@
#!/bin/sh
. /lib/dracut-zfs-lib.sh
_do_zpool_export() {
ret=0
errs=""
final="${1}"
info "ZFS: Exporting ZFS storage pools..."
errs=$(export_all -F 2>&1)
errs=$(zpool export -aF 2>&1)
ret=$?
[ -z "${errs}" ] || echo "${errs}" | vwarn
if [ "x${ret}" != "x0" ]; then
+61 -101
View File
@@ -6,8 +6,8 @@ check() {
[ "${1}" = "-d" ] && return 0
# Verify the zfs tool chain
for tool in "@sbindir@/zgenhostid" "@sbindir@/zpool" "@sbindir@/zfs" "@mounthelperdir@/mount.zfs" ; do
test -x "$tool" || return 1
for tool in "zgenhostid" "zpool" "zfs" "mount.zfs"; do
command -v "${tool}" >/dev/null || return 1
done
return 0
@@ -19,125 +19,85 @@ depends() {
}
installkernel() {
instmods zfs
instmods zcommon
instmods znvpair
instmods zavl
instmods zunicode
instmods zlua
instmods icp
instmods spl
instmods zlib_deflate
instmods zlib_inflate
instmods -c zfs
}
install() {
inst_rules @udevruledir@/90-zfs.rules
inst_rules @udevruledir@/69-vdev.rules
inst_rules @udevruledir@/60-zvol.rules
dracut_install hostid
dracut_install grep
dracut_install @sbindir@/zgenhostid
dracut_install @sbindir@/zfs
dracut_install @sbindir@/zpool
# Workaround for https://github.com/openzfs/zfs/issues/4749 by
# ensuring libgcc_s.so(.1) is included
if ldd @sbindir@/zpool | grep -qF 'libgcc_s.so'; then
# Dracut will have already tracked and included it
:;
elif command -v gcc-config >/dev/null 2>&1; then
# On systems with gcc-config (Gentoo, Funtoo, etc.):
# Use the current profile to resolve the appropriate path
s="$(gcc-config -c)"
dracut_install "/usr/lib/gcc/${s%-*}/${s##*-}/libgcc_s.so"*
elif [ "$(echo /usr/lib/libgcc_s.so*)" != "/usr/lib/libgcc_s.so*" ]; then
# Try a simple path first
dracut_install /usr/lib/libgcc_s.so*
elif [ "$(echo /lib*/libgcc_s.so*)" != "/lib*/libgcc_s.so*" ]; then
# SUSE
dracut_install /lib*/libgcc_s.so*
else
# Fallback: Guess the path and include all matches
dracut_install /usr/lib*/gcc/**/libgcc_s.so*
inst_rules 90-zfs.rules 69-vdev.rules 60-zvol.rules
inst_multiple \
zgenhostid \
zfs \
zpool \
mount.zfs \
hostid \
grep \
awk \
tr \
cut \
head ||
{ dfatal "Failed to install essential binaries"; exit 1; }
# Adapted from https://github.com/zbm-dev/zfsbootmenu
if ! ldd "$(command -v zpool)" | grep -qF 'libgcc_s.so'; then
# On systems with gcc-config (Gentoo, Funtoo, etc.), use it to find libgcc_s
if command -v gcc-config >/dev/null; then
inst_simple "/usr/lib/gcc/$(s=$(gcc-config -c); echo "${s%-*}/${s##*-}")/libgcc_s.so.1" ||
{ dfatal "Unable to install libgcc_s.so"; exit 1; }
# Otherwise, use dracut's library installation function to find the right one
elif ! inst_libdir_file "libgcc_s.so*"; then
# If all else fails, just try looking for some gcc arch directory
inst_simple /usr/lib/gcc/*/*/libgcc_s.so* ||
{ dfatal "Unable to install libgcc_s.so"; exit 1; }
fi
fi
# shellcheck disable=SC2050
if [ @LIBFETCH_DYNAMIC@ -gt 0 ]; then
for d in $libdirs; do
[ -e "$d/@LIBFETCH_SONAME@" ] && dracut_install "$d/@LIBFETCH_SONAME@"
done
fi
dracut_install @mounthelperdir@/mount.zfs
dracut_install @udevdir@/vdev_id
dracut_install awk
dracut_install cut
dracut_install tr
dracut_install head
dracut_install @udevdir@/zvol_id
inst_hook cmdline 95 "${moddir}/parse-zfs.sh"
if [ -n "$systemdutildir" ] ; then
inst_script "${moddir}/zfs-generator.sh" "$systemdutildir"/system-generators/dracut-zfs-generator
if [ -n "${systemdutildir}" ]; then
inst_script "${moddir}/zfs-generator.sh" "${systemdutildir}/system-generators/dracut-zfs-generator"
fi
inst_hook pre-mount 90 "${moddir}/zfs-load-key.sh"
inst_hook mount 98 "${moddir}/mount-zfs.sh"
inst_hook cleanup 99 "${moddir}/zfs-needshutdown.sh"
inst_hook shutdown 20 "${moddir}/export-zfs.sh"
inst_simple "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh"
if [ -e @sysconfdir@/zfs/zpool.cache ]; then
inst @sysconfdir@/zfs/zpool.cache
type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/zfs/zpool.cache
fi
inst_script "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh"
if [ -e @sysconfdir@/zfs/vdev_id.conf ]; then
inst @sysconfdir@/zfs/vdev_id.conf
type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/zfs/vdev_id.conf
fi
# -H ensures they are marked host-only
# -o ensures there is no error upon absence of these files
inst_multiple -o -H \
"@sysconfdir@/zfs/zpool.cache" \
"@sysconfdir@/zfs/vdev_id.conf"
# Synchronize initramfs and system hostid
if [ -f @sysconfdir@/hostid ]; then
inst @sysconfdir@/hostid
type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/hostid
elif HOSTID="$(hostid 2>/dev/null)" && [ "${HOSTID}" != "00000000" ]; then
zgenhostid -o "${initdir}@sysconfdir@/hostid" "${HOSTID}"
type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/hostid
if ! inst_simple -H @sysconfdir@/hostid; then
if HOSTID="$(hostid 2>/dev/null)" && [ "${HOSTID}" != "00000000" ]; then
zgenhostid -o "${initdir}@sysconfdir@/hostid" "${HOSTID}"
mark_hostonly @sysconfdir@/hostid
fi
fi
if dracut_module_included "systemd"; then
mkdir -p "${initdir}/$systemdsystemunitdir/zfs-import.target.wants"
for _service in "zfs-import-scan.service" "zfs-import-cache.service" ; do
dracut_install "@systemdunitdir@/$_service"
if ! [ -L "${initdir}/$systemdsystemunitdir/zfs-import.target.wants/$_service" ]; then
ln -sf ../$_service "${initdir}/$systemdsystemunitdir/zfs-import.target.wants/$_service"
type mark_hostonly >/dev/null 2>&1 && mark_hostonly "@systemdunitdir@/$_service"
fi
inst_simple "${systemdsystemunitdir}/zfs-import.target"
systemctl -q --root "${initdir}" add-wants initrd.target zfs-import.target
inst_simple "${moddir}/zfs-env-bootfs.service" "${systemdsystemunitdir}/zfs-env-bootfs.service"
systemctl -q --root "${initdir}" add-wants zfs-import.target zfs-env-bootfs.service
for _service in \
"zfs-import-scan.service" \
"zfs-import-cache.service"; do
inst_simple "${systemdsystemunitdir}/${_service}"
systemctl -q --root "${initdir}" add-wants zfs-import.target "${_service}"
done
inst "${moddir}"/zfs-env-bootfs.service "${systemdsystemunitdir}"/zfs-env-bootfs.service
ln -s ../zfs-env-bootfs.service "${initdir}/${systemdsystemunitdir}/zfs-import.target.wants"/zfs-env-bootfs.service
type mark_hostonly >/dev/null 2>&1 && mark_hostonly @systemdunitdir@/zfs-env-bootfs.service
dracut_install systemd-ask-password
dracut_install systemd-tty-ask-password-agent
mkdir -p "${initdir}/$systemdsystemunitdir/initrd.target.wants"
dracut_install @systemdunitdir@/zfs-import.target
if ! [ -L "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import.target ]; then
ln -s ../zfs-import.target "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import.target
type mark_hostonly >/dev/null 2>&1 && mark_hostonly @systemdunitdir@/zfs-import.target
fi
for _service in zfs-snapshot-bootfs.service zfs-rollback-bootfs.service ; do
inst "${moddir}/$_service" "${systemdsystemunitdir}/$_service"
if ! [ -L "${initdir}/$systemdsystemunitdir/initrd.target.wants/$_service" ]; then
ln -s "../$_service" "${initdir}/$systemdsystemunitdir/initrd.target.wants/$_service"
fi
for _service in \
"zfs-snapshot-bootfs.service" \
"zfs-rollback-bootfs.service"; do
inst_simple "${moddir}/${_service}" "${systemdsystemunitdir}/${_service}"
systemctl -q --root "${initdir}" add-wants initrd.target "${_service}"
done
# There isn't a pkg-config variable for this,
# and dracut doesn't automatically resolve anything this'd be next to
local systemdsystemenvironmentgeneratordir
systemdsystemenvironmentgeneratordir="$(pkg-config --variable=prefix systemd || echo "/usr")/lib/systemd/system-environment-generators"
mkdir -p "${initdir}/${systemdsystemenvironmentgeneratordir}"
inst "${moddir}"/import-opts-generator.sh "${systemdsystemenvironmentgeneratordir}"/zfs-import-opts.sh
inst_simple "${moddir}/import-opts-generator.sh" "${systemdutildir}/system-environment-generators/zfs-import-opts.sh"
fi
}
+83 -49
View File
@@ -3,48 +3,73 @@
. /lib/dracut-zfs-lib.sh
ZFS_DATASET=""
ZFS_POOL=""
case "${root}" in
zfs:*) ;;
*) return ;;
esac
decode_root_args || return 0
GENERATOR_FILE=/run/systemd/generator/sysroot.mount
GENERATOR_EXTENSION=/run/systemd/generator/sysroot.mount.d/zfs-enhancement.conf
if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ] ; then
# If the ZFS sysroot.mount flag exists, the initial RAM disk configured
# it to mount ZFS on root. In that case, we bail early. This flag
# file gets created by the zfs-generator program upon successful run.
info "ZFS: There is a sysroot.mount and zfs-generator has extended it."
info "ZFS: Delegating root mount to sysroot.mount."
# Let us tell the initrd to run on shutdown.
# We have a shutdown hook to run
# because we imported the pool.
if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ]; then
# We're under systemd and dracut-zfs-generator ran to completion.
info "ZFS: Delegating root mount to sysroot.mount at al."
# We now prevent Dracut from running this thing again.
for zfsmounthook in "$hookdir"/mount/*zfs* ; do
if [ -f "$zfsmounthook" ] ; then
rm -f "$zfsmounthook"
fi
done
rm -f "$hookdir"/mount/*zfs*
return
fi
info "ZFS: No sysroot.mount exists or zfs-generator did not extend it."
info "ZFS: Mounting root with the traditional mount-zfs.sh instead."
# ask_for_password tries prompt cmd
#
# Wraps around plymouth ask-for-password and adds fallback to tty password ask
# if plymouth is not present.
ask_for_password() {
tries="$1"
prompt="$2"
cmd="$3"
{
flock -s 9
# Prompt for password with plymouth, if installed and running.
if plymouth --ping 2>/dev/null; then
plymouth ask-for-password \
--prompt "$prompt" --number-of-tries="$tries" | \
eval "$cmd"
ret=$?
else
i=1
while [ "$i" -le "$tries" ]; do
printf "%s [%i/%i]:" "$prompt" "$i" "$tries" >&2
eval "$cmd" && ret=0 && break
ret=$?
i=$((i+1))
printf '\n' >&2
done
unset i
fi
} 9>/.console_lock
[ "$ret" -ne 0 ] && echo "Wrong password" >&2
return "$ret"
}
# Delay until all required block devices are present.
modprobe zfs 2>/dev/null
udevadm settle
ZFS_DATASET=
ZFS_POOL=
if [ "${root}" = "zfs:AUTO" ] ; then
if ! ZFS_DATASET="$(find_bootfs)" ; then
if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then
# shellcheck disable=SC2086
zpool import -N -a ${ZPOOL_IMPORT_OPTS}
if ! ZFS_DATASET="$(find_bootfs)" ; then
if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then
warn "ZFS: No bootfs attribute found in importable pools."
export_all -F
zpool export -aF
rootok=0
return 1
@@ -53,34 +78,43 @@ if [ "${root}" = "zfs:AUTO" ] ; then
info "ZFS: Using ${ZFS_DATASET} as root."
fi
ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}"
ZFS_DATASET="${ZFS_DATASET:-${root}}"
ZFS_POOL="${ZFS_DATASET%%/*}"
if import_pool "${ZFS_POOL}" ; then
# Load keys if we can or if we need to
if [ "$(zpool list -H -o feature@encryption "${ZFS_POOL}")" = 'active' ]; then
# if the root dataset has encryption enabled
ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${ZFS_DATASET}")"
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
KEYSTATUS="$(zfs get -H -o value keystatus "${ENCRYPTIONROOT}")"
# if the key needs to be loaded
if [ "$KEYSTATUS" = "unavailable" ]; then
# decrypt them
ask_for_password \
--tries 5 \
--prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
--cmd "zfs load-key '${ENCRYPTIONROOT}'"
fi
if ! zpool get -Ho name "${ZFS_POOL}" > /dev/null 2>&1; then
info "ZFS: Importing pool ${ZFS_POOL}..."
# shellcheck disable=SC2086
if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${ZFS_POOL}"; then
warn "ZFS: Unable to import pool ${ZFS_POOL}"
rootok=0
return 1
fi
fi
# Load keys if we can or if we need to
# TODO: for_relevant_root_children like in zfs-load-key.sh.in
if [ "$(zpool get -Ho value feature@encryption "${ZFS_POOL}")" = 'active' ]; then
# if the root dataset has encryption enabled
ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${ZFS_DATASET}")"
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
KEYSTATUS="$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")"
# if the key needs to be loaded
if [ "$KEYSTATUS" = "unavailable" ]; then
# decrypt them
ask_for_password \
5 \
"Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
"zfs load-key '${ENCRYPTIONROOT}'"
fi
fi
# Let us tell the initrd to run on shutdown.
# We have a shutdown hook to run
# because we imported the pool.
info "ZFS: Mounting dataset ${ZFS_DATASET}..."
if mount_dataset "${ZFS_DATASET}" ; then
ROOTFS_MOUNTED=yes
return 0
fi
fi
rootok=0
# Let us tell the initrd to run on shutdown.
# We have a shutdown hook to run
# because we imported the pool.
info "ZFS: Mounting dataset ${ZFS_DATASET}..."
if ! mount_dataset "${ZFS_DATASET}"; then
rootok=0
return 1
fi
+17 -45
View File
@@ -1,7 +1,8 @@
#!/bin/sh
# shellcheck disable=SC2034,SC2154
. /lib/dracut-lib.sh
# shellcheck source=zfs-lib.sh.in
. /lib/dracut-zfs-lib.sh
# Let the command line override our host id.
spl_hostid=$(getarg spl_hostid=)
@@ -15,49 +16,20 @@ else
warn "ZFS: Pools may not import correctly."
fi
wait_for_zfs=0
case "${root}" in
""|zfs|zfs:)
# We'll take root unset, root=zfs, or root=zfs:
# No root set, so we want to read the bootfs attribute. We
# can't do that until udev settles so we'll set dummy values
# and hope for the best later on.
root="zfs:AUTO"
rootok=1
wait_for_zfs=1
if decode_root_args; then
if [ "$root" = "zfs:AUTO" ]; then
info "ZFS: Boot dataset autodetected from bootfs=."
else
info "ZFS: Boot dataset is ${root}."
fi
info "ZFS: Enabling autodetection of bootfs after udev settles."
;;
ZFS=*|zfs:*|FILESYSTEM=*)
# root is explicit ZFS root. Parse it now. We can handle
# a root=... param in any of the following formats:
# root=ZFS=rpool/ROOT
# root=zfs:rpool/ROOT
# root=zfs:FILESYSTEM=rpool/ROOT
# root=FILESYSTEM=rpool/ROOT
# root=ZFS=pool+with+space/ROOT+WITH+SPACE (translates to root=ZFS=pool with space/ROOT WITH SPACE)
# Strip down to just the pool/fs
root="${root#zfs:}"
root="${root#FILESYSTEM=}"
root="zfs:${root#ZFS=}"
# switch + with spaces because kernel cmdline does not allow us to quote parameters
root=$(echo "$root" | tr '+' ' ')
rootok=1
wait_for_zfs=1
info "ZFS: Set ${root} as bootfs."
;;
esac
# Make sure Dracut is happy that we have a root and will wait for ZFS
# modules to settle before mounting.
if [ ${wait_for_zfs} -eq 1 ]; then
ln -s /dev/null /dev/root 2>/dev/null
initqueuedir="${hookdir}/initqueue/finished"
test -d "${initqueuedir}" || {
initqueuedir="${hookdir}/initqueue-finished"
}
echo '[ -e /dev/zfs ]' > "${initqueuedir}/zfs.sh"
rootok=1
# Make sure Dracut is happy that we have a root and will wait for ZFS
# modules to settle before mounting.
if [ -n "${wait_for_zfs}" ]; then
ln -s null /dev/root
echo '[ -e /dev/zfs ]' > "${hookdir}/initqueue/finished/zfs.sh"
fi
else
info "ZFS: no ZFS-on-root."
fi
@@ -8,7 +8,7 @@ Before=zfs-import.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')"
ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"
[Install]
WantedBy=zfs-import.target
+5 -25
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# shellcheck disable=SC2016,SC1004
# shellcheck disable=SC2016,SC1004,SC2154
grep -wq debug /proc/cmdline && debug=1
[ -n "$debug" ] && echo "zfs-generator: starting" >> /dev/kmsg
@@ -10,37 +10,17 @@ GENERATOR_DIR="$1"
exit 1
}
[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
command -v getarg >/dev/null 2>&1 || {
[ -n "$debug" ] && echo "zfs-generator: loading Dracut library from $dracutlib" >> /dev/kmsg
. "$dracutlib"
}
# shellcheck source=zfs-lib.sh.in
. /lib/dracut-zfs-lib.sh
decode_root_args || exit 0
[ -z "$root" ] && root=$(getarg root=)
[ -z "$rootfstype" ] && rootfstype=$(getarg rootfstype=)
[ -z "$rootflags" ] && rootflags=$(getarg rootflags=)
# If root is not ZFS= or zfs: or rootfstype is not zfs
# then we are not supposed to handle it.
[ "${root##zfs:}" = "${root}" ] &&
[ "${root##ZFS=}" = "${root}" ] &&
[ "$rootfstype" != "zfs" ] &&
exit 0
[ -z "${rootflags}" ] && rootflags=$(getarg rootflags=)
case ",${rootflags}," in
*,zfsutil,*) ;;
,,) rootflags=zfsutil ;;
*) rootflags="zfsutil,${rootflags}" ;;
esac
if [ "${root}" != "zfs:AUTO" ]; then
root="${root##zfs:}"
root="${root##ZFS=}"
fi
[ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
@@ -89,7 +69,7 @@ else
_zfs_generator_cb() {
dset="${1}"
mpnt="${2}"
unit="sysroot$(echo "$mpnt" | tr '/' '-').mount"
unit="$(systemd-escape --suffix=mount -p "/sysroot${mpnt}")"
{
echo "[Unit]"
+54 -142
View File
@@ -1,74 +1,16 @@
#!/bin/sh
# shellcheck disable=SC2034
command -v getarg >/dev/null || . /lib/dracut-lib.sh
command -v getargbool >/dev/null || {
# Compatibility with older Dracut versions.
# With apologies to the Dracut developers.
getargbool() {
_default="$1"; shift
! _b=$(getarg "$@") && [ -z "$_b" ] && _b="$_default"
if [ -n "$_b" ]; then
[ "$_b" = "0" ] && return 1
[ "$_b" = "no" ] && return 1
[ "$_b" = "off" ] && return 1
fi
return 0
}
}
command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh
OLDIFS="${IFS}"
NEWLINE="
"
TAB=" "
ZPOOL_IMPORT_OPTS=""
if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then
ZPOOL_IMPORT_OPTS=
if getargbool 0 zfs_force -y zfs.force -y zfsforce; then
warn "ZFS: Will force-import pools if necessary."
ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f"
ZPOOL_IMPORT_OPTS=-f
fi
# find_bootfs
# returns the first dataset with the bootfs attribute.
find_bootfs() {
IFS="${NEWLINE}"
for dataset in $(zpool list -H -o bootfs); do
case "${dataset}" in
"" | "-")
continue
;;
"no pools available")
IFS="${OLDIFS}"
return 1
;;
*)
IFS="${OLDIFS}"
echo "${dataset}"
return 0
;;
esac
done
IFS="${OLDIFS}"
return 1
}
# import_pool POOL
# imports the given zfs pool if it isn't imported already.
import_pool() {
pool="${1}"
if ! zpool list -H "${pool}" > /dev/null 2>&1; then
info "ZFS: Importing pool ${pool}..."
# shellcheck disable=SC2086
if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then
warn "ZFS: Unable to import pool ${pool}"
return 1
fi
fi
return 0
}
_mount_dataset_cb() {
mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}"
}
@@ -121,87 +63,57 @@ for_relevant_root_children() {
)
}
# export_all OPTS
# exports all imported zfs pools.
export_all() {
ret=0
IFS="${NEWLINE}"
for pool in $(zpool list -H -o name) ; do
if zpool list -H "${pool}" > /dev/null 2>&1; then
zpool export "${pool}" "$@" || ret=$?
fi
done
IFS="${OLDIFS}"
return ${ret}
}
# ask_for_password
# Parse root=, rootfstype=, return them decoded and normalised to zfs:AUTO for auto, plain dset for explicit
#
# Wraps around plymouth ask-for-password and adds fallback to tty password ask
# if plymouth is not present.
# True if ZFS-on-root, false if we shouldn't
#
# --cmd command
# Command to execute. Required.
# --prompt prompt
# Password prompt. Note that function already adds ':' at the end.
# Recommended.
# --tries n
# How many times repeat command on its failure. Default is 3.
# --ply-[cmd|prompt|tries]
# Command/prompt/tries specific for plymouth password ask only.
# --tty-[cmd|prompt|tries]
# Command/prompt/tries specific for tty password ask only.
# --tty-echo-off
# Turn off input echo before tty command is executed and turn on after.
# It's useful when password is read from stdin.
ask_for_password() {
ply_tries=3
tty_tries=3
while [ "$#" -gt 0 ]; do
case "$1" in
--cmd) ply_cmd="$2"; tty_cmd="$2"; shift;;
--ply-cmd) ply_cmd="$2"; shift;;
--tty-cmd) tty_cmd="$2"; shift;;
--prompt) ply_prompt="$2"; tty_prompt="$2"; shift;;
--ply-prompt) ply_prompt="$2"; shift;;
--tty-prompt) tty_prompt="$2"; shift;;
--tries) ply_tries="$2"; tty_tries="$2"; shift;;
--ply-tries) ply_tries="$2"; shift;;
--tty-tries) tty_tries="$2"; shift;;
--tty-echo-off) tty_echo_off=yes;;
# Supported values:
# root=
# root=zfs
# root=zfs:
# root=zfs:AUTO
#
# root=ZFS=data/set
# root=zfs:data/set
# root=zfs:ZFS=data/set (as a side-effect; allowed but undocumented)
#
# rootfstype=zfs AND root=data/set <=> root=data/set
# rootfstype=zfs AND root= <=> root=zfs:AUTO
#
# '+'es in explicit dataset decoded to ' 's.
decode_root_args() {
if [ -n "$rootfstype" ]; then
[ "$rootfstype" = zfs ]
return
fi
root=$(getarg root=)
rootfstype=$(getarg rootfstype=)
# shellcheck disable=SC2249
case "$root" in
""|zfs|zfs:|zfs:AUTO)
root=zfs:AUTO
rootfstype=zfs
return 0
;;
ZFS=*|zfs:*)
root="${root#zfs:}"
root="${root#ZFS=}"
root=$(echo "$root" | tr '+' ' ')
rootfstype=zfs
return 0
;;
esac
if [ "$rootfstype" = "zfs" ]; then
case "$root" in
"") root=zfs:AUTO ;;
*) root=$(echo "$root" | tr '+' ' ') ;;
esac
shift
done
return 0
fi
{ flock -s 9;
# Prompt for password with plymouth, if installed and running.
if plymouth --ping 2>/dev/null; then
plymouth ask-for-password \
--prompt "$ply_prompt" --number-of-tries="$ply_tries" | \
eval "$ply_cmd"
ret=$?
else
if [ "$tty_echo_off" = yes ]; then
stty_orig="$(stty -g)"
stty -echo
fi
i=1
while [ "$i" -le "$tty_tries" ]; do
[ -n "$tty_prompt" ] && \
printf "%s [%i/%i]:" "$tty_prompt" "$i" "$tty_tries" >&2
eval "$tty_cmd" && ret=0 && break
ret=$?
i=$((i+1))
[ -n "$tty_prompt" ] && printf '\n' >&2
done
unset i
[ "$tty_echo_off" = yes ] && stty "$stty_orig"
fi
} 9>/.console_lock
[ $ret -ne 0 ] && echo "Wrong password" >&2
return $ret
return 1
}
+48 -57
View File
@@ -4,70 +4,61 @@
# only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise
[ -e /bin/systemctl ] || [ -e /usr/bin/systemctl ] || return 0
# This script only gets executed on systemd systems, see mount-zfs.sh for non-systemd systems
# shellcheck source=zfs-lib.sh.in
. /lib/dracut-zfs-lib.sh
# import the libs now that we know the pool imported
[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
# shellcheck source=./lib-zfs.sh.in
. "$dracutlib"
# load the kernel command line vars
[ -z "$root" ] && root="$(getarg root=)"
# If root is not ZFS= or zfs: or rootfstype is not zfs then we are not supposed to handle it.
[ "${root##zfs:}" = "${root}" ] && [ "${root##ZFS=}" = "${root}" ] && [ "$rootfstype" != "zfs" ] && exit 0
decode_root_args || return 0
# There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported
while [ "$(zpool list -H)" = "" ]; do
systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && exit 1
while ! systemctl is-active --quiet zfs-import.target; do
systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && return 1
sleep 0.1s
done
# run this after import as zfs-import-cache/scan service is confirmed good
# we do not overwrite the ${root} variable, but create a new one, BOOTFS, to hold the dataset
if [ "${root}" = "zfs:AUTO" ] ; then
BOOTFS="$(zpool list -H -o bootfs | awk '$1 != "-" {print; exit}')"
else
BOOTFS="${root##zfs:}"
BOOTFS="${BOOTFS##ZFS=}"
BOOTFS="$root"
if [ "$BOOTFS" = "zfs:AUTO" ]; then
BOOTFS="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"
fi
# if pool encryption is active and the zfs command understands '-o encryption'
if [ "$(zpool list -H -o feature@encryption "${BOOTFS%%/*}")" = 'active' ]; then
# if the root dataset has encryption enabled
ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${BOOTFS}")"
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
KEYSTATUS="$(zfs get -H -o value keystatus "${ENCRYPTIONROOT}")"
# continue only if the key needs to be loaded
[ "$KEYSTATUS" = "unavailable" ] || exit 0
[ "$(zpool get -Ho value feature@encryption "${BOOTFS%%/*}")" = 'active' ] || return 0
KEYLOCATION="$(zfs get -H -o value keylocation "${ENCRYPTIONROOT}")"
case "${KEYLOCATION%%://*}" in
prompt)
for _ in 1 2 3; do
systemd-ask-password --no-tty "Encrypted ZFS password for ${BOOTFS}" | zfs load-key "${ENCRYPTIONROOT}" && break
_load_key_cb() {
dataset="$1"
ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${dataset}")"
[ "${ENCRYPTIONROOT}" = "-" ] && return 0
[ "$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" = "unavailable" ] || return 0
KEYLOCATION="$(zfs get -Ho value keylocation "${ENCRYPTIONROOT}")"
case "${KEYLOCATION%%://*}" in
prompt)
for _ in 1 2 3; do
systemd-ask-password --no-tty "Encrypted ZFS password for ${dataset}" | zfs load-key "${ENCRYPTIONROOT}" && break
done
;;
http*)
systemctl start network-online.target
zfs load-key "${ENCRYPTIONROOT}"
;;
file)
KEYFILE="${KEYLOCATION#file://}"
[ -r "${KEYFILE}" ] || udevadm settle
[ -r "${KEYFILE}" ] || {
info "ZFS: Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..."
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
sleep 0.5s
[ -r "${KEYFILE}" ] && break
done
;;
http*)
systemctl start network-online.target
zfs load-key "${ENCRYPTIONROOT}"
;;
file)
KEYFILE="${KEYLOCATION#file://}"
[ -r "${KEYFILE}" ] || udevadm settle
[ -r "${KEYFILE}" ] || {
info "Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..."
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
sleep 0.5s
[ -r "${KEYFILE}" ] && break
done
}
[ -r "${KEYFILE}" ] || warn "Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway."
zfs load-key "${ENCRYPTIONROOT}"
;;
*)
zfs load-key "${ENCRYPTIONROOT}"
;;
esac
fi
fi
}
[ -r "${KEYFILE}" ] || warn "ZFS: Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway."
zfs load-key "${ENCRYPTIONROOT}"
;;
*)
zfs load-key "${ENCRYPTIONROOT}"
;;
esac
}
_load_key_cb "$BOOTFS"
for_relevant_root_children "$BOOTFS" _load_key_cb
+1 -1
View File
@@ -2,7 +2,7 @@
command -v getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
if zpool list 2>&1 | grep -q 'no pools available' ; then
if [ -z "$(zpool get -Ho value name)" ]; then
info "ZFS: No active pools, no need to export anything."
else
info "ZFS: There is an active pool, will export it."
@@ -1,14 +1,12 @@
[Unit]
Description=Rollback bootfs just before it is mounted
Requisite=zfs-import.target
After=zfs-import.target zfs-snapshot-bootfs.service
After=zfs-import.target dracut-pre-mount.service zfs-snapshot-bootfs.service
Before=dracut-mount.service
DefaultDependencies=no
ConditionKernelCommandLine=bootfs.rollback
[Service]
# ${BOOTFS} should have been set by zfs-env-bootfs.service
Type=oneshot
ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"'
ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"'
RemainAfterExit=yes
@@ -1,14 +1,12 @@
[Unit]
Description=Snapshot bootfs just before it is mounted
Requisite=zfs-import.target
After=zfs-import.target
After=zfs-import.target dracut-pre-mount.service
Before=dracut-mount.service
DefaultDependencies=no
ConditionKernelCommandLine=bootfs.snapshot
[Service]
# ${BOOTFS} should have been set by zfs-env-bootfs.service
Type=oneshot
ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"'
ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"'
RemainAfterExit=yes
+38 -213
View File
@@ -1,225 +1,50 @@
How to setup a zfs root filesystem using dracut
-----------------------------------------------
## Basic setup
1. Install `zfs-dracut`
2. Set `mountpoint=/` for your root dataset (for compatibility, `legacy` also works, but is not recommended for new installations):
```sh
zfs set mountpoint=/ pool/dataset
```
3. Either (a) set `bootfs=` on the pool to the dataset:
```sh
zpool set bootfs=pool/dataset pool
```
4. Or (b) append `root=zfs:pool/dataset` to your kernel cmdline.
5. Re-generate your initrd and update it in your boot bundle
1) Install the zfs-dracut package. This package adds a zfs dracut module
to the /usr/share/dracut/modules.d/ directory which allows dracut to
create an initramfs which is zfs aware.
Encrypted datasets have keys loaded automatically or prompted for.
2) Set the bootfs property for the bootable dataset in the pool. Then set
the dataset mountpoint property to '/'.
If the root dataset contains children with `mountpoint=`s of `/etc`, `/bin`, `/lib*`, or `/usr`, they're mounted too.
$ zpool set bootfs=pool/dataset pool
$ zfs set mountpoint=/ pool/dataset
For complete documentation, see `dracut.zfs(7)`.
Alternately, legacy mountpoints can be used by setting the 'root=' option
on the kernel line of your grub.conf/menu.lst configuration file. Then
set the dataset mountpoint property to 'legacy'.
## cmdline
1. `root=` | Root dataset is… |
---------------------------|----------------------------------------------------------|
*(empty)* | the first `bootfs=` after `zpool import -aN` |
`zfs:AUTO`, `zfs:`, `zfs` | *(as above, but overriding other autoselection methods)* |
`ZFS=pool/dataset` | `pool/dataset` |
`zfs:pool/dataset` | *(as above)* |
$ grub.conf/menu.lst: kernel ... root=ZFS=pool/dataset
$ zfs set mountpoint=legacy pool/dataset
All `+`es are replaced with spaces (i.e. to boot from `root pool/data set`, pass `root=zfs:root+pool/data+set`).
3) To set zfs module options put them in /etc/modprobe.d/zfs.conf file.
The complete list of zfs module options is available by running the
_modinfo zfs_ command. Commonly set options include: zfs_arc_min,
zfs_arc_max, zfs_prefetch_disable, and zfs_vdev_max_pending.
The dataset can be at any depth, including being the pool's root dataset (i.e. `root=zfs:pool`).
4) Finally, create your new initramfs by running dracut.
`rootfstype=zfs` is equivalent to `root=zfs:AUTO`, `rootfstype=zfs root=pool/dataset` is equivalent to `root=zfs:pool/dataset`.
$ dracut --force /path/to/initramfs kernel_version
2. `spl_hostid`: passed to `zgenhostid -f`, useful to override the `/etc/hostid` file baked into the initrd.
Kernel Command Line
-------------------
3. `bootfs.snapshot`, `bootfs.snapshot=snapshot-name`: enables `zfs-snapshot-bootfs.service`,
which creates a snapshot `$root_dataset@$(uname -r)` (or, in the second form, `$root_dataset@snapshot-name`)
after pool import but before the rootfs is mounted.
Failure to create the snapshot is noted, but booting continues.
The initramfs' behavior is influenced by the following kernel command line
parameters passed in from the boot loader:
4. `bootfs.rollback`, `bootfs.rollback=snapshot-name`: enables `zfs-snapshot-bootfs.service`,
which `-Rf` rolls back to `$root_dataset@$(uname -r)` (or, in the second form, `$root_dataset@snapshot-name`)
after pool import but before the rootfs is mounted.
Failure to roll back will fall down to the rescue shell.
This has obvious potential for data loss: make sure your persistent data is not below the rootfs and you don't care about any intermediate snapshots.
* `root=...`: If not set, importable pools are searched for a bootfs
attribute. If an explicitly set root is desired, you may use
`root=ZFS:pool/dataset`
5. If both `bootfs.snapshot` and `bootfs.rollback` are set, `bootfs.rollback` is ordered *after* `bootfs.snapshot`.
* `zfs_force=0`: If set to 1, the initramfs will run `zpool import -f` when
attempting to import pools if the required pool isn't automatically imported
by the zfs module. This can save you a trip to a bootcd if hostid has
changed, but is dangerous and can lead to zpool corruption, particularly in
cases where storage is on a shared fabric such as iSCSI where multiple hosts
can access storage devices concurrently. _Please understand the implications
of force-importing a pool before enabling this option!_
* `spl_hostid`: By default, the hostid used by the SPL module is read from
/etc/hostid inside the initramfs. This file is placed there from the host
system when the initramfs is built which effectively ties the ramdisk to the
host which builds it. If a different hostid is desired, one may be set in
this attribute and will override any file present in the ramdisk. The
format should be hex exactly as found in the `/etc/hostid` file, IE
`spl_hostid=0x00bab10c`.
Note that changing the hostid between boots will most likely lead to an
un-importable pool since the last importing hostid won't match. In order
to recover from this, you may use the `zfs_force` option or boot from a
different filesystem and `zpool import -f` then `zpool export` the pool
before rebooting with the new hostid.
* `bootfs.snapshot`: If listed, enables the zfs-snapshot-bootfs service on a Dracut system. The zfs-snapshot-bootfs service simply runs `zfs snapshot $BOOTFS@%v` after the pool has been imported but before the bootfs is mounted. `$BOOTFS` is substituted with the value of the bootfs setting on the pool. `%v` is substituted with the version string of the kernel currently being booted (e.g. 5.6.6-200.fc31.x86\_64). Failure to create the snapshot (e.g. because one with the same name already exists) will be logged, but will not otherwise interrupt the boot process.
It is safe to leave the bootfs.snapshot flag set persistently on your kernel command line so that a new snapshot of your bootfs will be created on every kernel update. If you leave bootfs.snapshot set persistently on your kernel command line, you may find the below script helpful for automatically removing old snapshots of the bootfs along with their associated kernel.
#!/usr/bin/sh
if [[ "$1" == "remove" ]] && grep -q "\bbootfs.snapshot\b" /proc/cmdline; then
zfs destroy $(findmnt -n -o source /)@$2 &> /dev/null
fi
exit 0
To use the above script place it in a plain text file named /etc/kernel/install.d/99-zfs-cleanup.install and mark it executable with the following command:
$ chmod +x /etc/kernel/install.d/99-zfs-cleanup.install
On Red Hat based systems, you can change the value of `installonly_limit` in /etc/dnf/dnf.conf to adjust the number of kernels and their associated snapshots that are kept.
* `bootfs.snapshot=<snapname>`: Is identical to the bootfs.snapshot parameter explained above except that the value substituted for \<snapname\> will be used when creating the snapshot instead of the version string of the kernel currently being booted.
* `bootfs.rollback`: If listed, enables the zfs-rollback-bootfs service on a Dracut system. The zfs-rollback-bootfs service simply runs `zfs rollback -Rf $BOOTFS@%v` after the pool has been imported but before the bootfs is mounted. If the rollback operation fails, the boot process will be interrupted with a Dracut rescue shell. __Use this parameter with caution. Intermediate snapshots of the bootfs will be destroyed!__ TIP: Keep your user data (e.g. /home) on separate file systems (it can be in the same pool though).
* `bootfs.rollback=<snapname>`: Is identical to the bootfs.rollback parameter explained above except that the value substituted for \<snapname\> will be used when rolling back the bootfs instead of the version string of the kernel currently being booted. If you use this form, choose a snapshot that is new enough to contain the needed kernel modules under /lib/modules or use a kernel that has all the needed modules built-in.
How it Works
============
The Dracut module consists of the following files (less Makefile's):
* `module-setup.sh`: Script run by the initramfs builder to create the
ramdisk. Contains instructions on which files are required by the modules
and z* programs. Also triggers inclusion of `/etc/hostid` and the zpool
cache. This file is not included in the initramfs.
* `90-zfs.rules`: udev rules which trigger loading of the ZFS modules at boot.
* `zfs-lib.sh`: Utility functions used by the other files.
* `parse-zfs.sh`: Run early in the initramfs boot process to parse kernel
command line and determine if ZFS is the active root filesystem.
* `mount-zfs.sh`: Run later in initramfs boot process after udev has settled
to mount the root dataset.
* `export-zfs.sh`: Run on shutdown after dracut has restored the initramfs
and pivoted to it, allowing for a clean unmount and export of the ZFS root.
`zfs-lib.sh`
------------
This file provides a few handy functions for working with ZFS. Those
functions are used by the `mount-zfs.sh` and `export-zfs.sh` files.
However, they could be used by any other file as well, as long as the file
sources `/lib/dracut-zfs-lib.sh`.
`module-setup.sh`
-----------------
This file is run by the Dracut script within the live system, not at boot
time. It's not included in the final initramfs. Functions in this script
describe which files are needed by ZFS at boot time.
Currently all the various z* and spl modules are included, a dependency is
asserted on udev-rules, and the various zfs, zpool, etc. helpers are included.
Dracut provides library functions which automatically gather the shared libs
necessary to run each of these binaries, so statically built binaries are
not required.
The zpool and zvol udev rules files are copied from where they are
installed by the ZFS build. __PACKAGERS TAKE NOTE__: If you move
`/etc/udev/rules/60-z*.rules`, you'll need to update this file to match.
Currently this file also includes `/etc/hostid` and `/etc/zfs/zpool.cache`
which means the generated ramdisk is specific to the host system which built
it. If a generic initramfs is required, it may be preferable to omit these
files and specify the `spl_hostid` from the boot loader instead.
`parse-zfs.sh`
--------------
Run during the cmdline phase of the initramfs boot process, this script
performs some basic sanity checks on kernel command line parameters to
determine if booting from ZFS is likely to be what is desired. Dracut
requires this script to adjust the `root` variable if required and to set
`rootok=1` if a mountable root filesystem is available. Unfortunately this
script must run before udev is settled and kernel modules are known to be
loaded, so accessing the zpool and zfs commands is unsafe.
If the root=ZFS... parameter is set on the command line, then it's at least
certain that ZFS is what is desired, though this script is unable to
determine if ZFS is in fact available. This script will alter the `root`
parameter to replace several historical forms of specifying the pool and
dataset name with the canonical form of `zfs:pool/dataset`.
If no root= parameter is set, the best this script can do is guess that
ZFS is desired. At present, no other known filesystems will work with no
root= parameter, though this might possibly interfere with using the
compiled-in default root in the kernel image. It's considered unlikely
that would ever be the case when an initramfs is in use, so this script
sets `root=zfs:AUTO` and hopes for the best.
Once the root=... (or lack thereof) parameter is parsed, a dummy symlink
is created from `/dev/root` -> `/dev/null` to satisfy parts of the Dracut
process which check for presence of a single root device node.
Finally, an initqueue/finished hook is registered which causes the initqueue
phase of Dracut to wait for `/dev/zfs` to become available before attempting
to mount anything.
`mount-zfs.sh`
--------------
This script is run after udev has settled and all tasks in the initqueue
have succeeded. This ensures that `/dev/zfs` is available and that the
various ZFS modules are successfully loaded. As it is now safe to call
zpool and friends, we can proceed to find the bootfs attribute if necessary.
If the root parameter was explicitly set on the command line, no parsing is
necessary. The list of imported pools is checked to see if the desired pool
is already imported. If it's not, and attempt is made to import the pool
explicitly, though no force is attempted. Finally the specified dataset
is mounted on `$NEWROOT`, first using the `-o zfsutil` option to handle
non-legacy mounts, then if that fails, without zfsutil to handle legacy
mount points.
If no root parameter was specified, this script attempts to find a pool with
its bootfs attribute set. First, already-imported pools are scanned and if
an appropriate pool is found, no additional pools are imported. If no pool
with bootfs is found, any additional pools in the system are imported with
`zpool import -N -a`, and the scan for bootfs is tried again. If no bootfs
is found with all pools imported, all pools are re-exported, and boot fails.
Assuming a bootfs is found, an attempt is made to mount it to `$NEWROOT`,
first with, then without the zfsutil option as above.
Ordinarily pools are imported _without_ the force option which may cause
boot to fail if the hostid has changed or a pool has been physically moved
between servers. The `zfs_force` kernel parameter is provided which when
set to `1` causes `zpool import` to be run with the `-f` flag. Forcing pool
import can lead to serious data corruption and loss of pools, so this option
should be used with extreme caution. Note that even with this flag set, if
the required zpool was auto-imported by the kernel module, no additional
`zpool import` commands are run, so nothing is forced.
`export-zfs.sh`
---------------
Normally the zpool containing the root dataset cannot be exported on
shutdown as it is still in use by the init process. To work around this,
Dracut is able to restore the initramfs on shutdown and pivot to it.
All remaining process are then running from a ramdisk, allowing for a
clean unmount and export of the ZFS root. The theory of operation is
described in detail in the [Dracut manual](https://www.kernel.org/pub/linux/utils/boot/dracut/dracut.html#_dracut_on_shutdown).
This script will try to export all remaining zpools after Dracut has
pivoted to the initramfs. If an initial regular export is not successful,
Dracut will call this script once more with the `final` option,
in which case a forceful export is attempted.
Other Dracut modules include similar shutdown scripts and Dracut
invokes these scripts round-robin until they succeed. In particular,
the `90dm` module installs a script which tries to close and remove
all device mapper targets. Thus, if there are ZVOLs containing
dm-crypt volumes or if the zpool itself is backed by a dm-crypt
volume, the shutdown scripts will try to untangle this.
6. `zfs_force`, `zfs.force`, `zfsforce`: add `-f` to all `zpool import` invocations.
May be useful. Use with caution.
+3 -2
View File
@@ -1,9 +1,10 @@
include $(top_srcdir)/config/Substfiles.am
include $(top_srcdir)/config/Shellcheck.am
initconf_SCRIPTS = zfs
initconf_DATA = zfs
SUBSTFILES += $(initconf_SCRIPTS)
SUBSTFILES += $(initconf_DATA)
SHELLCHECKSCRIPTS = $(initconf_DATA)
SHELLCHECK_SHELL = sh
SHELLCHECK_IGNORE = ,SC2034
@@ -27,9 +27,6 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
@@ -44,25 +41,16 @@
#include <errno.h>
#include <libzfs.h>
/*
* For debugging only.
*
* Free statics with trivial life-times,
* but saved line filenames are replaced with a static string.
*/
#define FREE_STATICS false
#define nitems(arr) (sizeof (arr) / sizeof (*arr))
#define STRCMP ((int(*)(const void *, const void *))&strcmp)
#define PID_T_CMP ((int(*)(const void *, const void *))&pid_t_cmp)
static int
pid_t_cmp(const pid_t *lhs, const pid_t *rhs)
{
/*
* This is always valid, quoth sys_types.h(7posix):
* > blksize_t, pid_t, and ssize_t shall be signed integer types.
*/
return (*lhs - *rhs);
}
#define EXIT_ENOMEM() \
do { \
fprintf(stderr, PROGNAME "[%d]: " \
"not enough memory (L%d)!\n", getpid(), __LINE__); \
_exit(1); \
} while (0)
#define PROGNAME "zfs-mount-generator"
@@ -80,20 +68,11 @@ pid_t_cmp(const pid_t *lhs, const pid_t *rhs)
#define URI_REGEX_S "^\\([A-Za-z][A-Za-z0-9+.\\-]*\\):\\/\\/\\(.*\\)$"
static regex_t uri_regex;
static char *argv0;
static const char *destdir = "/tmp";
static int destdir_fd = -1;
static void *known_pools = NULL; /* tsearch() of C strings */
static struct {
sem_t noauto_not_on_sem;
sem_t noauto_names_sem;
size_t noauto_names_len;
size_t noauto_names_max;
char noauto_names[][NAME_MAX];
} *noauto_files;
static void *noauto_files = NULL; /* tsearch() of C strings */
static char *
@@ -103,8 +82,12 @@ systemd_escape(const char *input, const char *prepend, const char *append)
size_t applen = strlen(append);
size_t prelen = strlen(prepend);
char *ret = malloc(4 * len + prelen + applen + 1);
if (!ret)
EXIT_ENOMEM();
if (!ret) {
fprintf(stderr, PROGNAME "[%d]: "
"out of memory to escape \"%s%s%s\"!\n",
getpid(), prepend, input, append);
return (NULL);
}
memcpy(ret, prepend, prelen);
char *out = ret + prelen;
@@ -166,8 +149,12 @@ systemd_escape_path(char *input, const char *prepend, const char *append)
{
if (strcmp(input, "/") == 0) {
char *ret;
if (asprintf(&ret, "%s-%s", prepend, append) == -1)
EXIT_ENOMEM();
if (asprintf(&ret, "%s-%s", prepend, append) == -1) {
fprintf(stderr, PROGNAME "[%d]: "
"out of memory to escape \"%s%s%s\"!\n",
getpid(), prepend, input, append);
ret = NULL;
}
return (ret);
} else {
/*
@@ -209,6 +196,10 @@ fopenat(int dirfd, const char *pathname, int flags,
static int
line_worker(char *line, const char *cachefile)
{
int ret = 0;
void *tofree_all[8];
void **tofree = tofree_all;
char *toktmp;
/* BEGIN CSTYLED */
const char *dataset = strtok_r(line, "\t", &toktmp);
@@ -240,11 +231,9 @@ line_worker(char *line, const char *cachefile)
if (p_nbmand == NULL) {
fprintf(stderr, PROGNAME "[%d]: %s: not enough tokens!\n",
getpid(), dataset);
return (1);
goto err;
}
strncpy(argv0, dataset, strlen(argv0));
/* Minimal pre-requisites to mount a ZFS dataset */
const char *after = "zfs-import.target";
const char *wants = "zfs-import.target";
@@ -280,28 +269,31 @@ line_worker(char *line, const char *cachefile)
if (strcmp(p_encroot, "-") != 0) {
char *keyloadunit =
char *keyloadunit = *(tofree++) =
systemd_escape(p_encroot, "zfs-load-key@", ".service");
if (keyloadunit == NULL)
goto err;
if (strcmp(dataset, p_encroot) == 0) {
const char *keymountdep = NULL;
bool is_prompt = false;
bool need_network = false;
regmatch_t uri_matches[3];
if (regexec(&uri_regex, p_keyloc,
sizeof (uri_matches) / sizeof (*uri_matches),
uri_matches, 0) == 0) {
nitems(uri_matches), uri_matches, 0) == 0) {
p_keyloc[uri_matches[1].rm_eo] = '\0';
p_keyloc[uri_matches[2].rm_eo] = '\0';
const char *scheme =
&p_keyloc[uri_matches[1].rm_so];
const char *path =
&p_keyloc[uri_matches[2].rm_so];
/*
* Assumes all URI keylocations need
* the mount for their path;
* http://, for example, wouldn't
* (but it'd need network-online.target et al.)
*/
keymountdep = path;
if (strcmp(scheme, "https") == 0 ||
strcmp(scheme, "http") == 0)
need_network = true;
else
keymountdep = path;
} else {
if (strcmp(p_keyloc, "prompt") != 0)
fprintf(stderr, PROGNAME "[%d]: %s: "
@@ -321,7 +313,7 @@ line_worker(char *line, const char *cachefile)
"couldn't open %s under %s: %s\n",
getpid(), dataset, keyloadunit, destdir,
strerror(errno));
return (1);
goto err;
}
fprintf(keyloadunit_f,
@@ -335,20 +327,22 @@ line_worker(char *line, const char *cachefile)
"After=%s\n",
dataset, cachefile, wants, after);
if (need_network)
fprintf(keyloadunit_f,
"Wants=network-online.target\n"
"After=network-online.target\n");
if (p_systemd_requires)
fprintf(keyloadunit_f,
"Requires=%s\n", p_systemd_requires);
if (p_systemd_requiresmountsfor || keymountdep) {
fprintf(keyloadunit_f, "RequiresMountsFor=");
if (p_systemd_requiresmountsfor)
fprintf(keyloadunit_f,
"%s ", p_systemd_requiresmountsfor);
if (keymountdep)
fprintf(keyloadunit_f,
"'%s'", keymountdep);
fprintf(keyloadunit_f, "\n");
}
if (p_systemd_requiresmountsfor)
fprintf(keyloadunit_f,
"RequiresMountsFor=%s\n",
p_systemd_requiresmountsfor);
if (keymountdep)
fprintf(keyloadunit_f,
"RequiresMountsFor='%s'\n", keymountdep);
/* BEGIN CSTYLED */
fprintf(keyloadunit_f,
@@ -393,9 +387,13 @@ line_worker(char *line, const char *cachefile)
if (after[0] == '\0')
after = keyloadunit;
else if (asprintf(&toktmp, "%s %s", after, keyloadunit) != -1)
after = toktmp;
else
EXIT_ENOMEM();
after = *(tofree++) = toktmp;
else {
fprintf(stderr, PROGNAME "[%d]: %s: "
"out of memory to generate after=\"%s %s\"!\n",
getpid(), dataset, after, keyloadunit);
goto err;
}
}
@@ -404,12 +402,12 @@ line_worker(char *line, const char *cachefile)
strcmp(p_systemd_ignore, "off") == 0) {
/* ok */
} else if (strcmp(p_systemd_ignore, "on") == 0)
return (0);
goto end;
else {
fprintf(stderr, PROGNAME "[%d]: %s: "
"invalid org.openzfs.systemd:ignore=%s\n",
getpid(), dataset, p_systemd_ignore);
return (1);
goto err;
}
/* Check for canmount */
@@ -418,21 +416,21 @@ line_worker(char *line, const char *cachefile)
} else if (strcmp(p_canmount, "noauto") == 0)
noauto = true;
else if (strcmp(p_canmount, "off") == 0)
return (0);
goto end;
else {
fprintf(stderr, PROGNAME "[%d]: %s: invalid canmount=%s\n",
getpid(), dataset, p_canmount);
return (1);
goto err;
}
/* Check for legacy and blank mountpoints */
if (strcmp(p_mountpoint, "legacy") == 0 ||
strcmp(p_mountpoint, "none") == 0)
return (0);
goto end;
else if (p_mountpoint[0] != '/') {
fprintf(stderr, PROGNAME "[%d]: %s: invalid mountpoint=%s\n",
getpid(), dataset, p_mountpoint);
return (1);
goto err;
}
/* Escape the mountpoint per systemd policy */
@@ -442,7 +440,7 @@ line_worker(char *line, const char *cachefile)
fprintf(stderr,
PROGNAME "[%d]: %s: abnormal simplified mountpoint: %s\n",
getpid(), dataset, p_mountpoint);
return (1);
goto err;
}
@@ -552,8 +550,7 @@ line_worker(char *line, const char *cachefile)
* files if we're sure they were created by us. (see 5.)
* 2. We handle files differently based on canmount.
* Units with canmount=on always have precedence over noauto.
* This is enforced by the noauto_not_on_sem semaphore,
* which is only unlocked when the last canmount=on process exits.
* This is enforced by processing these units before all others.
* It is important to use p_canmount and not noauto here,
* since we categorise by canmount while other properties,
* e.g. org.openzfs.systemd:wanted-by, also modify noauto.
@@ -561,7 +558,7 @@ line_worker(char *line, const char *cachefile)
* Additionally, we use noauto_files to track the unit file names
* (which are the systemd-escaped mountpoints) of all (exclusively)
* noauto datasets that had a file created.
* 4. If the file to be created is found in the tracking array,
* 4. If the file to be created is found in the tracking tree,
* we do NOT create it.
* 5. If a file exists for a noauto dataset,
* we check whether the file name is in the array.
@@ -571,29 +568,14 @@ line_worker(char *line, const char *cachefile)
* further noauto datasets creating a file for this path again.
*/
{
sem_t *our_sem = (strcmp(p_canmount, "on") == 0) ?
&noauto_files->noauto_names_sem :
&noauto_files->noauto_not_on_sem;
while (sem_wait(our_sem) == -1 && errno == EINTR)
;
}
struct stat stbuf;
bool already_exists = fstatat(destdir_fd, mountfile, &stbuf, 0) == 0;
bool is_known = tfind(mountfile, &noauto_files, STRCMP) != NULL;
bool is_known = false;
for (size_t i = 0; i < noauto_files->noauto_names_len; ++i) {
if (strncmp(
noauto_files->noauto_names[i], mountfile, NAME_MAX) == 0) {
is_known = true;
break;
}
}
*(tofree++) = (void *)mountfile;
if (already_exists) {
if (is_known) {
/* If it's in $noauto_files, we must be noauto too */
/* If it's in noauto_files, we must be noauto too */
/* See 5 */
errno = 0;
@@ -614,43 +596,31 @@ line_worker(char *line, const char *cachefile)
}
/* File exists: skip current dataset */
if (strcmp(p_canmount, "on") == 0)
sem_post(&noauto_files->noauto_names_sem);
return (0);
goto end;
} else {
if (is_known) {
/* See 4 */
if (strcmp(p_canmount, "on") == 0)
sem_post(&noauto_files->noauto_names_sem);
return (0);
goto end;
} else if (strcmp(p_canmount, "noauto") == 0) {
if (noauto_files->noauto_names_len ==
noauto_files->noauto_names_max)
if (tsearch(mountfile, &noauto_files, STRCMP) == NULL)
fprintf(stderr, PROGNAME "[%d]: %s: "
"noauto dataset limit (%zu) reached! "
"Not tracking %s. Please report this to "
"https://github.com/openzfs/zfs\n",
getpid(), dataset,
noauto_files->noauto_names_max, mountfile);
else {
strncpy(noauto_files->noauto_names[
noauto_files->noauto_names_len],
mountfile, NAME_MAX);
++noauto_files->noauto_names_len;
}
"out of memory for noauto datasets! "
"Not tracking %s.\n",
getpid(), dataset, mountfile);
else
/* mountfile escaped to noauto_files */
*(--tofree) = NULL;
}
}
FILE *mountfile_f = fopenat(destdir_fd, mountfile,
O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, "w", 0644);
if (strcmp(p_canmount, "on") == 0)
sem_post(&noauto_files->noauto_names_sem);
if (!mountfile_f) {
fprintf(stderr,
PROGNAME "[%d]: %s: couldn't open %s under %s: %s\n",
getpid(), dataset, mountfile, destdir, strerror(errno));
return (1);
goto err;
}
fprintf(mountfile_f,
@@ -699,12 +669,17 @@ line_worker(char *line, const char *cachefile)
(void) fclose(mountfile_f);
if (!requiredby && !wantedby)
return (0);
goto end;
/* Finally, create the appropriate dependencies */
char *linktgt;
if (asprintf(&linktgt, "../%s", mountfile) == -1)
EXIT_ENOMEM();
if (asprintf(&linktgt, "../%s", mountfile) == -1) {
fprintf(stderr, PROGNAME "[%d]: %s: "
"out of memory for dependents of %s!\n",
getpid(), dataset, mountfile);
goto err;
}
*(tofree++) = linktgt;
char *dependencies[][2] = {
{"wants", wantedby},
@@ -719,8 +694,14 @@ line_worker(char *line, const char *cachefile)
reqby;
reqby = strtok_r(NULL, " ", &toktmp)) {
char *depdir;
if (asprintf(&depdir, "%s.%s", reqby, (*dep)[0]) == -1)
EXIT_ENOMEM();
if (asprintf(
&depdir, "%s.%s", reqby, (*dep)[0]) == -1) {
fprintf(stderr, PROGNAME "[%d]: %s: "
"out of memory for dependent dir name "
"\"%s.%s\"!\n",
getpid(), dataset, reqby, (*dep)[0]);
continue;
}
(void) mkdirat(destdir_fd, depdir, 0755);
int depdir_fd = openat(destdir_fd, depdir,
@@ -746,7 +727,24 @@ line_worker(char *line, const char *cachefile)
}
}
return (0);
end:
if (tofree >= tofree_all + nitems(tofree_all)) {
/*
* This won't happen as-is:
* we've got 8 slots and allocate 4 things at most.
*/
fprintf(stderr,
PROGNAME "[%d]: %s: need to free %zu > %zu!\n",
getpid(), dataset, tofree - tofree_all, nitems(tofree_all));
ret = tofree - tofree_all;
}
while (tofree-- != tofree_all)
free(*tofree);
return (ret);
err:
ret = 1;
goto end;
}
@@ -780,12 +778,11 @@ main(int argc, char **argv)
if (kmfd >= 0) {
(void) dup2(kmfd, STDERR_FILENO);
(void) close(kmfd);
setlinebuf(stderr);
}
}
uint8_t debug = 0;
argv0 = argv[0];
switch (argc) {
case 1:
/* Use default */
@@ -844,33 +841,9 @@ main(int argc, char **argv)
}
}
{
/*
* We could just get a gigabyte here and Not Care,
* but if vm.overcommit_memory=2, then MAP_NORESERVE is ignored
* and we'd try (and likely fail) to rip it out of swap
*/
noauto_files = mmap(NULL, 4 * 1024 * 1024,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
if (noauto_files == MAP_FAILED) {
fprintf(stderr,
PROGNAME "[%d]: couldn't allocate IPC region: %s\n",
getpid(), strerror(errno));
_exit(1);
}
sem_init(&noauto_files->noauto_not_on_sem, true, 0);
sem_init(&noauto_files->noauto_names_sem, true, 1);
noauto_files->noauto_names_len = 0;
/* Works out to 16447ish, *well* enough */
noauto_files->noauto_names_max =
(4 * 1024 * 1024 - sizeof (*noauto_files)) / NAME_MAX;
}
bool debug = false;
char *line = NULL;
size_t linelen = 0;
struct timespec time_start = {};
{
const char *dbgenv = getenv("ZFS_DEBUG");
if (dbgenv)
@@ -879,7 +852,7 @@ main(int argc, char **argv)
FILE *cmdline = fopen("/proc/cmdline", "re");
if (cmdline != NULL) {
if (getline(&line, &linelen, cmdline) >= 0)
debug = strstr(line, "debug") ? 2 : 0;
debug = strstr(line, "debug");
(void) fclose(cmdline);
}
}
@@ -888,19 +861,17 @@ main(int argc, char **argv)
dup2(STDERR_FILENO, STDOUT_FILENO);
}
size_t forked_canmount_on = 0;
size_t forked_canmount_not_on = 0;
size_t canmount_on_pids_len = 128;
pid_t *canmount_on_pids =
malloc(canmount_on_pids_len * sizeof (*canmount_on_pids));
if (canmount_on_pids == NULL)
canmount_on_pids_len = 0;
struct timespec time_start = {};
if (debug)
clock_gettime(CLOCK_MONOTONIC_RAW, &time_start);
ssize_t read;
pid_t pid;
struct line {
char *line;
const char *fname;
struct line *next;
} *lines_canmount_not_on = NULL;
int ret = 0;
struct dirent *cachent;
while ((cachent = readdir(fslist_dir)) != NULL) {
if (strcmp(cachent->d_name, ".") == 0 ||
@@ -916,129 +887,67 @@ main(int argc, char **argv)
continue;
}
const char *filename = FREE_STATICS ? "(elided)" : NULL;
ssize_t read;
while ((read = getline(&line, &linelen, cachefile)) >= 0) {
line[read - 1] = '\0'; /* newline */
switch (pid = fork()) {
case -1:
fprintf(stderr,
PROGNAME "[%d]: couldn't fork for %s: %s\n",
getpid(), line, strerror(errno));
break;
case 0: /* child */
_exit(line_worker(line, cachent->d_name));
default: { /* parent */
char *tmp;
char *dset = strtok_r(line, "\t", &tmp);
strtok_r(NULL, "\t", &tmp);
char *canmount = strtok_r(NULL, "\t", &tmp);
bool canmount_on =
canmount && strncmp(canmount, "on", 2) == 0;
char *canmount = line;
canmount += strcspn(canmount, "\t");
canmount += strspn(canmount, "\t");
canmount += strcspn(canmount, "\t");
canmount += strspn(canmount, "\t");
bool canmount_on = strncmp(canmount, "on", 2) == 0;
if (debug >= 2)
printf(PROGNAME ": forked %d, "
"canmount_on=%d, dataset=%s\n",
(int)pid, canmount_on, dset);
if (canmount_on)
ret |= line_worker(line, cachent->d_name);
else {
if (filename == NULL)
filename =
strdup(cachent->d_name) ?: "(?)";
if (canmount_on &&
forked_canmount_on ==
canmount_on_pids_len) {
size_t new_len =
(canmount_on_pids_len ?: 16) * 2;
void *new_pidlist =
realloc(canmount_on_pids,
new_len *
sizeof (*canmount_on_pids));
if (!new_pidlist) {
fprintf(stderr,
PROGNAME "[%d]: "
"out of memory! "
"Mount ordering may be "
"affected.\n", getpid());
continue;
}
canmount_on_pids = new_pidlist;
canmount_on_pids_len = new_len;
struct line *l = calloc(1, sizeof (*l));
char *nl = strdup(line);
if (l == NULL || nl == NULL) {
fprintf(stderr, PROGNAME "[%d]: "
"out of memory for \"%s\" in %s\n",
getpid(), line, cachent->d_name);
free(l);
free(nl);
continue;
}
if (canmount_on) {
canmount_on_pids[forked_canmount_on] =
pid;
++forked_canmount_on;
} else
++forked_canmount_not_on;
break;
}
l->line = nl;
l->fname = filename;
l->next = lines_canmount_not_on;
lines_canmount_not_on = l;
}
}
(void) fclose(cachefile);
fclose(cachefile);
}
free(line);
if (forked_canmount_on == 0) {
/* No canmount=on processes to finish, so don't deadlock here */
for (size_t i = 0; i < forked_canmount_not_on; ++i)
sem_post(&noauto_files->noauto_not_on_sem);
} else {
/* Likely a no-op, since we got these from a narrow fork loop */
qsort(canmount_on_pids, forked_canmount_on,
sizeof (*canmount_on_pids), PID_T_CMP);
}
while (lines_canmount_not_on) {
struct line *l = lines_canmount_not_on;
lines_canmount_not_on = l->next;
int status, ret = 0;
struct rusage usage;
size_t forked_canmount_on_max = forked_canmount_on;
while ((pid = wait4(-1, &status, 0, &usage)) != -1) {
ret |= WEXITSTATUS(status) | WTERMSIG(status);
if (forked_canmount_on != 0) {
if (bsearch(&pid, canmount_on_pids,
forked_canmount_on_max, sizeof (*canmount_on_pids),
PID_T_CMP))
--forked_canmount_on;
if (forked_canmount_on == 0) {
/*
* All canmount=on processes have finished,
* let all the lower-priority ones finish now
*/
for (size_t i = 0;
i < forked_canmount_not_on; ++i)
sem_post(
&noauto_files->noauto_not_on_sem);
}
ret |= line_worker(l->line, l->fname);
if (FREE_STATICS) {
free(l->line);
free(l);
}
if (debug >= 2)
printf(PROGNAME ": %d done, user=%llu.%06us, "
"system=%llu.%06us, maxrss=%ldB, ex=0x%x\n",
(int)pid,
(unsigned long long) usage.ru_utime.tv_sec,
(unsigned int) usage.ru_utime.tv_usec,
(unsigned long long) usage.ru_stime.tv_sec,
(unsigned int) usage.ru_stime.tv_usec,
usage.ru_maxrss * 1024, status);
}
if (debug) {
struct timespec time_end = {};
clock_gettime(CLOCK_MONOTONIC_RAW, &time_end);
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
printf(
"\n"
PROGNAME ": self : "
"user=%llu.%06us, system=%llu.%06us, maxrss=%ldB\n",
(unsigned long long) usage.ru_utime.tv_sec,
(unsigned int) usage.ru_utime.tv_usec,
(unsigned long long) usage.ru_stime.tv_sec,
(unsigned int) usage.ru_stime.tv_usec,
usage.ru_maxrss * 1024);
getrusage(RUSAGE_CHILDREN, &usage);
printf(PROGNAME ": children: "
PROGNAME ": "
"user=%llu.%06us, system=%llu.%06us, maxrss=%ldB\n",
(unsigned long long) usage.ru_utime.tv_sec,
(unsigned int) usage.ru_utime.tv_usec,
@@ -1068,7 +977,7 @@ main(int argc, char **argv)
time_init.tv_nsec / 1000000000;
time_init.tv_nsec %= 1000000000;
printf(PROGNAME ": wall : "
printf(PROGNAME ": "
"total=%llu.%09llus = "
"init=%llu.%09llus + real=%llu.%09llus\n",
(unsigned long long) time_init.tv_sec,
@@ -1077,7 +986,15 @@ main(int argc, char **argv)
(unsigned long long) time_start.tv_nsec,
(unsigned long long) time_end.tv_sec,
(unsigned long long) time_end.tv_nsec);
fflush(stdout);
}
if (FREE_STATICS) {
closedir(fslist_dir);
tdestroy(noauto_files, free);
tdestroy(known_pools, free);
regfree(&uri_regex);
}
_exit(ret);
}
+3 -2
View File
@@ -10,9 +10,10 @@ dist_pkgsysconf_DATA = \
vdev_id.conf.multipath.example \
vdev_id.conf.scsi.example
pkgsysconf_SCRIPTS = \
pkgsysconf_DATA = \
zfs-functions
SUBSTFILES += $(pkgsysconf_SCRIPTS)
SUBSTFILES += $(pkgsysconf_DATA)
SHELLCHECKSCRIPTS = $(pkgsysconf_DATA)
SHELLCHECK_SHELL = dash # local variables
+4 -3
View File
@@ -795,9 +795,10 @@ extern int zfs_receive(libzfs_handle_t *, const char *, nvlist_t *,
recvflags_t *, int, avl_tree_t *);
typedef enum diff_flags {
ZFS_DIFF_PARSEABLE = 0x1,
ZFS_DIFF_TIMESTAMP = 0x2,
ZFS_DIFF_CLASSIFY = 0x4
ZFS_DIFF_PARSEABLE = 1 << 0,
ZFS_DIFF_TIMESTAMP = 1 << 1,
ZFS_DIFF_CLASSIFY = 1 << 2,
ZFS_DIFF_NO_MANGLE = 1 << 3
} diff_flags_t;
extern int zfs_show_diffs(zfs_handle_t *, int, const char *, const char *,
+1
View File
@@ -234,6 +234,7 @@ typedef struct differ_info {
boolean_t scripted;
boolean_t classify;
boolean_t timestamped;
boolean_t no_mangle;
uint64_t shares;
int zerr;
int cleanupfd;
-1
View File
@@ -22,7 +22,6 @@ KERNEL_H = \
inttypes.h \
isa_defs.h \
kmem_cache.h \
kidmap.h \
kmem.h \
kstat.h \
list_impl.h \
+10 -128
View File
@@ -48,138 +48,20 @@ extern "C" {
typedef struct ucred cred_t;
#define CRED() curthread->td_ucred
/*
* kcred is used when you need all privileges.
*/
#define kcred (thread0.td_ucred)
#define KUID_TO_SUID(x) (x)
#define KGID_TO_SGID(x) (x)
#define crgetuid(cred) ((cred)->cr_uid)
#define crgetruid(cred) ((cred)->cr_ruid)
#define crgetgid(cred) ((cred)->cr_gid)
#define crgetgroups(cred) ((cred)->cr_groups)
#define crgetngroups(cred) ((cred)->cr_ngroups)
#define crgetsid(cred, i) (NULL)
struct proc; /* cred.h is included in proc.h */
struct prcred;
struct ksid;
struct ksidlist;
struct credklpd;
struct credgrp;
struct auditinfo_addr; /* cred.h is included in audit.h */
extern int ngroups_max;
/*
* kcred is used when you need all privileges.
*/
extern void cred_init(void);
extern void crfree(cred_t *);
extern cred_t *cralloc(void); /* all but ref uninitialized */
extern cred_t *cralloc_ksid(void); /* cralloc() + ksid alloc'ed */
extern cred_t *crget(void); /* initialized */
extern void crcopy_to(cred_t *, cred_t *);
extern cred_t *crdup(cred_t *);
extern void crdup_to(cred_t *, cred_t *);
extern cred_t *crgetcred(void);
extern void crset(struct proc *, cred_t *);
extern void crset_zone_privall(cred_t *);
extern int supgroupmember(gid_t, const cred_t *);
extern int hasprocperm(const cred_t *, const cred_t *);
extern int prochasprocperm(struct proc *, struct proc *, const cred_t *);
extern int crcmp(const cred_t *, const cred_t *);
extern cred_t *zone_kcred(void);
extern gid_t crgetrgid(const cred_t *);
extern gid_t crgetsgid(const cred_t *);
#define crgetzoneid(cr) ((cr)->cr_prison->pr_id)
extern projid_t crgetprojid(const cred_t *);
extern cred_t *crgetmapped(const cred_t *);
extern const struct auditinfo_addr *crgetauinfo(const cred_t *);
extern struct auditinfo_addr *crgetauinfo_modifiable(cred_t *);
extern uint_t crgetref(const cred_t *);
extern const gid_t *crgetggroups(const struct credgrp *);
/*
* Sets real, effective and/or saved uid/gid;
* -1 argument accepted as "no change".
*/
extern int crsetresuid(cred_t *, uid_t, uid_t, uid_t);
extern int crsetresgid(cred_t *, gid_t, gid_t, gid_t);
/*
* Sets real, effective and saved uids/gids all to the same
* values. Both values must be non-negative and <= MAXUID
*/
extern int crsetugid(cred_t *, uid_t, gid_t);
/*
* Functions to handle the supplemental group list.
*/
extern struct credgrp *crgrpcopyin(int, gid_t *);
extern void crgrprele(struct credgrp *);
extern void crsetcredgrp(cred_t *, struct credgrp *);
/*
* Private interface for setting zone association of credential.
*/
struct zone;
extern void crsetzone(cred_t *, struct zone *);
extern struct zone *crgetzone(const cred_t *);
/*
* Private interface for setting project id in credential.
*/
extern void crsetprojid(cred_t *, projid_t);
/*
* Private interface for nfs.
*/
extern cred_t *crnetadjust(cred_t *);
/*
* Private interface for procfs.
*/
extern void cred2prcred(const cred_t *, struct prcred *);
/*
* Private interfaces for Rampart Trusted Solaris.
*/
struct ts_label_s;
extern struct ts_label_s *crgetlabel(const cred_t *);
extern boolean_t crisremote(const cred_t *);
/*
* Private interfaces for ephemeral uids.
*/
#define VALID_UID(id, zn) \
((id) <= MAXUID || valid_ephemeral_uid((zn), (id)))
#define VALID_GID(id, zn) \
((id) <= MAXUID || valid_ephemeral_gid((zn), (id)))
extern boolean_t valid_ephemeral_uid(struct zone *, uid_t);
extern boolean_t valid_ephemeral_gid(struct zone *, gid_t);
extern int eph_uid_alloc(struct zone *, int, uid_t *, int);
extern int eph_gid_alloc(struct zone *, int, gid_t *, int);
extern void crsetsid(cred_t *, struct ksid *, int);
extern void crsetsidlist(cred_t *, struct ksidlist *);
extern struct ksidlist *crgetsidlist(const cred_t *);
extern int crsetpriv(cred_t *, ...);
extern struct credklpd *crgetcrklpd(const cred_t *);
extern void crsetcrklpd(cred_t *, struct credklpd *);
#define crgetuid(cr) ((cr)->cr_uid)
#define crgetruid(cr) ((cr)->cr_ruid)
#define crgetgid(cr) ((cr)->cr_gid)
#define crgetgroups(cr) ((cr)->cr_groups)
#define crgetngroups(cr) ((cr)->cr_ngroups)
#define crgetzoneid(cr) ((cr)->cr_prison->pr_id)
#ifdef __cplusplus
}
-41
View File
@@ -1,41 +0,0 @@
/*
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _OPENSOLARIS_SYS_KIDMAP_H_
#define _OPENSOLARIS_SYS_KIDMAP_H_
#include <sys/idmap.h>
typedef int32_t idmap_stat;
typedef void idmap_get_handle_t;
#define kidmap_get_create() (NULL)
#define kidmap_get_destroy(hdl) do { } while (0)
#define kidmap_get_mappings(hdl) (NULL)
#endif /* _OPENSOLARIS_SYS_KIDMAP_H_ */
-25
View File
@@ -29,7 +29,6 @@
#ifndef _OPENSOLARIS_SYS_SID_H_
#define _OPENSOLARIS_SYS_SID_H_
#include <sys/idmap.h>
#include <sys/kidmap.h>
typedef struct ksiddomain {
char *kd_name; /* Domain part of SID */
@@ -59,28 +58,4 @@ ksiddomain_rele(ksiddomain_t *kd)
kmem_free(kd, sizeof (*kd));
}
static __inline uint_t
ksid_getid(ksid_t *ks)
{
panic("%s has been unexpectedly called", __func__);
}
static __inline const char *
ksid_getdomain(ksid_t *ks)
{
panic("%s has been unexpectedly called", __func__);
}
static __inline uint_t
ksid_getrid(ksid_t *ks)
{
panic("%s has been unexpectedly called", __func__);
}
#define kidmap_getsidbyuid(zone, uid, sid_prefix, rid) (1)
#define kidmap_getsidbygid(zone, gid, sid_prefix, rid) (1)
#endif /* _OPENSOLARIS_SYS_SID_H_ */
+18 -14
View File
@@ -123,25 +123,29 @@ extern minor_t zfsdev_minor_alloc(void);
#define zn_rlimit_fsize(zp, uio) \
vn_rlimit_fsize(ZTOV(zp), GET_UIO_STRUCT(uio), zfs_uio_td(uio))
#define ZFS_ENTER_ERROR(zfsvfs, error) do { \
ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \
if (__predict_false((zfsvfs)->z_unmounted)) { \
ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
return (error); \
} \
} while (0)
/* Called on entry to each ZFS vnode and vfs operation */
#define ZFS_ENTER(zfsvfs) \
{ \
ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \
if (__predict_false((zfsvfs)->z_unmounted)) { \
ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
return (EIO); \
} \
}
#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO)
/* Must be called before exiting the vop */
#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
#define ZFS_VERIFY_ZP_ERROR(zp, error) do { \
if (__predict_false((zp)->z_sa_hdl == NULL)) { \
ZFS_EXIT((zp)->z_zfsvfs); \
return (error); \
} \
} while (0)
/* Verifies the znode is valid */
#define ZFS_VERIFY_ZP(zp) \
if (__predict_false((zp)->z_sa_hdl == NULL)) { \
ZFS_EXIT((zp)->z_zfsvfs); \
return (EIO); \
} \
#define ZFS_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, EIO)
/*
* Macros for dealing with dmu_buf_hold
+37 -8
View File
@@ -495,21 +495,45 @@ blk_queue_discard_granularity(struct request_queue *q, unsigned int dg)
}
/*
* 5.19 API,
* bdev_max_discard_sectors()
*
* 2.6.32 API,
* blk_queue_discard()
*/
static inline boolean_t
bdev_discard_supported(struct block_device *bdev)
{
#if defined(HAVE_BDEV_MAX_DISCARD_SECTORS)
return (!!bdev_max_discard_sectors(bdev));
#elif defined(HAVE_BLK_QUEUE_DISCARD)
return (!!blk_queue_discard(bdev_get_queue(bdev)));
#else
#error "Unsupported kernel"
#endif
}
/*
* 5.19 API,
* bdev_max_secure_erase_sectors()
*
* 4.8 API,
* blk_queue_secure_erase()
*
* 2.6.36 - 4.7 API,
* blk_queue_secdiscard()
*/
static inline int
blk_queue_discard_secure(struct request_queue *q)
static inline boolean_t
bdev_secure_discard_supported(struct block_device *bdev)
{
#if defined(HAVE_BLK_QUEUE_SECURE_ERASE)
return (blk_queue_secure_erase(q));
#if defined(HAVE_BDEV_MAX_SECURE_ERASE_SECTORS)
return (!!bdev_max_secure_erase_sectors(bdev));
#elif defined(HAVE_BLK_QUEUE_SECURE_ERASE)
return (!!blk_queue_secure_erase(bdev_get_queue(bdev)));
#elif defined(HAVE_BLK_QUEUE_SECDISCARD)
return (blk_queue_secdiscard(q));
return (!!blk_queue_secdiscard(bdev_get_queue(bdev)));
#else
return (0);
#error "Unsupported kernel"
#endif
}
@@ -527,7 +551,10 @@ blk_generic_start_io_acct(struct request_queue *q __attribute__((unused)),
struct gendisk *disk __attribute__((unused)),
int rw __attribute__((unused)), struct bio *bio)
{
#if defined(HAVE_DISK_IO_ACCT)
#if defined(HAVE_BDEV_IO_ACCT)
return (bdev_start_io_acct(bio->bi_bdev, bio_sectors(bio),
bio_op(bio), jiffies));
#elif defined(HAVE_DISK_IO_ACCT)
return (disk_start_io_acct(disk, bio_sectors(bio), bio_op(bio)));
#elif defined(HAVE_BIO_IO_ACCT)
return (bio_start_io_acct(bio));
@@ -550,7 +577,9 @@ blk_generic_end_io_acct(struct request_queue *q __attribute__((unused)),
struct gendisk *disk __attribute__((unused)),
int rw __attribute__((unused)), struct bio *bio, unsigned long start_time)
{
#if defined(HAVE_DISK_IO_ACCT)
#if defined(HAVE_BDEV_IO_ACCT)
bdev_end_io_acct(bio->bi_bdev, bio_op(bio), start_time);
#elif defined(HAVE_DISK_IO_ACCT)
disk_end_io_acct(disk, bio_op(bio), start_time);
#elif defined(HAVE_BIO_IO_ACCT)
bio_end_io_acct(bio, start_time);
+4 -2
View File
@@ -87,7 +87,9 @@
#if defined(HAVE_KERNEL_FPU_API_HEADER)
#include <asm/fpu/api.h>
#if defined(HAVE_KERNEL_FPU_INTERNAL_HEADER)
#include <asm/fpu/internal.h>
#endif
#if defined(HAVE_KERNEL_FPU_XCR_HEADER)
#include <asm/fpu/xcr.h>
#endif
@@ -420,9 +422,9 @@ kfpu_end(void)
if (static_cpu_has(X86_FEATURE_XSAVE)) {
kfpu_do_xrstor("xrstor", &state->xsave, ~0);
} else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_save_fxsr(&state->fxsave);
kfpu_restore_fxsr(&state->fxsave);
} else {
kfpu_save_fsave(&state->fsave);
kfpu_restore_fsave(&state->fsave);
}
out:
local_irq_enable();
-5
View File
@@ -49,12 +49,7 @@ extern void crhold(cred_t *cr);
extern void crfree(cred_t *cr);
extern uid_t crgetuid(const cred_t *cr);
extern uid_t crgetruid(const cred_t *cr);
extern uid_t crgetsuid(const cred_t *cr);
extern uid_t crgetfsuid(const cred_t *cr);
extern gid_t crgetgid(const cred_t *cr);
extern gid_t crgetrgid(const cred_t *cr);
extern gid_t crgetsgid(const cred_t *cr);
extern gid_t crgetfsgid(const cred_t *cr);
extern int crgetngroups(const cred_t *cr);
extern gid_t *crgetgroups(const cred_t *cr);
extern int groupmember(gid_t gid, const cred_t *cr);
+3 -4
View File
@@ -321,13 +321,12 @@ typedef struct dmu_buf_impl {
uint8_t db_dirtycnt;
} dmu_buf_impl_t;
/* Note: the dbuf hash table is exposed only for the mdb module */
#define DBUF_MUTEXES 2048
#define DBUF_HASH_MUTEX(h, idx) (&(h)->hash_mutexes[(idx) & (DBUF_MUTEXES-1)])
#define DBUF_RWLOCKS 8192
#define DBUF_HASH_RWLOCK(h, idx) (&(h)->hash_rwlocks[(idx) & (DBUF_RWLOCKS-1)])
typedef struct dbuf_hash_table {
uint64_t hash_table_mask;
dmu_buf_impl_t **hash_table;
kmutex_t hash_mutexes[DBUF_MUTEXES] ____cacheline_aligned;
krwlock_t hash_rwlocks[DBUF_RWLOCKS] ____cacheline_aligned;
} dbuf_hash_table_t;
typedef void (*dbuf_prefetch_fn)(void *, boolean_t);
+1 -1
View File
@@ -616,7 +616,7 @@ _NOTE(CONSTCOND) } while (0)
#else
#define dprintf_dnode(db, fmt, ...)
#define DNODE_VERIFY(dn)
#define DNODE_VERIFY(dn) ((void) sizeof ((uintptr_t)(dn)))
#define FREE_VERIFY(db, start, end, tx)
#endif
+1
View File
@@ -370,6 +370,7 @@ struct spa {
boolean_t spa_is_root; /* pool is root */
int spa_minref; /* num refs when first opened */
spa_mode_t spa_mode; /* SPA_MODE_{READ|WRITE} */
boolean_t spa_read_spacemaps; /* spacemaps available if ro */
spa_log_state_t spa_log_state; /* log state */
uint64_t spa_autoexpand; /* lun expansion on/off */
ddt_t *spa_ddt[ZIO_CHECKSUM_FUNCTIONS]; /* in-core DDTs */
+5
View File
@@ -110,7 +110,12 @@ typedef enum zap_flags {
* already randomly distributed.
*/
ZAP_FLAG_PRE_HASHED_KEY = 1 << 2,
#if defined(__linux__) && defined(_KERNEL)
} zfs_zap_flags_t;
#define zap_flags_t zfs_zap_flags_t
#else
} zap_flags_t;
#endif
/*
* Create a new zapobj with no attributes and return its object number.
+15 -1
View File
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -136,6 +137,7 @@ statfs2mnttab(struct statfs *sfs, struct mnttab *mp)
mp->mnt_mntopts = gmntopts;
}
static pthread_rwlock_t gsfs_lock = PTHREAD_RWLOCK_INITIALIZER;
static struct statfs *gsfs = NULL;
static int allfs = 0;
@@ -145,6 +147,8 @@ statfs_init(void)
struct statfs *sfs;
int error;
(void) pthread_rwlock_wrlock(&gsfs_lock);
if (gsfs != NULL) {
free(gsfs);
gsfs = NULL;
@@ -162,6 +166,7 @@ statfs_init(void)
sfs = realloc(gsfs, allfs * sizeof (gsfs[0]));
if (sfs != NULL)
gsfs = sfs;
(void) pthread_rwlock_unlock(&gsfs_lock);
return (0);
fail:
error = errno;
@@ -169,6 +174,7 @@ fail:
free(gsfs);
gsfs = NULL;
allfs = 0;
(void) pthread_rwlock_unlock(&gsfs_lock);
return (error);
}
@@ -181,6 +187,8 @@ getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
if (error != 0)
return (error);
(void) pthread_rwlock_rdlock(&gsfs_lock);
for (i = 0; i < allfs; i++) {
if (mrefp->mnt_special != NULL &&
strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
@@ -195,8 +203,10 @@ getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
continue;
}
statfs2mnttab(&gsfs[i], mgetp);
(void) pthread_rwlock_unlock(&gsfs_lock);
return (0);
}
(void) pthread_rwlock_unlock(&gsfs_lock);
return (-1);
}
@@ -214,9 +224,13 @@ getmntent(FILE *fp, struct mnttab *mp)
if (error != 0)
return (error);
}
if (nfs >= allfs)
(void) pthread_rwlock_rdlock(&gsfs_lock);
if (nfs >= allfs) {
(void) pthread_rwlock_unlock(&gsfs_lock);
return (-1);
}
statfs2mnttab(&gsfs[nfs], mp);
(void) pthread_rwlock_unlock(&gsfs_lock);
if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
return (errno);
return (0);
-1
View File
@@ -606,7 +606,6 @@ get_key_material_https(libzfs_handle_t *hdl, const char *uri,
kfdok:
if ((key = fdopen(kfd, "r+")) == NULL) {
ret = errno;
free(path);
(void) close(kfd);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"Couldn't reopen temporary file: %s"), strerror(ret));
+9 -4
View File
@@ -449,14 +449,19 @@ make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
* We've managed to open the dataset and gather statistics. Determine
* the high-level type.
*/
if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) {
zhp->zfs_head_type = ZFS_TYPE_VOLUME;
else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
} else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) {
zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
else if (zhp->zfs_dmustats.dds_type == DMU_OST_OTHER)
} else if (zhp->zfs_dmustats.dds_type == DMU_OST_OTHER) {
errno = EINVAL;
return (-1);
else
} else if (zhp->zfs_dmustats.dds_inconsistent) {
errno = EBUSY;
return (-1);
} else {
abort();
}
if (zhp->zfs_dmustats.dds_is_snapshot)
zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
+10 -4
View File
@@ -122,9 +122,9 @@ stream_bytes(FILE *fp, const char *string)
while ((c = *string++) != '\0') {
if (c > ' ' && c != '\\' && c < '\177') {
(void) fprintf(fp, "%c", c);
(void) fputc(c, fp);
} else {
(void) fprintf(fp, "\\%04o", (uint8_t)c);
(void) fprintf(fp, "\\%04hho", (uint8_t)c);
}
}
}
@@ -176,8 +176,13 @@ print_what(FILE *fp, mode_t what)
static void
print_cmn(FILE *fp, differ_info_t *di, const char *file)
{
stream_bytes(fp, di->dsmnt);
stream_bytes(fp, file);
if (!di->no_mangle) {
stream_bytes(fp, di->dsmnt);
stream_bytes(fp, file);
} else {
(void) fputs(di->dsmnt, fp);
(void) fputs(file, fp);
}
}
static void
@@ -752,6 +757,7 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap,
di.scripted = (flags & ZFS_DIFF_PARSEABLE);
di.classify = (flags & ZFS_DIFF_CLASSIFY);
di.timestamped = (flags & ZFS_DIFF_TIMESTAMP);
di.no_mangle = (flags & ZFS_DIFF_NO_MANGLE);
di.outputfd = outfd;
di.datafd = pipefd[0];
+10 -10
View File
@@ -146,10 +146,10 @@ zpool_clear_label(int fd)
struct stat64 statbuf;
int l;
vdev_label_t *label;
l2arc_dev_hdr_phys_t *l2dhdr;
l2arc_dev_hdr_phys_t *l2dhdr = NULL;
uint64_t size;
int labels_cleared = 0, header_cleared = 0;
boolean_t clear_l2arc_header = B_FALSE;
int labels_cleared = 0;
boolean_t clear_l2arc_header = B_FALSE, header_cleared = B_FALSE;
if (fstat64_blk(fd, &statbuf) == -1)
return (0);
@@ -219,13 +219,10 @@ zpool_clear_label(int fd)
}
/* Clear the L2ARC header. */
if (clear_l2arc_header) {
memset(l2dhdr, 0, sizeof (l2arc_dev_hdr_phys_t));
if (pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t),
VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t)) {
header_cleared++;
}
}
if (clear_l2arc_header &&
pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t),
VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t))
header_cleared = B_TRUE;
free(label);
free(l2dhdr);
@@ -233,6 +230,9 @@ zpool_clear_label(int fd)
if (labels_cleared == 0)
return (-1);
if (clear_l2arc_header && !header_cleared)
return (-1);
return (0);
}
+3 -1
View File
@@ -1348,7 +1348,7 @@ zfs_mount_task(void *arg)
sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
if (mp->mnt_func(handles[idx], mp->mnt_data) != 0)
return;
goto out;
/*
* We dispatch tasks to mount filesystems with mountpoints underneath
@@ -1369,6 +1369,8 @@ zfs_mount_task(void *arg)
zfs_dispatch_mount(mp->mnt_hdl, handles, num_handles, i,
mp->mnt_func, mp->mnt_data, mp->mnt_tp);
}
out:
free(mp);
}
+15 -11
View File
@@ -2133,7 +2133,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
avl_tree_t *fsavl = NULL;
static uint64_t holdseq;
int spa_version;
int featureflags = 0;
FILE *fout;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
@@ -2145,17 +2144,23 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
}
if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM) {
uint64_t version;
version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
if (version >= ZPL_VERSION_SA) {
featureflags |= DMU_BACKUP_FEATURE_SA_SPILL;
if (fromsnap) {
char full_fromsnap_name[ZFS_MAX_DATASET_NAME_LEN];
if (snprintf(full_fromsnap_name, sizeof (full_fromsnap_name),
"%s@%s", zhp->zfs_name, fromsnap) >=
sizeof (full_fromsnap_name)) {
err = EINVAL;
goto stderr_out;
}
zfs_handle_t *fromsnapn = zfs_open(zhp->zfs_hdl,
full_fromsnap_name, ZFS_TYPE_SNAPSHOT);
if (fromsnapn == NULL) {
err = -1;
goto err_out;
}
zfs_close(fromsnapn);
}
if (flags->holds)
featureflags |= DMU_BACKUP_FEATURE_HOLDS;
if (flags->replicate || flags->doall || flags->props ||
flags->holds || flags->backup) {
char full_tosnap_name[ZFS_MAX_DATASET_NAME_LEN];
@@ -2522,8 +2527,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
if (flags->progress) {
void *status = NULL;
if (err != 0)
(void) pthread_cancel(ptid);
(void) pthread_cancel(ptid);
(void) pthread_join(ptid, &status);
int error = (int)(uintptr_t)status;
if (error != 0 && status != PTHREAD_CANCELED)
+17 -11
View File
@@ -527,7 +527,7 @@ zfs_dev_is_dm(const char *dev_name)
boolean_t
zfs_dev_is_whole_disk(const char *dev_name)
{
struct dk_gpt *label;
struct dk_gpt *label = NULL;
int fd;
if ((fd = open(dev_name, O_RDONLY | O_DIRECT | O_CLOEXEC)) < 0)
@@ -613,22 +613,24 @@ zfs_get_underlying_path(const char *dev_name)
/*
* A disk is considered a multipath whole disk when:
* DEVNAME key value has "dm-"
* DM_NAME key value has "mpath" prefix
* DM_UUID key exists
* DM_UUID key exists and starts with 'mpath-'
* ID_PART_TABLE_TYPE key does not exist or is not gpt
* ID_FS_LABEL key does not exist (disk isn't labeled)
*/
static boolean_t
udev_mpath_whole_disk(struct udev_device *dev)
is_mpath_udev_sane(struct udev_device *dev)
{
const char *devname, *type, *uuid;
const char *devname, *type, *uuid, *label;
devname = udev_device_get_property_value(dev, "DEVNAME");
type = udev_device_get_property_value(dev, "ID_PART_TABLE_TYPE");
uuid = udev_device_get_property_value(dev, "DM_UUID");
label = udev_device_get_property_value(dev, "ID_FS_LABEL");
if ((devname != NULL && strncmp(devname, "/dev/dm-", 8) == 0) &&
((type == NULL) || (strcmp(type, "gpt") != 0)) &&
(uuid != NULL)) {
((uuid != NULL) && (strncmp(uuid, "mpath-", 6) == 0)) &&
(label == NULL)) {
return (B_TRUE);
}
@@ -636,7 +638,11 @@ udev_mpath_whole_disk(struct udev_device *dev)
}
/*
* Check if a disk is effectively a multipath whole disk
* Check if a disk is a multipath "blank" disk:
*
* 1. The disk has udev values that suggest it's a multipath disk
* 2. The disk is not currently labeled with a filesystem of any type
* 3. There are no partitions on the disk
*/
boolean_t
is_mpath_whole_disk(const char *path)
@@ -645,7 +651,6 @@ is_mpath_whole_disk(const char *path)
struct udev_device *dev = NULL;
char nodepath[MAXPATHLEN];
char *sysname;
boolean_t wholedisk = B_FALSE;
if (realpath(path, nodepath) == NULL)
return (B_FALSE);
@@ -660,10 +665,11 @@ is_mpath_whole_disk(const char *path)
return (B_FALSE);
}
wholedisk = udev_mpath_whole_disk(dev);
/* Sanity check some udev values */
boolean_t is_sane = is_mpath_udev_sane(dev);
udev_device_unref(dev);
return (wholedisk);
return (is_sane);
}
#else /* HAVE_LIBUDEV */
+1 -4
View File
@@ -1791,16 +1791,13 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp,
nvlist_t *match = NULL;
nvlist_t *config = NULL;
char *sepp = NULL;
char sep = '\0';
int count = 0;
char *targetdup = strdup(target);
*configp = NULL;
if ((sepp = strpbrk(targetdup, "/@")) != NULL) {
sep = *sepp;
if ((sepp = strpbrk(targetdup, "/@")) != NULL)
*sepp = '\0';
}
pools = zpool_search_import(hdl, args, pco);
+1
View File
@@ -15,6 +15,7 @@ dist_man_MANS = \
man4/spl.4 \
man4/zfs.4 \
\
man7/dracut.zfs.7 \
man7/zpool-features.7 \
man7/zfsconcepts.7 \
man7/zfsprops.7 \
+4 -4
View File
@@ -1581,12 +1581,12 @@ Allow no-operation writes.
The occurrence of nopwrites will further depend on other pool properties
.Pq i.a. the checksumming and compression algorithms .
.
.It Sy zfs_dmu_offset_next_sync Ns = Ns Sy 0 Ns | Ns 1 Pq int
.It Sy zfs_dmu_offset_next_sync Ns = Ns Sy 1 Ns | Ns 0 Pq int
Enable forcing TXG sync to find holes.
When enabled forces ZFS to act like prior versions when
When enabled forces ZFS to sync data when
.Sy SEEK_HOLE No or Sy SEEK_DATA
flags are used, which, when a dnode is dirty,
causes TXGs to be synced so that this data can be found.
flags are used allowing holes in a file to be accurately reported.
When disabled holes will not be reported in recently dirtied files.
.
.It Sy zfs_pd_bytes_max Ns = Ns Sy 52428800 Ns B Po 50MB Pc Pq int
The number of bytes which should be prefetched during a pool traversal, like
+278
View File
@@ -0,0 +1,278 @@
.\" SPDX-License-Identifier: 0BSD
.\"
.Dd April 4, 2022
.Dt DRACUT.ZFS 7
.Os
.
.Sh NAME
.Nm dracut.zfs
.Nd overview of ZFS dracut hooks
.
.Sh SYNOPSIS
.Bd -literal -compact
parse-zfs.sh \(-> dracut-cmdline.service
| \(da
| …
| \(da
\e\(em\(em\(em\(em\(em\(em\(em\(em\(-> dracut-initqueue.service
| zfs-import-opts.sh
zfs-load-module.service \(da | |
| | sysinit.target \(da |
\(da | | zfs-import-scan.service \(da
zfs-import-scan.service \(da \(da | zfs-import-cache.service
| zfs-import-cache.service basic.target | |
\e__________________| | \(da \(da
\(da | zfs-load-key.sh
zfs-env-bootfs.service | |
\(da \(da \(da
zfs-import.target \(-> dracut-pre-mount.service
| \(ua |
| dracut-zfs-generator |
| ____________________/|
|/ \(da
| sysroot.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em dracut-zfs-generator
| | \(da |
| \(da sysroot-{usr,etc,lib,&c.}.mount |
| initrd-root-fs.target \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em or \(da
| | zfs-nonroot-necessities.service
| \(da |
\(da dracut-mount.service |
zfs-snapshot-bootfs.service | |
| \(da |
\(da … |
zfs-rollback-bootfs.service | |
| \(da |
| sysroot-usr.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/
| |
| \(da
| initrd-fs.target
\e______________________ |
\e|
\(da
export-zfs.sh initrd.target
| |
\(da \(da
dracut-shutdown.service …
|
\(da
zfs-needshutdown.sh \(-> initrd-cleanup.service
.Ed
.Pp
Compare
.Xr dracut.bootup 7
for the full flowchart.
.
.Sh DESCRIPTION
Under dracut, booting with
.No ZFS-on- Ns Pa /
is facilitated by a number of hooks in the
.Nm 90zfs
module.
.Pp
Booting into a ZFS dataset requires
.Sy mountpoint Ns = Ns Pa /
to be set on the dataset containing the root filesystem (henceforth "the boot dataset") and at the very least either the
.Sy bootfs
property to be set to that dataset, or the
.Sy root=
kernel cmdline (or dracut drop-in) argument to specify it.
.Pp
All children of the boot dataset with
.Sy canmount Ns = Ns Sy on
with
.Sy mountpoint Ns s
matching
.Pa /etc , /bin , /lib , /lib?? , /libx32 , No and Pa /usr
globs are deemed essential and will be mounted as well.
.Pp
.Xr zfs-mount-generator 8
is recommended for proper functioning of the system afterward (correct mount properties, remounting, &c.).
.
.Sh CMDLINE
.Ss Standard
.Bl -tag -compact -width ".Sy root=zfs:AUTO , root=zfs: , root=zfs , Op Sy root="
.It Sy root=zfs:\& Ns Ar dataset , Sy root=ZFS= Ns Ar dataset
Use
.Ar dataset
as the boot dataset.
All pluses
.Pq Sq +
are replaced with spaces
.Pq Sq \ .
.
.It Sy root=zfs:AUTO , root=zfs:\& , root=zfs , Op Sy root=
After import, search for the first pool with the
.Sy bootfs
property set, use its value as-if specified as the
.Ar dataset
above.
.
.It Sy rootfstype=zfs root= Ns Ar dataset
Equivalent to
.Sy root=zfs:\& Ns Ar dataset .
.
.It Sy rootfstype=zfs Op Sy root=
Equivalent to
.Sy root=zfs:AUTO .
.
.It Sy rootflags= Ns Ar flags
Mount the boot dataset with
.Fl o Ar flags ;
cf.\&
.Sx Temporary Mount Point Properties
in
.Xr zfsprops 7 .
These properties will not last, since all filesystems will be re-mounted from the real root.
.
.It Sy debug
If specified,
.Nm dracut-zfs-generator
logs to the journal.
.El
.Pp
Be careful about setting neither
.Sy rootfstype=zfs
nor
.Sy root=zfs:\& Ns Ar dataset
\(em other automatic boot selection methods, like
.Nm systemd-gpt-auto-generator
and
.Nm systemd-fstab-generator
might take precedent.
.
.Ss ZFS-specific
.Bl -tag -compact -width ".Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name"
.It Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name
Execute
.Nm zfs Cm snapshot Ar boot-dataset Ns Sy @ Ns Ar snapshot-name
before pivoting to the real root.
.Ar snapshot-name
defaults to the current kernel release.
.
.It Sy bootfs.rollback Ns Op Sy = Ns Ar snapshot-name
Execute
.Nm zfs Cm snapshot Fl Rf Ar boot-dataset Ns Sy @ Ns Ar snapshot-name
before pivoting to the real root.
.Ar snapshot-name
defaults to the current kernel release.
.
.It Sy spl_hostid= Ns Ar host-id
Use
.Xr zgenhostid 8
to set the host ID to
.Ar host-id ;
otherwise,
.Pa /etc/hostid
inherited from the real root is used.
.
.It Sy zfs_force , zfs.force , zfsforce
Appends
.Fl f
to all
.Nm zpool Cm import
invocations; primarily useful in conjunction with
.Sy spl_hostid= ,
or if no host ID was inherited.
.El
.
.Sh FILES
.Bl -tag -width 0
.It Pa parse-zfs.sh Pq Sy cmdline
Processes
.Sy spl_hostid= .
If
.Sy root=
matches a known pattern, above, provides
.Pa /dev/root
and delays the initqueue until
.Xr zfs 4
is loaded,
.
.It Pa zfs-import-opts.sh Pq Nm systemd No environment generator
Turns
.Sy zfs_force , zfs.force , No or Sy zfsforce
into
.Ev ZPOOL_IMPORT_OPTS Ns = Ns Fl f
for
.Pa zfs-import-scan.service
or
.Pa zfs-import-cache.service .
.
.It Pa zfs-load-key.sh Pq Sy pre-mount
Loads encryption keys for the boot dataset and its essential descendants.
.Bl -tag -compact -offset 4n -width ".Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL"
.It Sy keylocation Ns = Ns Sy prompt
Is prompted for via
.Nm systemd-ask-password
thrice.
.
.It Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL
.Pa network-online.target
is started before loading.
.
.It Sy keylocation Ns = Ns Sy file:// Ns Ar path
If
.Ar path
doesn't exist,
.Nm udevadm No is Cm settle Ns d .
If it still doesn't, it's waited for for up to
.Sy 10 Ns s .
.El
.
.It Pa zfs-env-bootfs.service Pq Nm systemd No service
After pool import, sets
.Ev BOOTFS Ns =
in the systemd environment to the first non-null
.Sy bootfs
value in iteration order.
.
.It Pa dracut-zfs-generator Pq Nm systemd No generator
Generates
.Pa sysroot.mount Pq using Sy rootflags= , No if any .
If an explicit boot dataset was specified, also generates essential mountpoints
.Pq Pa sysroot-etc.mount , sysroot-bin.mount , No &c.\& ,
otherwise generates
.Pa zfs-nonroot-necessities.service
which mounts them explicitly after
.Pa /sysroot
using
.Ev BOOTFS Ns = .
.
.It Pa zfs-snapshot-bootfs.service , zfs-rollback-bootfs.service Pq Nm systemd No services
Consume
.Sy bootfs.snapshot
and
.Sy bootfs.rollback
as described in
.Sx CMDLINE .
Use
.Ev BOOTFS Ns =
if no explicit boot dataset was specified.
.
.It Pa zfs-needshutdown.sh Pq Sy cleanup
If any pools were imported, signals that shutdown hooks are required.
.
.It Pa export-zfs.sh Pq Sy shutdown
Forcibly exports all pools.
.
.It Pa /etc/hostid , /etc/zfs/zpool.cache , /etc/zfs/vdev_id.conf Pq regular files
Included verbatim, hostonly.
.
.It Pa mount-zfs.sh Pq Sy mount
Does nothing on
.Nm systemd
systems
.Pq if Pa dracut-zfs-generator No succeeded .
Otherwise, loads encryption key for the boot dataset from the console or via plymouth.
It may not work at all!
.El
.
.Sh SEE ALSO
.Xr dracut.bootup 7 ,
.Xr zfsprops 7 ,
.Xr zpoolprops 7 ,
.Xr dracut-shutdown.service 8 ,
.Xr systemd-fstab-generator 8 ,
.Xr systemd-gpt-auto-generator 8 ,
.Xr zfs-mount-generator 8 ,
.Xr zgenhostid 8
+5 -1
View File
@@ -39,7 +39,7 @@
.Sh SYNOPSIS
.Nm zfs
.Cm diff
.Op Fl FHt
.Op Fl FHth
.Ar snapshot Ar snapshot Ns | Ns Ar filesystem
.
.Sh DESCRIPTION
@@ -92,6 +92,10 @@ Give more parsable tab-separated output, without header lines and without
arrows.
.It Fl t
Display the path's inode change time as the first column of output.
.It Fl h
Do not
.Sy \e0 Ns Ar ooo Ns -escape
non-ASCII paths.
.El
.
.Sh SEE ALSO
+4 -15
View File
@@ -142,22 +142,11 @@ ZEDLET, if enabled
.Pq see Xr zed 8 .
.
.Sh ENVIRONMENT
The
If the
.Sy ZFS_DEBUG
environment variable can either be
.Sy 0
(default),
.Sy 1
(print summary accounting information at the end), or at least
.Sy 2
(print accounting information for each subprocess as it finishes).
.
If not present,
.Pa /proc/cmdline
is additionally checked for
.Qq debug ,
in which case the debug level is set to
.Sy 2 .
environment variable is nonzero
.Pq or unset and Pa /proc/cmdline No contains Qq Sy debug ,
print summary accounting information at the end.
.
.Sh EXAMPLES
To begin, enable tracking for the pool:
+3 -2
View File
@@ -170,8 +170,9 @@ inherited.
.It Fl r
Recursively inherit the given property for all children.
.It Fl S
Revert the property to the received value if one exists; otherwise operate as
if the
Revert the property to the received value, if one exists;
otherwise, for non-inheritable properties, to the default;
otherwise, operate as if the
.Fl S
option was not specified.
.El
+2 -1
View File
@@ -71,7 +71,8 @@
.Xc
Lists pools available to import.
If the
.Fl d or
.Fl d
or
.Fl c
options are not specified, this command searches for devices using libblkid
on Linux and geom on
+2 -1
View File
@@ -32,7 +32,7 @@ CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h
CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \
-DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \
-D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP -DHAVE_KSID -DCOMPAT_FREEBSD11
-D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP -DCOMPAT_FREEBSD11
.if ${MACHINE_ARCH} == "amd64"
CFLAGS+= -DHAVE_AVX2 -DHAVE_AVX -D__x86_64 -DHAVE_SSE2 -DHAVE_AVX512F -DHAVE_SSSE3
@@ -320,6 +320,7 @@ beforeinstall:
CFLAGS.gcc+= -Wno-pointer-to-int-cast
CFLAGS.clang+= ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.lapi.c= -Wno-cast-qual
CFLAGS.lcompat.c= -Wno-cast-qual
+1 -1
View File
@@ -798,7 +798,7 @@ static gcm_impl_ops_t *gcm_supp_impl[ARRAY_SIZE(gcm_all_impl)];
* fallback to the fastest generic implementation.
*/
const gcm_impl_ops_t *
gcm_impl_get_ops()
gcm_impl_get_ops(void)
{
if (!kfpu_allowed())
return (&gcm_generic_impl);
+11 -1
View File
@@ -250,7 +250,17 @@ sysevent_worker(void *arg __unused)
nvlist_free(event);
}
}
zfs_zevent_destroy(ze);
/*
* We avoid zfs_zevent_destroy() here because we're otherwise racing
* against fm_fini() destroying the zevent_lock. zfs_zevent_destroy()
* will currently only clear `ze->ze_zevent` from an event list then
* free `ze`, so just inline the free() here -- events have already
* been drained.
*/
VERIFY3P(ze->ze_zevent, ==, NULL);
kmem_free(ze, sizeof (zfs_zevent_t));
kthread_exit();
}
+3 -7
View File
@@ -113,7 +113,6 @@ static kstat_t *abd_ksp;
* memory by only using a single zero buffer for the scatter chunks.
*/
abd_t *abd_zero_scatter = NULL;
static char *abd_zero_buf = NULL;
static uint_t
abd_chunkcnt_for_bytes(size_t size)
@@ -241,18 +240,16 @@ abd_free_struct_impl(abd_t *abd)
/*
* Allocate scatter ABD of size SPA_MAXBLOCKSIZE, where
* each chunk in the scatterlist will be set to abd_zero_buf.
* each chunk in the scatterlist will be set to the same area.
*/
_Static_assert(ZERO_REGION_SIZE >= PAGE_SIZE, "zero_region too small");
static void
abd_alloc_zero_scatter(void)
{
uint_t i, n;
n = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
abd_zero_buf = kmem_cache_alloc(abd_chunk_cache, KM_PUSHPAGE);
bzero(abd_zero_buf, PAGE_SIZE);
abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE);
abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER | ABD_FLAG_ZEROS;
abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE;
@@ -260,7 +257,7 @@ abd_alloc_zero_scatter(void)
for (i = 0; i < n; i++) {
ABD_SCATTER(abd_zero_scatter).abd_chunks[i] =
abd_zero_buf;
__DECONST(void *, zero_region);
}
ABDSTAT_BUMP(abdstat_scatter_cnt);
@@ -275,7 +272,6 @@ abd_free_zero_scatter(void)
abd_free_struct(abd_zero_scatter);
abd_zero_scatter = NULL;
kmem_cache_free(abd_chunk_cache, abd_zero_buf);
}
static int
-2
View File
@@ -183,7 +183,6 @@ spa_import_rootpool(const char *name, bool checkpointrewind)
spa_t *spa;
vdev_t *rvd;
nvlist_t *config, *nvtop;
uint64_t txg;
char *pname;
int error;
@@ -196,7 +195,6 @@ spa_import_rootpool(const char *name, bool checkpointrewind)
if (config != NULL) {
pname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
VERIFY0(strcmp(name, pname));
txg = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG);
if ((spa = spa_lookup(pname)) != NULL) {
/*
+5 -1
View File
@@ -1132,8 +1132,12 @@ vdev_geom_fill_unmap_cb(void *buf, size_t len, void *priv)
vm_offset_t addr = (vm_offset_t)buf;
vm_offset_t end = addr + len;
if (bp->bio_ma_n == 0)
if (bp->bio_ma_n == 0) {
bp->bio_ma_offset = addr & PAGE_MASK;
addr &= ~PAGE_MASK;
} else {
ASSERT0(P2PHASE(addr, PAGE_SIZE));
}
do {
bp->bio_ma[bp->bio_ma_n++] =
PHYS_TO_VM_PAGE(pmap_kextract(addr));
+4 -2
View File
@@ -1653,8 +1653,10 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
ZFS_GROUP, &acl_ids->z_fuidp);
gid = vap->va_gid;
} else {
acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER,
cr, &acl_ids->z_fuidp);
uid_t id = crgetuid(cr);
if (IS_EPHEMERAL(id))
id = UID_NOBODY;
acl_ids->z_fuid = (uint64_t)id;
acl_ids->z_fgid = 0;
if (vap->va_mask & AT_GID) {
acl_ids->z_fgid = zfs_fuid_create(zfsvfs,
+76 -31
View File
@@ -97,6 +97,10 @@
VFS_SMR_DECLARE;
#if __FreeBSD_version < 1300103
#define NDFREE_PNBUF(ndp) NDFREE((ndp), NDF_ONLY_PNBUF)
#endif
#if __FreeBSD_version >= 1300047
#define vm_page_wire_lock(pp)
#define vm_page_wire_unlock(pp)
@@ -1060,8 +1064,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
objset_t *os;
dmu_tx_t *tx;
int error;
ksid_t *ksid;
uid_t uid;
uid_t uid = crgetuid(cr);
gid_t gid = crgetgid(cr);
uint64_t projid = ZFS_DEFAULT_PROJID;
zfs_acl_ids_t acl_ids;
@@ -1075,13 +1078,6 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
* If we have an ephemeral id, ACL, or XVATTR then
* make sure file system is at proper version
*/
ksid = crgetsid(cr, KSID_OWNER);
if (ksid)
uid = ksid_getid(ksid);
else
uid = crgetuid(cr);
if (zfsvfs->z_use_fuids == B_FALSE &&
(vsecp || (vap->va_mask & AT_XVATTR) ||
IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
@@ -1415,8 +1411,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
uint64_t txtype;
dmu_tx_t *tx;
int error;
ksid_t *ksid;
uid_t uid;
uid_t uid = crgetuid(cr);
gid_t gid = crgetgid(cr);
zfs_acl_ids_t acl_ids;
boolean_t fuid_dirtied;
@@ -1427,12 +1422,6 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
* If we have an ephemeral id, ACL, or XVATTR then
* make sure file system is at proper version
*/
ksid = crgetsid(cr, KSID_OWNER);
if (ksid)
uid = ksid_getid(ksid);
else
uid = crgetuid(cr);
if (zfsvfs->z_use_fuids == B_FALSE &&
((vap->va_mask & AT_XVATTR) ||
IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
@@ -4073,8 +4062,8 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
int pgsin_b, pgsin_a;
int error;
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
ZFS_ENTER_ERROR(zfsvfs, zfs_vm_pagerret_error);
ZFS_VERIFY_ZP_ERROR(zp, zfs_vm_pagerret_error);
start = IDX_TO_OFF(ma[0]->pindex);
end = IDX_TO_OFF(ma[count - 1]->pindex + 1);
@@ -4198,19 +4187,18 @@ zfs_putpages(struct vnode *vp, vm_page_t *ma, size_t len, int flags,
int err;
int i;
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
object = vp->v_object;
pcount = btoc(len);
ncount = pcount;
KASSERT(ma[0]->object == object, ("mismatching object"));
KASSERT(len > 0 && (len & PAGE_MASK) == 0, ("unexpected length"));
pcount = btoc(len);
ncount = pcount;
for (i = 0; i < pcount; i++)
rtvals[i] = zfs_vm_pagerret_error;
ZFS_ENTER_ERROR(zfsvfs, zfs_vm_pagerret_error);
ZFS_VERIFY_ZP_ERROR(zp, zfs_vm_pagerret_error);
off = IDX_TO_OFF(ma[0]->pindex);
blksz = zp->z_blksz;
lo_off = rounddown(off, blksz);
@@ -5249,6 +5237,11 @@ zfs_freebsd_pathconf(struct vop_pathconf_args *ap)
case _PC_NAME_MAX:
*ap->a_retval = NAME_MAX;
return (0);
#if __FreeBSD_version >= 1400032
case _PC_DEALLOC_PRESENT:
*ap->a_retval = 1;
return (0);
#endif
case _PC_PIPE_BUF:
if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) {
*ap->a_retval = PIPE_BUF;
@@ -5372,7 +5365,7 @@ zfs_getextattr_dir(struct vop_getextattr_args *ap, const char *attrname)
#endif
error = vn_open_cred(&nd, &flags, 0, VN_OPEN_INVFS, ap->a_cred, NULL);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
NDFREE_PNBUF(&nd);
if (error != 0)
return (error);
@@ -5445,7 +5438,7 @@ zfs_getextattr(struct vop_getextattr_args *ap)
error = ENOENT;
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp)
ZFS_VERIFY_ZP(zp);
rw_enter(&zp->z_xattr_lock, RW_READER);
if (zfsvfs->z_use_sa && zp->z_is_sa)
error = zfs_getextattr_sa(ap, attrname);
@@ -5490,12 +5483,12 @@ zfs_deleteextattr_dir(struct vop_deleteextattr_args *ap, const char *attrname)
error = namei(&nd);
vp = nd.ni_vp;
if (error != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
NDFREE_PNBUF(&nd);
return (error);
}
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
NDFREE(&nd, NDF_ONLY_PNBUF);
NDFREE_PNBUF(&nd);
vput(nd.ni_dvp);
if (vp == nd.ni_dvp)
@@ -5620,7 +5613,7 @@ zfs_setextattr_dir(struct vop_setextattr_args *ap, const char *attrname)
error = vn_open_cred(&nd, &flags, 0600, VN_OPEN_INVFS, ap->a_cred,
NULL);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
NDFREE_PNBUF(&nd);
if (error != 0)
return (error);
@@ -5775,7 +5768,7 @@ zfs_listextattr_dir(struct vop_listextattr_args *ap, const char *attrprefix)
#endif
error = namei(&nd);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
NDFREE_PNBUF(&nd);
if (error != 0)
return (error);
@@ -6088,6 +6081,55 @@ zfs_vptocnp(struct vop_vptocnp_args *ap)
return (error);
}
#if __FreeBSD_version >= 1400032
static int
zfs_deallocate(struct vop_deallocate_args *ap)
{
znode_t *zp = VTOZ(ap->a_vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
zilog_t *zilog;
off_t off, len, file_sz;
int error;
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
/*
* Callers might not be able to detect properly that we are read-only,
* so check it explicitly here.
*/
if (zfs_is_readonly(zfsvfs)) {
ZFS_EXIT(zfsvfs);
return (SET_ERROR(EROFS));
}
zilog = zfsvfs->z_log;
off = *ap->a_offset;
len = *ap->a_len;
file_sz = zp->z_size;
if (off + len > file_sz)
len = file_sz - off;
/* Fast path for out-of-range request. */
if (len <= 0) {
*ap->a_len = 0;
ZFS_EXIT(zfsvfs);
return (0);
}
error = zfs_freesp(zp, off, len, O_RDWR, TRUE);
if (error == 0) {
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS ||
(ap->a_ioflag & IO_SYNC) != 0)
zil_commit(zilog, zp->z_id);
*ap->a_offset = off + len;
*ap->a_len = 0;
}
ZFS_EXIT(zfsvfs);
return (error);
}
#endif
struct vop_vector zfs_vnodeops;
struct vop_vector zfs_fifoops;
struct vop_vector zfs_shareops;
@@ -6107,6 +6149,9 @@ struct vop_vector zfs_vnodeops = {
#endif
.vop_access = zfs_freebsd_access,
.vop_allocate = VOP_EINVAL,
#if __FreeBSD_version >= 1400032
.vop_deallocate = zfs_deallocate,
#endif
.vop_lookup = zfs_cache_lookup,
.vop_cachedlookup = zfs_freebsd_cachedlookup,
.vop_getattr = zfs_freebsd_getattr,
+14 -12
View File
@@ -575,7 +575,6 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
dmu_buf_t *db;
timestruc_t now;
uint64_t gen, obj;
int err;
int bonuslen;
int dnodesize;
sa_handle_t *sa_hdl;
@@ -815,12 +814,11 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
VERIFY0(zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx));
}
if (!(flag & IS_ROOT_NODE)) {
vnode_t *vp;
vp = ZTOV(*zpp);
vnode_t *vp = ZTOV(*zpp);
vp->v_vflag |= VV_FORCEINSMQ;
err = insmntque(vp, zfsvfs->z_vfs);
int err = insmntque(vp, zfsvfs->z_vfs);
vp->v_vflag &= ~VV_FORCEINSMQ;
(void) err;
KASSERT(err == 0, ("insmntque() failed: error %d", err));
}
kmem_free(sa_attrs, sizeof (sa_bulk_attr_t) * ZPL_END);
@@ -839,7 +837,9 @@ zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
xoap = xva_getxoptattr(xvap);
ASSERT3P(xoap, !=, NULL);
ASSERT_VOP_IN_SEQC(ZTOV(zp));
if (zp->z_zfsvfs->z_replay == B_FALSE) {
ASSERT_VOP_IN_SEQC(ZTOV(zp));
}
if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
uint64_t times[2];
@@ -932,11 +932,9 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
znode_t *zp;
vnode_t *vp;
sa_handle_t *hdl;
struct thread *td;
int locked;
int err;
td = curthread;
getnewvnode_reserve_();
again:
*zpp = NULL;
@@ -962,7 +960,7 @@ again:
hdl = dmu_buf_get_user(db);
if (hdl != NULL) {
zp = sa_get_userdata(hdl);
zp = sa_get_userdata(hdl);
/*
* Since "SA" does immediate eviction we
@@ -1489,12 +1487,16 @@ zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len);
if (error == 0) {
#if __FreeBSD_version >= 1400032
vnode_pager_purge_range(ZTOV(zp), off, off + len);
#else
/*
* In FreeBSD we cannot free block in the middle of a file,
* but only at the end of a file, so this code path should
* never happen.
* Before __FreeBSD_version 1400032 we cannot free block in the
* middle of a file, but only at the end of a file, so this code
* path should never happen.
*/
vnode_pager_setsize(ZTOV(zp), off);
#endif
}
zfs_rangelock_exit(lr);
+1 -2
View File
@@ -1063,7 +1063,7 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
zvol_state_t *zv;
zfs_locked_range_t *lr;
off_t offset, length;
int i, error;
int error;
boolean_t sync;
zv = dev->si_drv2;
@@ -1072,7 +1072,6 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
KASSERT(zv->zv_open_count > 0,
("Device with zero access count in %s", __func__));
i = IOCPARM_LEN(cmd);
switch (cmd) {
case DIOCGSECTORSIZE:
*(uint32_t *)data = DEV_BSIZE;
+1 -41
View File
@@ -128,7 +128,7 @@ groupmember(gid_t gid, const cred_t *cr)
uid_t
crgetuid(const cred_t *cr)
{
return (KUID_TO_SUID(cr->euid));
return (KUID_TO_SUID(cr->fsuid));
}
/* Return the real user id */
@@ -138,44 +138,9 @@ crgetruid(const cred_t *cr)
return (KUID_TO_SUID(cr->uid));
}
/* Return the saved user id */
uid_t
crgetsuid(const cred_t *cr)
{
return (KUID_TO_SUID(cr->suid));
}
/* Return the filesystem user id */
uid_t
crgetfsuid(const cred_t *cr)
{
return (KUID_TO_SUID(cr->fsuid));
}
/* Return the effective group id */
gid_t
crgetgid(const cred_t *cr)
{
return (KGID_TO_SGID(cr->egid));
}
/* Return the real group id */
gid_t
crgetrgid(const cred_t *cr)
{
return (KGID_TO_SGID(cr->gid));
}
/* Return the saved group id */
gid_t
crgetsgid(const cred_t *cr)
{
return (KGID_TO_SGID(cr->sgid));
}
/* Return the filesystem group id */
gid_t
crgetfsgid(const cred_t *cr)
{
return (KGID_TO_SGID(cr->fsgid));
}
@@ -184,12 +149,7 @@ EXPORT_SYMBOL(crhold);
EXPORT_SYMBOL(crfree);
EXPORT_SYMBOL(crgetuid);
EXPORT_SYMBOL(crgetruid);
EXPORT_SYMBOL(crgetsuid);
EXPORT_SYMBOL(crgetfsuid);
EXPORT_SYMBOL(crgetgid);
EXPORT_SYMBOL(crgetrgid);
EXPORT_SYMBOL(crgetsgid);
EXPORT_SYMBOL(crgetfsgid);
EXPORT_SYMBOL(crgetngroups);
EXPORT_SYMBOL(crgetgroups);
EXPORT_SYMBOL(groupmember);
+1 -1
View File
@@ -1421,7 +1421,7 @@ EXPORT_SYMBOL(spl_kmem_cache_reap_now);
* it should do no harm.
*/
int
spl_kmem_cache_reap_active()
spl_kmem_cache_reap_active(void)
{
return (0);
}
+12 -4
View File
@@ -184,8 +184,11 @@ abd_t *abd_zero_scatter = NULL;
struct page;
/*
* abd_zero_page we will be an allocated zero'd PAGESIZE buffer, which is
* assigned to set each of the pages of abd_zero_scatter.
* _KERNEL - Will point to ZERO_PAGE if it is available or it will be
* an allocated zero'd PAGESIZE buffer.
* Userspace - Will be an allocated zero'ed PAGESIZE buffer.
*
* abd_zero_page is assigned to each of the pages of abd_zero_scatter.
*/
static struct page *abd_zero_page = NULL;
@@ -465,15 +468,19 @@ abd_alloc_zero_scatter(void)
struct scatterlist *sg = NULL;
struct sg_table table;
gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
gfp_t gfp_zero_page = gfp | __GFP_ZERO;
int nr_pages = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
int i = 0;
#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
gfp_t gfp_zero_page = gfp | __GFP_ZERO;
while ((abd_zero_page = __page_cache_alloc(gfp_zero_page)) == NULL) {
ABDSTAT_BUMP(abdstat_scatter_page_alloc_retry);
schedule_timeout_interruptible(1);
}
abd_mark_zfs_page(abd_zero_page);
#else
abd_zero_page = ZERO_PAGE(0);
#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
while (sg_alloc_table(&table, nr_pages, gfp)) {
ABDSTAT_BUMP(abdstat_scatter_sg_table_retry);
@@ -612,7 +619,6 @@ abd_alloc_zero_scatter(void)
ABD_SCATTER(abd_zero_scatter).abd_offset = 0;
ABD_SCATTER(abd_zero_scatter).abd_nents = nr_pages;
abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE;
zfs_refcount_create(&abd_zero_scatter->abd_children);
ABD_SCATTER(abd_zero_scatter).abd_sgl = vmem_alloc(nr_pages *
sizeof (struct scatterlist), KM_SLEEP);
@@ -694,8 +700,10 @@ abd_free_zero_scatter(void)
abd_zero_scatter = NULL;
ASSERT3P(abd_zero_page, !=, NULL);
#if defined(_KERNEL)
#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
abd_unmark_zfs_page(abd_zero_page);
__free_page(abd_zero_page);
#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
#else
umem_free(abd_zero_page, PAGESIZE);
#endif /* _KERNEL */
+5 -5
View File
@@ -121,7 +121,7 @@ secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner,
int
secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
{
if (crgetfsuid(cr) == owner)
if (crgetuid(cr) == owner)
return (0);
if (zpl_inode_owner_or_capable(kcred->user_ns, ip))
@@ -147,7 +147,7 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
int
secpolicy_vnode_chown(const cred_t *cr, uid_t owner)
{
if (crgetfsuid(cr) == owner)
if (crgetuid(cr) == owner)
return (0);
#if defined(CONFIG_USER_NS)
@@ -184,7 +184,7 @@ secpolicy_vnode_remove(const cred_t *cr)
int
secpolicy_vnode_setdac(const cred_t *cr, uid_t owner)
{
if (crgetfsuid(cr) == owner)
if (crgetuid(cr) == owner)
return (0);
#if defined(CONFIG_USER_NS)
@@ -220,7 +220,7 @@ secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid)
if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid)))
return (EPERM);
#endif
if (crgetfsgid(cr) != gid && !groupmember(gid, cr))
if (crgetgid(cr) != gid && !groupmember(gid, cr))
return (priv_policy_user(cr, CAP_FSETID, EPERM));
return (0);
@@ -286,7 +286,7 @@ secpolicy_setid_clear(vattr_t *vap, cred_t *cr)
static int
secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner)
{
if (crgetfsuid(cr) == owner)
if (crgetuid(cr) == owner)
return (0);
#if defined(CONFIG_USER_NS)
+78 -29
View File
@@ -304,8 +304,6 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
rw_exit(&vd->vd_lock);
}
struct request_queue *q = bdev_get_queue(vd->vd_bdev);
/* Determine the physical block size */
int physical_block_size = bdev_physical_block_size(vd->vd_bdev);
@@ -316,13 +314,13 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
v->vdev_nowritecache = B_FALSE;
/* Set when device reports it supports TRIM. */
v->vdev_has_trim = !!blk_queue_discard(q);
v->vdev_has_trim = bdev_discard_supported(vd->vd_bdev);
/* Set when device reports it supports secure TRIM. */
v->vdev_has_securetrim = !!blk_queue_discard_secure(q);
v->vdev_has_securetrim = bdev_secure_discard_supported(vd->vd_bdev);
/* Inform the ZIO pipeline that we are non-rotational */
v->vdev_nonrot = blk_queue_nonrot(q);
v->vdev_nonrot = blk_queue_nonrot(bdev_get_queue(vd->vd_bdev));
/* Physical volume size in bytes for the partition */
*psize = bdev_capacity(vd->vd_bdev);
@@ -460,6 +458,13 @@ vdev_submit_bio_impl(struct bio *bio)
#define preempt_schedule_notrace(x) preempt_schedule(x)
#endif
/*
* As for the Linux 5.18 kernel bio_alloc() expects a block_device struct
* as an argument removing the need to set it with bio_set_dev(). This
* removes the need for all of the following compatibility code.
*/
#if !defined(HAVE_BIO_ALLOC_4ARG)
#ifdef HAVE_BIO_SET_DEV
#if defined(CONFIG_BLK_CGROUP) && defined(HAVE_BIO_SET_DEV_GPL_ONLY)
/*
@@ -467,8 +472,11 @@ vdev_submit_bio_impl(struct bio *bio)
* blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
* As a side effect the function was converted to GPL-only. Define our
* own version when needed which uses rcu_read_lock_sched().
*
* The Linux 5.17 kernel split linux/blk-cgroup.h into a private and a public
* part, moving blkg_tryget into the private one. Define our own version.
*/
#if defined(HAVE_BLKG_TRYGET_GPL_ONLY)
#if defined(HAVE_BLKG_TRYGET_GPL_ONLY) || !defined(HAVE_BLKG_TRYGET)
static inline bool
vdev_blkg_tryget(struct blkcg_gq *blkg)
{
@@ -493,7 +501,7 @@ vdev_blkg_tryget(struct blkcg_gq *blkg)
return (rc);
}
#elif defined(HAVE_BLKG_TRYGET)
#else
#define vdev_blkg_tryget(bg) blkg_tryget(bg)
#endif
#ifdef HAVE_BIO_SET_DEV_MACRO
@@ -553,6 +561,7 @@ bio_set_dev(struct bio *bio, struct block_device *bdev)
bio->bi_bdev = bdev;
}
#endif /* HAVE_BIO_SET_DEV */
#endif /* !HAVE_BIO_ALLOC_4ARG */
static inline void
vdev_submit_bio(struct bio *bio)
@@ -563,6 +572,36 @@ vdev_submit_bio(struct bio *bio)
current->bio_list = bio_list;
}
static inline struct bio *
vdev_bio_alloc(struct block_device *bdev, gfp_t gfp_mask,
unsigned short nr_vecs)
{
struct bio *bio;
#ifdef HAVE_BIO_ALLOC_4ARG
bio = bio_alloc(bdev, nr_vecs, 0, gfp_mask);
#else
bio = bio_alloc(gfp_mask, nr_vecs);
if (likely(bio != NULL))
bio_set_dev(bio, bdev);
#endif
return (bio);
}
static inline unsigned int
vdev_bio_max_segs(zio_t *zio, int bio_size, uint64_t abd_offset)
{
unsigned long nr_segs = abd_nr_pages_off(zio->io_abd,
bio_size, abd_offset);
#ifdef HAVE_BIO_MAX_SEGS
return (bio_max_segs(nr_segs));
#else
return (MIN(nr_segs, BIO_MAX_PAGES));
#endif
}
static int
__vdev_disk_physio(struct block_device *bdev, zio_t *zio,
size_t io_size, uint64_t io_offset, int rw, int flags)
@@ -574,6 +613,7 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio,
int bio_count = 16;
int error = 0;
struct blk_plug plug;
unsigned short nr_vecs;
/*
* Accessing outside the block device is never allowed.
@@ -623,15 +663,8 @@ retry:
goto retry;
}
/* bio_alloc() with __GFP_WAIT never returns NULL */
#ifdef HAVE_BIO_MAX_SEGS
dr->dr_bio[i] = bio_alloc(GFP_NOIO, bio_max_segs(
abd_nr_pages_off(zio->io_abd, bio_size, abd_offset)));
#else
dr->dr_bio[i] = bio_alloc(GFP_NOIO,
MIN(abd_nr_pages_off(zio->io_abd, bio_size, abd_offset),
BIO_MAX_PAGES));
#endif
nr_vecs = vdev_bio_max_segs(zio, bio_size, abd_offset);
dr->dr_bio[i] = vdev_bio_alloc(bdev, GFP_NOIO, nr_vecs);
if (unlikely(dr->dr_bio[i] == NULL)) {
vdev_disk_dio_free(dr);
return (SET_ERROR(ENOMEM));
@@ -640,7 +673,6 @@ retry:
/* Matching put called by vdev_disk_physio_completion */
vdev_disk_dio_get(dr);
bio_set_dev(dr->dr_bio[i], bdev);
BIO_BI_SECTOR(dr->dr_bio[i]) = bio_offset >> 9;
dr->dr_bio[i]->bi_end_io = vdev_disk_physio_completion;
dr->dr_bio[i]->bi_private = dr;
@@ -704,14 +736,12 @@ vdev_disk_io_flush(struct block_device *bdev, zio_t *zio)
if (!q)
return (SET_ERROR(ENXIO));
bio = bio_alloc(GFP_NOIO, 0);
/* bio_alloc() with __GFP_WAIT never returns NULL */
bio = vdev_bio_alloc(bdev, GFP_NOIO, 0);
if (unlikely(bio == NULL))
return (SET_ERROR(ENOMEM));
bio->bi_end_io = vdev_disk_io_flush_completion;
bio->bi_private = zio;
bio_set_dev(bio, bdev);
bio_set_flush(bio);
vdev_submit_bio(bio);
invalidate_bdev(bdev);
@@ -719,12 +749,38 @@ vdev_disk_io_flush(struct block_device *bdev, zio_t *zio)
return (0);
}
static int
vdev_disk_io_trim(zio_t *zio)
{
vdev_t *v = zio->io_vd;
vdev_disk_t *vd = v->vdev_tsd;
#if defined(HAVE_BLKDEV_ISSUE_SECURE_ERASE)
if (zio->io_trim_flags & ZIO_TRIM_SECURE) {
return (-blkdev_issue_secure_erase(vd->vd_bdev,
zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS));
} else {
return (-blkdev_issue_discard(vd->vd_bdev,
zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS));
}
#elif defined(HAVE_BLKDEV_ISSUE_DISCARD)
unsigned long trim_flags = 0;
#if defined(BLKDEV_DISCARD_SECURE)
if (zio->io_trim_flags & ZIO_TRIM_SECURE)
trim_flags |= BLKDEV_DISCARD_SECURE;
#endif
return (-blkdev_issue_discard(vd->vd_bdev,
zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS, trim_flags));
#else
#error "Unsupported kernel"
#endif
}
static void
vdev_disk_io_start(zio_t *zio)
{
vdev_t *v = zio->io_vd;
vdev_disk_t *vd = v->vdev_tsd;
unsigned long trim_flags = 0;
int rw, error;
/*
@@ -797,14 +853,7 @@ vdev_disk_io_start(zio_t *zio)
break;
case ZIO_TYPE_TRIM:
#if defined(BLKDEV_DISCARD_SECURE)
if (zio->io_trim_flags & ZIO_TRIM_SECURE)
trim_flags |= BLKDEV_DISCARD_SECURE;
#endif
zio->io_error = -blkdev_issue_discard(vd->vd_bdev,
zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS,
trim_flags);
zio->io_error = vdev_disk_io_trim(zio);
rw_exit(&vd->vd_lock);
zio_interrupt(zio);
return;
+22 -17
View File
@@ -65,16 +65,15 @@
/*
* A zfs_mod_kobj_t represents a zfs kobject under '/sys/module/zfs'
*/
struct zfs_mod_kobj;
typedef struct zfs_mod_kobj zfs_mod_kobj_t;
struct zfs_mod_kobj {
struct kobject zko_kobj;
struct kobj_type zko_kobj_type;
struct sysfs_ops zko_sysfs_ops;
size_t zko_attr_count;
struct attribute *zko_attr_list; /* allocated */
struct attribute **zko_default_attrs; /* allocated */
struct attribute_group zko_default_group; /* .attrs allocated */
const struct attribute_group *zko_default_groups[2];
size_t zko_child_count;
zfs_mod_kobj_t *zko_children; /* allocated */
};
@@ -126,10 +125,10 @@ zfs_kobj_release(struct kobject *kobj)
zkobj->zko_attr_list = NULL;
}
if (zkobj->zko_default_attrs != NULL) {
kmem_free(zkobj->zko_default_attrs,
if (zkobj->zko_default_group.attrs != NULL) {
kmem_free(zkobj->zko_default_group.attrs,
DEFAULT_ATTR_SIZE(zkobj->zko_attr_count));
zkobj->zko_default_attrs = NULL;
zkobj->zko_default_group.attrs = NULL;
}
if (zkobj->zko_child_count != 0) {
@@ -153,11 +152,12 @@ zfs_kobj_add_attr(zfs_mod_kobj_t *zkobj, int attr_num, const char *attr_name)
{
VERIFY3U(attr_num, <, zkobj->zko_attr_count);
ASSERT(zkobj->zko_attr_list);
ASSERT(zkobj->zko_default_attrs);
ASSERT(zkobj->zko_default_group.attrs);
zkobj->zko_attr_list[attr_num].name = attr_name;
zkobj->zko_attr_list[attr_num].mode = 0444;
zkobj->zko_default_attrs[attr_num] = &zkobj->zko_attr_list[attr_num];
zkobj->zko_default_group.attrs[attr_num] =
&zkobj->zko_attr_list[attr_num];
sysfs_attr_init(&zkobj->zko_attr_list[attr_num]);
}
@@ -175,9 +175,9 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
return (ENOMEM);
}
/* this will always have at least one slot for NULL termination */
zkobj->zko_default_attrs = kmem_zalloc(DEFAULT_ATTR_SIZE(attr_cnt),
KM_SLEEP);
if (zkobj->zko_default_attrs == NULL) {
zkobj->zko_default_group.attrs =
kmem_zalloc(DEFAULT_ATTR_SIZE(attr_cnt), KM_SLEEP);
if (zkobj->zko_default_group.attrs == NULL) {
if (zkobj->zko_attr_list != NULL) {
kmem_free(zkobj->zko_attr_list,
ATTR_TABLE_SIZE(attr_cnt));
@@ -185,14 +185,19 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
return (ENOMEM);
}
zkobj->zko_attr_count = attr_cnt;
zkobj->zko_kobj_type.default_attrs = zkobj->zko_default_attrs;
zkobj->zko_default_groups[0] = &zkobj->zko_default_group;
#ifdef HAVE_SYSFS_DEFAULT_GROUPS
zkobj->zko_kobj_type.default_groups = zkobj->zko_default_groups;
#else
zkobj->zko_kobj_type.default_attrs = zkobj->zko_default_group.attrs;
#endif
if (child_cnt > 0) {
zkobj->zko_children = kmem_zalloc(CHILD_TABLE_SIZE(child_cnt),
KM_SLEEP);
if (zkobj->zko_children == NULL) {
if (zkobj->zko_default_attrs != NULL) {
kmem_free(zkobj->zko_default_attrs,
if (zkobj->zko_default_group.attrs != NULL) {
kmem_free(zkobj->zko_default_group.attrs,
DEFAULT_ATTR_SIZE(attr_cnt));
}
if (zkobj->zko_attr_list != NULL) {
@@ -214,9 +219,9 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
static int
zfs_kobj_add(zfs_mod_kobj_t *zkobj, struct kobject *parent, const char *name)
{
/* zko_default_attrs must be NULL terminated */
ASSERT(zkobj->zko_default_attrs != NULL);
ASSERT(zkobj->zko_default_attrs[zkobj->zko_attr_count] == NULL);
/* zko_default_group.attrs must be NULL terminated */
ASSERT(zkobj->zko_default_group.attrs != NULL);
ASSERT(zkobj->zko_default_group.attrs[zkobj->zko_attr_count] == NULL);
kobject_init(&zkobj->zko_kobj, &zkobj->zko_kobj_type);
return (kobject_add(&zkobj->zko_kobj, parent, name));
+2 -2
View File
@@ -248,7 +248,7 @@ zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio)
/* touch each page in this segment. */
p = iov->iov_base + skip;
while (cnt) {
if (get_user(tmp, (uint8_t *)p))
if (copy_from_user(&tmp, p, 1))
return (EFAULT);
ulong_t incr = MIN(cnt, PAGESIZE);
p += incr;
@@ -256,7 +256,7 @@ zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio)
}
/* touch the last byte in case it straddles a page. */
p--;
if (get_user(tmp, (uint8_t *)p))
if (copy_from_user(&tmp, p, 1))
return (EFAULT);
}
}
+4
View File
@@ -3594,7 +3594,11 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
dmu_tx_wait(tx);
dmu_tx_abort(tx);
#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
filemap_dirty_folio(page_mapping(pp), page_folio(pp));
#else
__set_page_dirty_nobuffers(pp);
#endif
ClearPageError(pp);
end_page_writeback(pp);
zfs_rangelock_exit(lr);
+49 -5
View File
@@ -33,9 +33,13 @@
#include <sys/zfs_vfsops.h>
#include <sys/zfs_vnops.h>
#include <sys/zfs_project.h>
#ifdef HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS
#if defined(HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS) || \
defined(HAVE_VFS_FILEMAP_DIRTY_FOLIO)
#include <linux/pagemap.h>
#endif
#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
#include <linux/writeback.h>
#endif
/*
* When using fallocate(2) to preallocate space, inflate the requested
@@ -413,6 +417,8 @@ zpl_aio_write(struct kiocb *kiocb, const struct iovec *iov,
if (ret)
return (ret);
kiocb->ki_pos = pos;
zfs_uio_t uio;
zfs_uio_iovec_init(&uio, iov, nr_segs, kiocb->ki_pos, UIO_USERSPACE,
count, 0);
@@ -629,11 +635,19 @@ zpl_readpage_common(struct page *pp)
return (error);
}
#ifdef HAVE_VFS_READ_FOLIO
static int
zpl_read_folio(struct file *filp, struct folio *folio)
{
return (zpl_readpage_common(&folio->page));
}
#else
static int
zpl_readpage(struct file *filp, struct page *pp)
{
return (zpl_readpage_common(pp));
}
#endif
static int
zpl_readpage_filler(void *data, struct page *pp)
@@ -647,12 +661,29 @@ zpl_readpage_filler(void *data, struct page *pp)
* paging. For simplicity, the code relies on read_cache_pages() to
* correctly lock each page for IO and call zpl_readpage().
*/
#ifdef HAVE_VFS_READPAGES
static int
zpl_readpages(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
return (read_cache_pages(mapping, pages, zpl_readpage_filler, NULL));
}
#else
static void
zpl_readahead(struct readahead_control *ractl)
{
struct page *page;
while ((page = readahead_page(ractl)) != NULL) {
int ret;
ret = zpl_readpage_filler(NULL, page);
put_page(page);
if (ret)
break;
}
}
#endif
static int
zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
@@ -764,11 +795,13 @@ zpl_fallocate_common(struct inode *ip, int mode, loff_t offset, loff_t len)
if (mode & (test_mode)) {
flock64_t bf;
if (offset > olen)
goto out_unmark;
if (mode & FALLOC_FL_KEEP_SIZE) {
if (offset > olen)
goto out_unmark;
if (offset + len > olen)
len = olen - offset;
if (offset + len > olen)
len = olen - offset;
}
bf.l_type = F_WRLCK;
bf.l_whence = SEEK_SET;
bf.l_start = offset;
@@ -1027,14 +1060,25 @@ zpl_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
const struct address_space_operations zpl_address_space_operations = {
#ifdef HAVE_VFS_READPAGES
.readpages = zpl_readpages,
#else
.readahead = zpl_readahead,
#endif
#ifdef HAVE_VFS_READ_FOLIO
.read_folio = zpl_read_folio,
#else
.readpage = zpl_readpage,
#endif
.writepage = zpl_writepage,
.writepages = zpl_writepages,
.direct_IO = zpl_direct_IO,
#ifdef HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS
.set_page_dirty = __set_page_dirty_nobuffers,
#endif
#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
.dirty_folio = filemap_dirty_folio,
#endif
};
const struct file_operations zpl_file_operations = {
+2 -2
View File
@@ -116,14 +116,14 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr)
{
vap->va_mask = ATTR_MODE;
vap->va_mode = mode;
vap->va_uid = crgetfsuid(cr);
vap->va_uid = crgetuid(cr);
if (dir && dir->i_mode & S_ISGID) {
vap->va_gid = KGID_TO_SGID(dir->i_gid);
if (S_ISDIR(mode))
vap->va_mode |= S_ISGID;
} else {
vap->va_gid = crgetfsgid(cr);
vap->va_gid = crgetgid(cr);
}
}
+2 -2
View File
@@ -492,8 +492,8 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
vap->va_mode = xattr_mode;
vap->va_mask = ATTR_MODE;
vap->va_uid = crgetfsuid(cr);
vap->va_gid = crgetfsgid(cr);
vap->va_uid = crgetuid(cr);
vap->va_gid = crgetgid(cr);
error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp,
cr, 0, NULL);

Some files were not shown because too many files have changed in this diff Show More