mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-25 11:47:43 +03:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e25f9131d6 | |||
| 4e49d8ed27 | |||
| a969b1b22c | |||
| 18edf7a3ba | |||
| 33003ecc93 | |||
| 07cc8ae46a | |||
| e202d3b867 | |||
| 3d9f37026d | |||
| fc2c0256c5 | |||
| a69765ea5b | |||
| a164143dfd | |||
| c63b47e4da | |||
| 0e30635f9c | |||
| 777c98ee52 | |||
| 164d184ed9 | |||
| 3da577280a | |||
| 433b9a89c4 | |||
| 374f86b5c9 | |||
| 59f1875639 | |||
| aa7258ced0 | |||
| dedd8243fc | |||
| 43d63ab2d4 | |||
| bd9a9a4e1a | |||
| 5219a2691e | |||
| 48f376b0c5 | |||
| 345f8beb58 | |||
| a5c469c5f3 | |||
| 4b3133e671 | |||
| 4f6e0ca117 | |||
| 1d2aea7711 | |||
| 0a4e41d0fa | |||
| 050be02c02 | |||
| 576d34cb11 | |||
| 6281b5c488 | |||
| 231a37c4c0 | |||
| 9d2e5c14b2 | |||
| b644a45bd4 | |||
| fd0893cf1f | |||
| c8d36e2192 | |||
| edaa250bb3 | |||
| 04a6ae0585 | |||
| eb68e3cd56 | |||
| 2098a00318 | |||
| 82e3117095 | |||
| fce0f7aff4 | |||
| df18a44396 | |||
| 41fb4e071c | |||
| 7043742828 | |||
| aa256549d1 | |||
| 083239575a | |||
| 57159a519b | |||
| 8473829d1f | |||
| e45a981f6d | |||
| 5161e5d8a4 | |||
| 92e0d9d183 | |||
| 232fc23c6e | |||
| 11bdc5c8e8 | |||
| 04b02785b6 | |||
| f22254283a | |||
| 7319a73921 | |||
| 596cfb6b15 | |||
| f806306ce0 | |||
| f33b298346 | |||
| 04fcf13de0 | |||
| 37dbf91c8a | |||
| be697f4339 | |||
| c07a8660f0 | |||
| ea62fb4ab7 | |||
| 5aca6e1092 | |||
| d72e004715 | |||
| 9ef565a185 | |||
| 0e72f5fb83 | |||
| e9897e542d | |||
| 70b1b5bb98 | |||
| a2aabac123 | |||
| 3207803abf | |||
| 6219190d7f | |||
| 24a6d8316a | |||
| e23ed1b330 | |||
| 572114d846 | |||
| 6af8e80310 | |||
| f8a124b104 | |||
| 689c53f2c5 | |||
| 0156253d29 | |||
| 3e0962a236 | |||
| 3c0b8c874b | |||
| b586ea5d93 | |||
| 138d2b29dd | |||
| 5371d8dae7 | |||
| a75af541cf | |||
| 75fbe7eb99 | |||
| d0f350c962 | |||
| 2f2d6bece8 | |||
| fbbc375d43 | |||
| e84a2ed7a8 | |||
| f28c7302cb | |||
| 4767037bcf | |||
| d50ce5c9ec | |||
| 05732da4d1 | |||
| 8f7826f73b |
@@ -0,0 +1,57 @@
|
||||
acl
|
||||
alien
|
||||
attr
|
||||
autoconf
|
||||
bc
|
||||
build-essential
|
||||
curl
|
||||
dbench
|
||||
debhelper-compat
|
||||
dh-python
|
||||
dkms
|
||||
fakeroot
|
||||
fio
|
||||
gdb
|
||||
gdebi
|
||||
git
|
||||
ksh
|
||||
lcov
|
||||
libacl1-dev
|
||||
libaio-dev
|
||||
libattr1-dev
|
||||
libblkid-dev
|
||||
libcurl4-openssl-dev
|
||||
libdevmapper-dev
|
||||
libelf-dev
|
||||
libffi-dev
|
||||
libmount-dev
|
||||
libpam0g-dev
|
||||
libselinux1-dev
|
||||
libssl-dev
|
||||
libtool
|
||||
libudev-dev
|
||||
linux-headers-generic
|
||||
lsscsi
|
||||
mdadm
|
||||
nfs-kernel-server
|
||||
pamtester
|
||||
parted
|
||||
po-debconf
|
||||
python3
|
||||
python3-all-dev
|
||||
python3-cffi
|
||||
python3-dev
|
||||
python3-packaging
|
||||
python3-pip
|
||||
python3-setuptools
|
||||
python3-sphinx
|
||||
rng-tools-debian
|
||||
rsync
|
||||
samba
|
||||
sysstat
|
||||
uuid-dev
|
||||
watchdog
|
||||
wget
|
||||
xfslibs-dev
|
||||
xz-utils
|
||||
zlib1g-dev
|
||||
@@ -0,0 +1,2 @@
|
||||
pax-utils
|
||||
shellcheck
|
||||
@@ -6,20 +6,27 @@ on:
|
||||
|
||||
jobs:
|
||||
checkstyle:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gawk alien fakeroot linux-headers-$(uname -r)
|
||||
sudo apt-get install --yes -qq zlib1g-dev uuid-dev libattr1-dev libblkid-dev libselinux-dev libudev-dev libssl-dev python-dev python-setuptools python-cffi python3 python3-dev python3-setuptools python3-cffi
|
||||
# packages for tests
|
||||
sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
|
||||
sudo apt-get install --yes -qq mandoc cppcheck pax-utils devscripts
|
||||
sudo -E pip --quiet install flake8
|
||||
# https://github.com/orgs/community/discussions/47863
|
||||
sudo apt-mark hold grub-efi-amd64-signed
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get upgrade
|
||||
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq
|
||||
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/checkstyle-dependencies.txt apt-get install -qq
|
||||
sudo python3 -m pip install --quiet flake8
|
||||
sudo apt-get clean
|
||||
|
||||
# confirm that the tools are installed
|
||||
# the build system doesn't fail when they are not
|
||||
flake8 --version
|
||||
scanelf --version
|
||||
shellcheck --version
|
||||
- name: Prepare
|
||||
run: |
|
||||
sh ./autogen.sh
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
# remove 4GiB of images
|
||||
sudo systemd-run docker system prune --force --all --volumes
|
||||
|
||||
# remove unused software
|
||||
sudo systemd-run --wait rm -rf \
|
||||
"$AGENT_TOOLSDIRECTORY" \
|
||||
/opt/* \
|
||||
/usr/local/* \
|
||||
/usr/share/az* \
|
||||
/usr/share/dotnet \
|
||||
/usr/share/gradle* \
|
||||
/usr/share/miniconda \
|
||||
/usr/share/swift \
|
||||
/var/lib/gems \
|
||||
/var/lib/mysql \
|
||||
/var/lib/snapd
|
||||
|
||||
# trim the cleaned space
|
||||
sudo fstrim /
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [18.04, 20.04]
|
||||
os: [20.04, 22.04]
|
||||
runs-on: ubuntu-${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -17,17 +17,12 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
||||
git alien fakeroot wget curl bc fio acl \
|
||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
||||
nfs-kernel-server samba rng-tools xz-utils \
|
||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
||||
python3 python3-dev python3-setuptools python3-cffi python3-packaging \
|
||||
libcurl4-openssl-dev
|
||||
# https://github.com/orgs/community/discussions/47863
|
||||
sudo apt-mark hold grub-efi-amd64-signed
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get upgrade
|
||||
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq
|
||||
sudo apt-get clean
|
||||
- name: Autogen.sh
|
||||
run: |
|
||||
sh autogen.sh
|
||||
@@ -56,12 +51,13 @@ jobs:
|
||||
sudo udevadm control --reload-rules
|
||||
fi
|
||||
fi
|
||||
# Workaround to provide additional free space for testing.
|
||||
# https://github.com/actions/virtual-environments/issues/2840
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf "/usr/local/share/boost"
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
- name: Clear the kernel ring buffer
|
||||
run: |
|
||||
sudo dmesg -c >/var/tmp/dmesg-prerun
|
||||
- name: Reclaim and report disk space
|
||||
run: |
|
||||
${{ github.workspace }}/.github/workflows/scripts/reclaim_disk_space.sh
|
||||
df -h /
|
||||
- name: Tests
|
||||
run: |
|
||||
/usr/share/zfs/zfs-tests.sh -vR -s 3G
|
||||
@@ -71,7 +67,7 @@ jobs:
|
||||
run: |
|
||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
||||
sudo dmesg > $RESULTS_PATH/dmesg
|
||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
||||
sudo cp /var/log/syslog /var/tmp/dmesg-prerun $RESULTS_PATH/
|
||||
sudo chmod +r $RESULTS_PATH/*
|
||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
||||
for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done
|
||||
@@ -79,5 +75,7 @@ jobs:
|
||||
if: failure()
|
||||
with:
|
||||
name: Test logs Ubuntu-${{ matrix.os }}
|
||||
path: /var/tmp/test_results/20*/
|
||||
path: |
|
||||
/var/tmp/test_results/*
|
||||
!/var/tmp/test_results/current
|
||||
if-no-files-found: ignore
|
||||
|
||||
@@ -6,24 +6,19 @@ on:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
||||
git alien fakeroot wget curl bc fio acl \
|
||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
||||
nfs-kernel-server samba rng-tools xz-utils \
|
||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
||||
python3 python3-dev python3-setuptools python3-cffi python3-packaging \
|
||||
libcurl4-openssl-dev
|
||||
# https://github.com/orgs/community/discussions/47863
|
||||
sudo apt-mark hold grub-efi-amd64-signed
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get upgrade
|
||||
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq
|
||||
sudo apt-get clean
|
||||
- name: Autogen.sh
|
||||
run: |
|
||||
sh autogen.sh
|
||||
@@ -52,12 +47,13 @@ jobs:
|
||||
sudo udevadm control --reload-rules
|
||||
fi
|
||||
fi
|
||||
# Workaround to provide additional free space for testing.
|
||||
# https://github.com/actions/virtual-environments/issues/2840
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf "/usr/local/share/boost"
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
- name: Clear the kernel ring buffer
|
||||
run: |
|
||||
sudo dmesg -c >/var/tmp/dmesg-prerun
|
||||
- name: Reclaim and report disk space
|
||||
run: |
|
||||
${{ github.workspace }}/.github/workflows/scripts/reclaim_disk_space.sh
|
||||
df -h /
|
||||
- name: Tests
|
||||
run: |
|
||||
/usr/share/zfs/zfs-tests.sh -vR -s 3G -r sanity
|
||||
@@ -67,13 +63,15 @@ jobs:
|
||||
run: |
|
||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
||||
sudo dmesg > $RESULTS_PATH/dmesg
|
||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
||||
sudo cp /var/log/syslog /var/tmp/dmesg-prerun $RESULTS_PATH/
|
||||
sudo chmod +r $RESULTS_PATH/*
|
||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
||||
for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: Test logs
|
||||
path: /var/tmp/test_results/20*/
|
||||
name: Test logs Ubuntu-${{ matrix.os }}
|
||||
path: |
|
||||
/var/tmp/test_results/*
|
||||
!/var/tmp/test_results/current
|
||||
if-no-files-found: ignore
|
||||
|
||||
+10
-12
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
TEST_DIR: /var/tmp/zloop
|
||||
steps:
|
||||
@@ -15,15 +15,12 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb \
|
||||
git alien fakeroot \
|
||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
||||
libpam0g-dev \
|
||||
python-dev python-setuptools python-cffi python-packaging \
|
||||
python3 python3-dev python3-setuptools python3-cffi python3-packaging
|
||||
# https://github.com/orgs/community/discussions/47863
|
||||
sudo apt-mark hold grub-efi-amd64-signed
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get upgrade
|
||||
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq
|
||||
sudo apt-get clean
|
||||
- name: Autogen.sh
|
||||
run: |
|
||||
sh autogen.sh
|
||||
@@ -44,8 +41,9 @@ jobs:
|
||||
- name: Tests
|
||||
run: |
|
||||
sudo mkdir -p $TEST_DIR
|
||||
# run for 20 minutes to have a total runner time of 30 minutes
|
||||
sudo /usr/share/zfs/zloop.sh -t 1200 -l -m1 -- -T 120 -P 60
|
||||
# run for 10 minutes or at most 2 iterations for a maximum runner
|
||||
# time of 20 minutes.
|
||||
sudo /usr/share/zfs/zloop.sh -t 600 -I 2 -l -m1 -- -T 120 -P 60
|
||||
- name: Prepare artifacts
|
||||
if: failure()
|
||||
run: |
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
|
||||
The [OpenZFS Code of Conduct](https://openzfs.org/wiki/Code_of_Conduct)
|
||||
applies to spaces associated with the OpenZFS project, including GitHub.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 2.1.7
|
||||
Version: 2.1.11
|
||||
Release: 1
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS
|
||||
Linux-Maximum: 6.0
|
||||
Linux-Maximum: 6.2
|
||||
Linux-Minimum: 3.10
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
bin_SCRIPTS = arc_summary
|
||||
|
||||
CLEANFILES = arc_summary
|
||||
EXTRA_DIST = arc_summary2 arc_summary3
|
||||
|
||||
if USING_PYTHON_2
|
||||
SCRIPT = arc_summary2
|
||||
else
|
||||
EXTRA_DIST = arc_summary3
|
||||
SCRIPT = arc_summary3
|
||||
endif
|
||||
|
||||
arc_summary: $(SCRIPT)
|
||||
cp $< $@
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -191,21 +191,13 @@ elif sys.platform.startswith('linux'):
|
||||
# there, so we fall back on modinfo
|
||||
command = ["/sbin/modinfo", request, "-0"]
|
||||
|
||||
# The recommended way to do this is with subprocess.run(). However,
|
||||
# some installed versions of Python are < 3.5, so we offer them
|
||||
# the option of doing it the old way (for now)
|
||||
info = ''
|
||||
|
||||
try:
|
||||
|
||||
if 'run' in dir(subprocess):
|
||||
info = subprocess.run(command, stdout=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
raw_output = info.stdout.split('\0')
|
||||
else:
|
||||
info = subprocess.check_output(command,
|
||||
universal_newlines=True)
|
||||
raw_output = info.split('\0')
|
||||
info = subprocess.run(command, stdout=subprocess.PIPE,
|
||||
check=True, universal_newlines=True)
|
||||
raw_output = info.stdout.split('\0')
|
||||
|
||||
except subprocess.CalledProcessError:
|
||||
print("Error: Descriptions not available",
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
# @hdr is the array of fields that needs to be printed, so we
|
||||
# just iterate over this array and print the values using our pretty printer.
|
||||
#
|
||||
# This script must remain compatible with Python 2.6+ and Python 3.4+.
|
||||
# This script must remain compatible with Python 3.6+.
|
||||
#
|
||||
|
||||
import sys
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# Copyright (C) 2013 Lawrence Livermore National Security, LLC.
|
||||
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
#
|
||||
# This script must remain compatible with Python 2.6+ and Python 3.4+.
|
||||
# This script must remain compatible with and Python 3.6+.
|
||||
#
|
||||
|
||||
import sys
|
||||
|
||||
+40
-16
@@ -80,6 +80,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
char *path = NULL;
|
||||
uint_t c, children;
|
||||
nvlist_t **child;
|
||||
uint64_t vdev_guid;
|
||||
|
||||
/*
|
||||
* First iterate over any children.
|
||||
@@ -100,7 +101,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
|
||||
return (B_TRUE);
|
||||
}
|
||||
}
|
||||
@@ -109,7 +110,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
|
||||
return (B_TRUE);
|
||||
}
|
||||
}
|
||||
@@ -126,6 +127,21 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
&gsp->gs_vdev_expandtime);
|
||||
return (B_TRUE);
|
||||
}
|
||||
/*
|
||||
* Otherwise, on a vdev guid match, grab the devid and expansion
|
||||
* time. The devid might be missing on removal since its not part
|
||||
* of blkid cache and L2ARC VDEV does not contain pool guid in its
|
||||
* blkid, so this is a special case for L2ARC VDEV.
|
||||
*/
|
||||
else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
|
||||
nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
|
||||
gsp->gs_vdev_guid == vdev_guid) {
|
||||
(void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
|
||||
&gsp->gs_devid);
|
||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
|
||||
&gsp->gs_vdev_expandtime);
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
return (B_FALSE);
|
||||
}
|
||||
@@ -148,13 +164,13 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
|
||||
/*
|
||||
* if a match was found then grab the pool guid
|
||||
*/
|
||||
if (gsp->gs_vdev_guid) {
|
||||
if (gsp->gs_vdev_guid && gsp->gs_devid) {
|
||||
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
|
||||
&gsp->gs_pool_guid);
|
||||
}
|
||||
|
||||
zpool_close(zhp);
|
||||
return (gsp->gs_vdev_guid != 0);
|
||||
return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -195,11 +211,13 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||
uint64_t pool_guid = 0, vdev_guid = 0;
|
||||
guid_search_t search = { 0 };
|
||||
device_type_t devtype = DEVICE_TYPE_PRIMARY;
|
||||
char *devid = NULL;
|
||||
|
||||
class = "resource.fs.zfs.removed";
|
||||
subclass = "";
|
||||
|
||||
(void) nvlist_add_string(payload, FM_CLASS, class);
|
||||
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid);
|
||||
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
|
||||
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
|
||||
|
||||
@@ -209,20 +227,24 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
||||
|
||||
/*
|
||||
* If devid is missing but vdev_guid is available, find devid
|
||||
* and pool_guid from vdev_guid.
|
||||
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
|
||||
* ZFS_EV_POOL_GUID may be missing so find them.
|
||||
*/
|
||||
if (pool_guid == 0 || vdev_guid == 0) {
|
||||
if ((nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
||||
&search.gs_devid) == 0) &&
|
||||
(zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search)
|
||||
== 1)) {
|
||||
if (pool_guid == 0)
|
||||
pool_guid = search.gs_pool_guid;
|
||||
if (vdev_guid == 0)
|
||||
vdev_guid = search.gs_vdev_guid;
|
||||
devtype = search.gs_vdev_type;
|
||||
}
|
||||
if (devid == NULL || pool_guid == 0 || vdev_guid == 0) {
|
||||
if (devid == NULL)
|
||||
search.gs_vdev_guid = vdev_guid;
|
||||
else
|
||||
search.gs_devid = devid;
|
||||
zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
|
||||
if (devid == NULL)
|
||||
devid = search.gs_devid;
|
||||
if (pool_guid == 0)
|
||||
pool_guid = search.gs_pool_guid;
|
||||
if (vdev_guid == 0)
|
||||
vdev_guid = search.gs_vdev_guid;
|
||||
devtype = search.gs_vdev_type;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -235,7 +257,9 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||
search.gs_vdev_expandtime + 10 > tv.tv_sec) {
|
||||
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
|
||||
"for recently expanded device '%s'", EC_DEV_REMOVE,
|
||||
search.gs_devid);
|
||||
devid);
|
||||
fnvlist_free(payload);
|
||||
free(event);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
+36
-11
@@ -185,10 +185,12 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
uint64_t wholedisk = 0ULL;
|
||||
uint64_t offline = 0ULL, faulted = 0ULL;
|
||||
uint64_t guid = 0ULL;
|
||||
uint64_t is_spare = 0;
|
||||
char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
|
||||
char rawpath[PATH_MAX], fullpath[PATH_MAX];
|
||||
char devpath[PATH_MAX];
|
||||
int ret;
|
||||
int online_flag = ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE;
|
||||
boolean_t is_sd = B_FALSE;
|
||||
boolean_t is_mpath_wholedisk = B_FALSE;
|
||||
uint_t c;
|
||||
@@ -214,6 +216,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_FAULTED, &faulted);
|
||||
|
||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid);
|
||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_IS_SPARE, &is_spare);
|
||||
|
||||
/*
|
||||
* Special case:
|
||||
@@ -304,11 +307,13 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
}
|
||||
}
|
||||
|
||||
if (is_spare)
|
||||
online_flag |= ZFS_ONLINE_SPARE;
|
||||
|
||||
/*
|
||||
* Attempt to online the device.
|
||||
*/
|
||||
if (zpool_vdev_online(zhp, fullpath,
|
||||
ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, &newstate) == 0 &&
|
||||
if (zpool_vdev_online(zhp, fullpath, online_flag, &newstate) == 0 &&
|
||||
(newstate == VDEV_STATE_HEALTHY ||
|
||||
newstate == VDEV_STATE_DEGRADED)) {
|
||||
zed_log_msg(LOG_INFO,
|
||||
@@ -525,7 +530,9 @@ typedef struct dev_data {
|
||||
boolean_t dd_islabeled;
|
||||
uint64_t dd_pool_guid;
|
||||
uint64_t dd_vdev_guid;
|
||||
uint64_t dd_new_vdev_guid;
|
||||
const char *dd_new_devid;
|
||||
uint64_t dd_num_spares;
|
||||
} dev_data_t;
|
||||
|
||||
static void
|
||||
@@ -535,6 +542,8 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
char *path = NULL;
|
||||
uint_t c, children;
|
||||
nvlist_t **child;
|
||||
uint64_t guid = 0;
|
||||
uint64_t isspare = 0;
|
||||
|
||||
/*
|
||||
* First iterate over any children.
|
||||
@@ -560,19 +569,16 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
}
|
||||
|
||||
/* once a vdev was matched and processed there is nothing left to do */
|
||||
if (dp->dd_found)
|
||||
if (dp->dd_found && dp->dd_num_spares == 0)
|
||||
return;
|
||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid);
|
||||
|
||||
/*
|
||||
* Match by GUID if available otherwise fallback to devid or physical
|
||||
*/
|
||||
if (dp->dd_vdev_guid != 0) {
|
||||
uint64_t guid;
|
||||
|
||||
if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
|
||||
&guid) != 0 || guid != dp->dd_vdev_guid) {
|
||||
if (guid != dp->dd_vdev_guid)
|
||||
return;
|
||||
}
|
||||
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid);
|
||||
dp->dd_found = B_TRUE;
|
||||
|
||||
@@ -582,6 +588,12 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
* illumos, substring matching is not required to accommodate
|
||||
* the partition suffix. An exact match will be present in
|
||||
* the dp->dd_compare value.
|
||||
* If the attached disk already contains a vdev GUID, it means
|
||||
* the disk is not clean. In such a scenario, the physical path
|
||||
* would be a match that makes the disk faulted when trying to
|
||||
* online it. So, we would only want to proceed if either GUID
|
||||
* matches with the last attached disk or the disk is in clean
|
||||
* state.
|
||||
*/
|
||||
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
|
||||
strcmp(dp->dd_compare, path) != 0) {
|
||||
@@ -589,6 +601,12 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
__func__, dp->dd_compare, path);
|
||||
return;
|
||||
}
|
||||
if (dp->dd_new_vdev_guid != 0 && dp->dd_new_vdev_guid != guid) {
|
||||
zed_log_msg(LOG_INFO, " %s: no match (GUID:%llu"
|
||||
" != vdev GUID:%llu)", __func__,
|
||||
dp->dd_new_vdev_guid, guid);
|
||||
return;
|
||||
}
|
||||
|
||||
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched %s on %s",
|
||||
dp->dd_prop, path);
|
||||
@@ -601,6 +619,10 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
if (dp->dd_found == B_TRUE && nvlist_lookup_uint64(nvl,
|
||||
ZPOOL_CONFIG_IS_SPARE, &isspare) == 0 && isspare)
|
||||
dp->dd_num_spares++;
|
||||
|
||||
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
||||
}
|
||||
|
||||
@@ -661,7 +683,9 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
|
||||
}
|
||||
|
||||
zpool_close(zhp);
|
||||
return (dp->dd_found); /* cease iteration after a match */
|
||||
|
||||
/* cease iteration after a match */
|
||||
return (dp->dd_found && dp->dd_num_spares == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -670,7 +694,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
|
||||
*/
|
||||
static boolean_t
|
||||
devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
|
||||
boolean_t is_slice)
|
||||
boolean_t is_slice, uint64_t new_vdev_guid)
|
||||
{
|
||||
dev_data_t data = { 0 };
|
||||
|
||||
@@ -680,6 +704,7 @@ devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
|
||||
data.dd_found = B_FALSE;
|
||||
data.dd_islabeled = is_slice;
|
||||
data.dd_new_devid = devid; /* used by auto replace code */
|
||||
data.dd_new_vdev_guid = new_vdev_guid;
|
||||
|
||||
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
|
||||
|
||||
@@ -848,7 +873,7 @@ zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
|
||||
if (devid_iter(devid, zfs_process_add, is_slice))
|
||||
return (0);
|
||||
if (devpath != NULL && devphys_iter(devpath, devid, zfs_process_add,
|
||||
is_slice))
|
||||
is_slice, vdev_guid))
|
||||
return (0);
|
||||
if (vdev_guid != 0)
|
||||
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,
|
||||
|
||||
+105
-10
@@ -75,6 +75,8 @@ typedef struct find_cbdata {
|
||||
uint64_t cb_guid;
|
||||
zpool_handle_t *cb_zhp;
|
||||
nvlist_t *cb_vdev;
|
||||
uint64_t cb_vdev_guid;
|
||||
uint64_t cb_num_spares;
|
||||
} find_cbdata_t;
|
||||
|
||||
static int
|
||||
@@ -140,6 +142,64 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
remove_spares(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
nvlist_t *config, *nvroot;
|
||||
nvlist_t **spares;
|
||||
uint_t nspares;
|
||||
char *devname;
|
||||
find_cbdata_t *cbp = data;
|
||||
uint64_t spareguid = 0;
|
||||
vdev_stat_t *vs;
|
||||
unsigned int c;
|
||||
|
||||
config = zpool_get_config(zhp, NULL);
|
||||
if (nvlist_lookup_nvlist(config,
|
||||
ZPOOL_CONFIG_VDEV_TREE, &nvroot) != 0) {
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
||||
&spares, &nspares) != 0) {
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nspares; i++) {
|
||||
if (nvlist_lookup_uint64(spares[i], ZPOOL_CONFIG_GUID,
|
||||
&spareguid) == 0 && spareguid == cbp->cb_vdev_guid) {
|
||||
devname = zpool_vdev_name(NULL, zhp, spares[i],
|
||||
B_FALSE);
|
||||
nvlist_lookup_uint64_array(spares[i],
|
||||
ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c);
|
||||
if (vs->vs_state != VDEV_STATE_REMOVED &&
|
||||
zpool_vdev_remove_wanted(zhp, devname) == 0)
|
||||
cbp->cb_num_spares++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a vdev guid, find and remove all spares associated with it.
|
||||
*/
|
||||
static int
|
||||
find_and_remove_spares(libzfs_handle_t *zhdl, uint64_t vdev_guid)
|
||||
{
|
||||
find_cbdata_t cb;
|
||||
|
||||
cb.cb_num_spares = 0;
|
||||
cb.cb_vdev_guid = vdev_guid;
|
||||
zpool_iter(zhdl, remove_spares, &cb);
|
||||
|
||||
return (cb.cb_num_spares);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a (pool, vdev) GUID pair, find the matching pool and vdev.
|
||||
*/
|
||||
@@ -315,6 +375,8 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
libzfs_handle_t *zhdl = zdp->zrd_hdl;
|
||||
boolean_t fault_device, degrade_device;
|
||||
boolean_t is_repair;
|
||||
boolean_t l2arc = B_FALSE;
|
||||
boolean_t spare = B_FALSE;
|
||||
char *scheme;
|
||||
nvlist_t *vdev = NULL;
|
||||
char *uuid;
|
||||
@@ -323,6 +385,8 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
boolean_t is_disk;
|
||||
vdev_aux_t aux;
|
||||
uint64_t state = 0;
|
||||
vdev_stat_t *vs;
|
||||
unsigned int c;
|
||||
|
||||
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
|
||||
|
||||
@@ -339,10 +403,26 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
char *devtype;
|
||||
char *devname;
|
||||
|
||||
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
||||
&devtype) == 0) {
|
||||
if (strcmp(devtype, VDEV_TYPE_SPARE) == 0)
|
||||
spare = B_TRUE;
|
||||
else if (strcmp(devtype, VDEV_TYPE_L2CACHE) == 0)
|
||||
l2arc = B_TRUE;
|
||||
}
|
||||
|
||||
if (nvlist_lookup_uint64(nvl,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
||||
return;
|
||||
|
||||
if (spare) {
|
||||
int nspares = find_and_remove_spares(zhdl, vdev_guid);
|
||||
fmd_hdl_debug(hdl, "%d spares removed", nspares);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
|
||||
&pool_guid) != 0 ||
|
||||
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
|
||||
&vdev_guid) != 0)
|
||||
&pool_guid) != 0)
|
||||
return;
|
||||
|
||||
if ((zhp = find_by_guid(zhdl, pool_guid, vdev_guid,
|
||||
@@ -351,13 +431,28 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
|
||||
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
|
||||
|
||||
/* Can't replace l2arc with a spare: offline the device */
|
||||
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
||||
&devtype) == 0 && strcmp(devtype, VDEV_TYPE_L2CACHE) == 0) {
|
||||
fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
|
||||
zpool_vdev_offline(zhp, devname, B_TRUE);
|
||||
} else if (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
|
||||
replace_with_spare(hdl, zhp, vdev) == B_FALSE) {
|
||||
nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
|
||||
(uint64_t **)&vs, &c);
|
||||
|
||||
/*
|
||||
* If state removed is requested for already removed vdev,
|
||||
* its a loopback event from spa_async_remove(). Just
|
||||
* ignore it.
|
||||
*/
|
||||
if (vs->vs_state == VDEV_STATE_REMOVED &&
|
||||
state == VDEV_STATE_REMOVED)
|
||||
return;
|
||||
|
||||
/* Remove the vdev since device is unplugged */
|
||||
if (l2arc || (strcmp(class, "resource.fs.zfs.removed") == 0)) {
|
||||
int status = zpool_vdev_remove_wanted(zhp, devname);
|
||||
fmd_hdl_debug(hdl, "zpool_vdev_remove_wanted '%s'"
|
||||
", ret:%d", devname, status);
|
||||
}
|
||||
|
||||
/* Replace the vdev with a spare if its not a l2arc */
|
||||
if (!l2arc && (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
|
||||
replace_with_spare(hdl, zhp, vdev) == B_FALSE)) {
|
||||
/* Could not handle with spare */
|
||||
fmd_hdl_debug(hdl, "no spare for '%s'", devname);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ if [ "${ZEVENT_VDEV_STATE_STR}" != "FAULTED" ] \
|
||||
fi
|
||||
|
||||
umask 077
|
||||
note_subject="ZFS device fault for pool ${ZEVENT_POOL_GUID} on $(hostname)"
|
||||
note_subject="ZFS device fault for pool ${ZEVENT_POOL} on $(hostname)"
|
||||
note_pathname="$(mktemp)"
|
||||
{
|
||||
if [ "${ZEVENT_VDEV_STATE_STR}" = "FAULTED" ] ; then
|
||||
@@ -65,7 +65,7 @@ note_pathname="$(mktemp)"
|
||||
[ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}"
|
||||
[ -n "${ZEVENT_VDEV_DEVID}" ] && echo " devid: ${ZEVENT_VDEV_DEVID}"
|
||||
|
||||
echo " pool: ${ZEVENT_POOL_GUID}"
|
||||
echo " pool: ${ZEVENT_POOL} (${ZEVENT_POOL_GUID})"
|
||||
|
||||
} > "${note_pathname}"
|
||||
|
||||
|
||||
+56
-7
@@ -315,14 +315,14 @@ get_usage(zfs_help_t idx)
|
||||
case HELP_ROLLBACK:
|
||||
return (gettext("\trollback [-rRf] <snapshot>\n"));
|
||||
case HELP_SEND:
|
||||
return (gettext("\tsend [-DnPpRvLecwhb] [-[i|I] snapshot] "
|
||||
return (gettext("\tsend [-DnPpRVvLecwhb] [-[i|I] snapshot] "
|
||||
"<snapshot>\n"
|
||||
"\tsend [-DnvPLecw] [-i snapshot|bookmark] "
|
||||
"\tsend [-DnVvPLecw] [-i snapshot|bookmark] "
|
||||
"<filesystem|volume|snapshot>\n"
|
||||
"\tsend [-DnPpvLec] [-i bookmark|snapshot] "
|
||||
"\tsend [-DnPpVvLec] [-i bookmark|snapshot] "
|
||||
"--redact <bookmark> <snapshot>\n"
|
||||
"\tsend [-nvPe] -t <receive_resume_token>\n"
|
||||
"\tsend [-Pnv] --saved filesystem\n"));
|
||||
"\tsend [-nVvPe] -t <receive_resume_token>\n"
|
||||
"\tsend [-PnVv] --saved filesystem\n"));
|
||||
case HELP_SET:
|
||||
return (gettext("\tset <property=value> ... "
|
||||
"<filesystem|volume|snapshot> ...\n"));
|
||||
@@ -3474,6 +3474,8 @@ print_header(list_cbdata_t *cb)
|
||||
boolean_t first = B_TRUE;
|
||||
boolean_t right_justify;
|
||||
|
||||
color_start(ANSI_BOLD);
|
||||
|
||||
for (; pl != NULL; pl = pl->pl_next) {
|
||||
if (!first) {
|
||||
(void) printf(" ");
|
||||
@@ -3500,9 +3502,31 @@ print_header(list_cbdata_t *cb)
|
||||
(void) printf("%-*s", (int)pl->pl_width, header);
|
||||
}
|
||||
|
||||
color_end();
|
||||
|
||||
(void) printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Decides on the color that the avail value should be printed in.
|
||||
* > 80% used = yellow
|
||||
* > 90% used = red
|
||||
*/
|
||||
static const char *
|
||||
zfs_list_avail_color(zfs_handle_t *zhp)
|
||||
{
|
||||
uint64_t used = zfs_prop_get_int(zhp, ZFS_PROP_USED);
|
||||
uint64_t avail = zfs_prop_get_int(zhp, ZFS_PROP_AVAILABLE);
|
||||
int percentage = (int)((double)avail / MAX(avail + used, 1) * 100);
|
||||
|
||||
if (percentage > 20)
|
||||
return (NULL);
|
||||
else if (percentage > 10)
|
||||
return (ANSI_YELLOW);
|
||||
else
|
||||
return (ANSI_RED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a dataset and a list of fields, print out all the properties according
|
||||
* to the described layout.
|
||||
@@ -3565,6 +3589,22 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
|
||||
right_justify = B_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* zfs_list_avail_color() needs ZFS_PROP_AVAILABLE + USED
|
||||
* - so we need another for() search for the USED part
|
||||
* - when no colors wanted, we can skip the whole thing
|
||||
*/
|
||||
if (use_color() && pl->pl_prop == ZFS_PROP_AVAILABLE) {
|
||||
zprop_list_t *pl2 = cb->cb_proplist;
|
||||
for (; pl2 != NULL; pl2 = pl2->pl_next) {
|
||||
if (pl2->pl_prop == ZFS_PROP_USED) {
|
||||
color_start(zfs_list_avail_color(zhp));
|
||||
/* found it, no need for more loops */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is being called in scripted mode, or if this is the
|
||||
* last column and it is left-justified, don't include a width
|
||||
@@ -3576,6 +3616,9 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
|
||||
(void) printf("%*s", (int)pl->pl_width, propstr);
|
||||
else
|
||||
(void) printf("%-*s", (int)pl->pl_width, propstr);
|
||||
|
||||
if (pl->pl_prop == ZFS_PROP_AVAILABLE)
|
||||
color_end();
|
||||
}
|
||||
|
||||
(void) printf("\n");
|
||||
@@ -4407,6 +4450,7 @@ zfs_do_send(int argc, char **argv)
|
||||
{"props", no_argument, NULL, 'p'},
|
||||
{"parsable", no_argument, NULL, 'P'},
|
||||
{"dedup", no_argument, NULL, 'D'},
|
||||
{"proctitle", no_argument, NULL, 'V'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{"dryrun", no_argument, NULL, 'n'},
|
||||
{"large-block", no_argument, NULL, 'L'},
|
||||
@@ -4421,7 +4465,7 @@ zfs_do_send(int argc, char **argv)
|
||||
};
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt_long(argc, argv, ":i:I:RsDpvnPLeht:cwbd:S",
|
||||
while ((c = getopt_long(argc, argv, ":i:I:RsDpVvnPLeht:cwbd:S",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
@@ -4456,6 +4500,9 @@ zfs_do_send(int argc, char **argv)
|
||||
case 'P':
|
||||
flags.parsable = B_TRUE;
|
||||
break;
|
||||
case 'V':
|
||||
flags.progressastitle = B_TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
flags.verbosity++;
|
||||
flags.progress = B_TRUE;
|
||||
@@ -4531,7 +4578,7 @@ zfs_do_send(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (flags.parsable && flags.verbosity == 0)
|
||||
if ((flags.parsable || flags.progressastitle) && flags.verbosity == 0)
|
||||
flags.verbosity = 1;
|
||||
|
||||
argc -= optind;
|
||||
@@ -8693,6 +8740,8 @@ main(int argc, char **argv)
|
||||
|
||||
libzfs_print_on_error(g_zfs, B_TRUE);
|
||||
|
||||
zfs_setproctitle_init(argc, argv, environ);
|
||||
|
||||
/*
|
||||
* Many commands modify input strings for string parsing reasons.
|
||||
* We create a copy to protect the original argv.
|
||||
|
||||
+43
-2
@@ -4205,6 +4205,8 @@ print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
|
||||
unsigned int namewidth;
|
||||
const char *title;
|
||||
|
||||
color_start(ANSI_BOLD);
|
||||
|
||||
if (cb->cb_flags & IOS_ANYHISTO_M) {
|
||||
title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
|
||||
} else if (cb->cb_vdev_names_count) {
|
||||
@@ -4238,6 +4240,8 @@ print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
|
||||
if (cb->vcdl != NULL)
|
||||
print_cmd_columns(cb->vcdl, 1);
|
||||
|
||||
color_end();
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -4247,6 +4251,37 @@ print_iostat_header(iostat_cbdata_t *cb)
|
||||
print_iostat_header_impl(cb, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints a size string (i.e. 120M) with the suffix ("M") colored
|
||||
* by order of magnitude. Uses column_size to add padding.
|
||||
*/
|
||||
static void
|
||||
print_stat_color(const char *statbuf, unsigned int column_size)
|
||||
{
|
||||
fputs(" ", stdout);
|
||||
size_t len = strlen(statbuf);
|
||||
while (len < column_size) {
|
||||
fputc(' ', stdout);
|
||||
column_size--;
|
||||
}
|
||||
if (*statbuf == '0') {
|
||||
color_start(ANSI_GRAY);
|
||||
fputc('0', stdout);
|
||||
} else {
|
||||
for (; *statbuf; statbuf++) {
|
||||
if (*statbuf == 'K') color_start(ANSI_GREEN);
|
||||
else if (*statbuf == 'M') color_start(ANSI_YELLOW);
|
||||
else if (*statbuf == 'G') color_start(ANSI_RED);
|
||||
else if (*statbuf == 'T') color_start(ANSI_BOLD_BLUE);
|
||||
else if (*statbuf == 'P') color_start(ANSI_MAGENTA);
|
||||
else if (*statbuf == 'E') color_start(ANSI_CYAN);
|
||||
fputc(*statbuf, stdout);
|
||||
if (--column_size <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
color_end();
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a single statistic.
|
||||
@@ -4262,7 +4297,7 @@ print_one_stat(uint64_t value, enum zfs_nicenum_format format,
|
||||
if (scripted)
|
||||
printf("\t%s", buf);
|
||||
else
|
||||
printf(" %*s", column_size, buf);
|
||||
print_stat_color(buf, column_size);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5414,7 +5449,13 @@ print_zpool_dir_scripts(char *dirpath)
|
||||
if ((dir = opendir(dirpath)) != NULL) {
|
||||
/* print all the files and directories within directory */
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
sprintf(fullpath, "%s/%s", dirpath, ent->d_name);
|
||||
if (snprintf(fullpath, sizeof (fullpath), "%s/%s",
|
||||
dirpath, ent->d_name) >= sizeof (fullpath)) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("internal error: "
|
||||
"ZPOOL_SCRIPTS_PATH too large.\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Print the scripts */
|
||||
if (stat(fullpath, &dir_stat) == 0)
|
||||
|
||||
+1
-1
@@ -1184,7 +1184,7 @@ ztest_kill(ztest_shared_t *zs)
|
||||
* See comment above spa_write_cachefile().
|
||||
*/
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE);
|
||||
spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE, B_FALSE);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
||||
(void) kill(getpid(), SIGKILL);
|
||||
|
||||
+6
-19
@@ -1,7 +1,6 @@
|
||||
dnl #
|
||||
dnl # The majority of the python scripts are written to be compatible
|
||||
dnl # with Python 2.6 and Python 3.4. Therefore, they may be installed
|
||||
dnl # and used with either interpreter. This option is intended to
|
||||
dnl # with Python 3.6. This option is intended to
|
||||
dnl # to provide a method to specify the default system version, and
|
||||
dnl # set the PYTHON environment variable accordingly.
|
||||
dnl #
|
||||
@@ -13,9 +12,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
|
||||
[with_python=check])
|
||||
|
||||
AS_CASE([$with_python],
|
||||
[check], [AC_CHECK_PROGS([PYTHON], [python3 python2], [:])],
|
||||
[2*], [PYTHON="python${with_python}"],
|
||||
[*python2*], [PYTHON="${with_python}"],
|
||||
[check], [AC_CHECK_PROGS([PYTHON], [python3], [:])],
|
||||
[3*], [PYTHON="python${with_python}"],
|
||||
[*python3*], [PYTHON="${with_python}"],
|
||||
[no], [PYTHON=":"],
|
||||
@@ -23,8 +20,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
|
||||
)
|
||||
|
||||
dnl #
|
||||
dnl # Minimum supported Python versions for utilities:
|
||||
dnl # Python 2.6 or Python 3.4
|
||||
dnl # Minimum supported Python versions for utilities: Python 3.6
|
||||
dnl #
|
||||
AM_PATH_PYTHON([], [], [:])
|
||||
AS_IF([test -z "$PYTHON_VERSION"], [
|
||||
@@ -33,25 +29,16 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
|
||||
PYTHON_MINOR=${PYTHON_VERSION#*\.}
|
||||
|
||||
AS_CASE([$PYTHON_VERSION],
|
||||
[2.*], [
|
||||
AS_IF([test $PYTHON_MINOR -lt 6],
|
||||
[AC_MSG_ERROR("Python >= 2.6 is required")])
|
||||
],
|
||||
[3.*], [
|
||||
AS_IF([test $PYTHON_MINOR -lt 4],
|
||||
[AC_MSG_ERROR("Python >= 3.4 is required")])
|
||||
AS_IF([test $PYTHON_MINOR -lt 6],
|
||||
[AC_MSG_ERROR("Python >= 3.6 is required")])
|
||||
],
|
||||
[:|2|3], [],
|
||||
[PYTHON_VERSION=3]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([USING_PYTHON], [test "$PYTHON" != :])
|
||||
AM_CONDITIONAL([USING_PYTHON_2], [test "x${PYTHON_VERSION%%\.*}" = x2])
|
||||
AM_CONDITIONAL([USING_PYTHON_3], [test "x${PYTHON_VERSION%%\.*}" = x3])
|
||||
|
||||
AM_COND_IF([USING_PYTHON_2],
|
||||
[AC_SUBST([PYTHON_SHEBANG], [python2])],
|
||||
[AC_SUBST([PYTHON_SHEBANG], [python3])])
|
||||
AC_SUBST([PYTHON_SHEBANG], [python3])
|
||||
|
||||
dnl #
|
||||
dnl # Request that packages be built for a specific Python version.
|
||||
|
||||
@@ -18,7 +18,7 @@ AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Determines if pyzfs can be built, requires Python 2.7 or later.
|
||||
dnl # Determines if pyzfs can be built, requires Python 3.6 or later.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
AC_ARG_ENABLE([pyzfs],
|
||||
@@ -72,12 +72,11 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Require python-devel libraries
|
||||
dnl # Require python3-devel libraries
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
|
||||
AS_CASE([$PYTHON_VERSION],
|
||||
[3.*], [PYTHON_REQUIRED_VERSION=">= '3.4.0'"],
|
||||
[2.*], [PYTHON_REQUIRED_VERSION=">= '2.7.0'"],
|
||||
[3.*], [PYTHON_REQUIRED_VERSION=">= '3.6.0'"],
|
||||
[AC_MSG_ERROR("Python $PYTHON_VERSION unknown")]
|
||||
)
|
||||
|
||||
|
||||
+35
-36
@@ -97,23 +97,13 @@ AC_DEFUN([AX_PYTHON_DEVEL],[
|
||||
# Check for a version of Python >= 2.1.0
|
||||
#
|
||||
AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
|
||||
ac_supports_python_ver=`cat<<EOD | $PYTHON -
|
||||
from __future__ import print_function;
|
||||
import sys;
|
||||
try:
|
||||
from packaging import version;
|
||||
except ImportError:
|
||||
from distlib import version;
|
||||
ver = sys.version.split ()[[0]];
|
||||
(tst_cmp, tst_ver) = ">= '2.1.0'".split ();
|
||||
tst_ver = tst_ver.strip ("'");
|
||||
eval ("print (version.LegacyVersion (ver)"+ tst_cmp +"version.LegacyVersion (tst_ver))")
|
||||
EOD`
|
||||
ac_supports_python_ver=`$PYTHON -c "import sys; \
|
||||
ver = sys.version.split ()[[0]]; \
|
||||
print (ver >= '2.1.0')"`
|
||||
if test "$ac_supports_python_ver" != "True"; then
|
||||
if test -z "$PYTHON_NOVERSIONCHECK"; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_FAILURE([
|
||||
AC_MSG_FAILURE([
|
||||
This version of the AC@&t@_PYTHON_DEVEL macro
|
||||
doesn't work properly with versions of Python before
|
||||
2.1.0. You may need to re-run configure, setting the
|
||||
@@ -122,7 +112,6 @@ PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
|
||||
Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
|
||||
to something else than an empty string.
|
||||
])
|
||||
])
|
||||
else
|
||||
AC_MSG_RESULT([skip at user request])
|
||||
fi
|
||||
@@ -131,37 +120,47 @@ to something else than an empty string.
|
||||
fi
|
||||
|
||||
#
|
||||
# if the macro parameter ``version'' is set, honour it
|
||||
# If the macro parameter ``version'' is set, honour it.
|
||||
# A Python shim class, VPy, is used to implement correct version comparisons via
|
||||
# string expressions, since e.g. a naive textual ">= 2.7.3" won't work for
|
||||
# Python 2.7.10 (the ".1" being evaluated as less than ".3").
|
||||
#
|
||||
if test -n "$1"; then
|
||||
AC_MSG_CHECKING([for a version of Python $1])
|
||||
# Why the strip ()? Because if we don't, version.parse
|
||||
# will, for example, report 3.10.0 >= '3.11.0'
|
||||
ac_supports_python_ver=`cat<<EOD | $PYTHON -
|
||||
|
||||
from __future__ import print_function;
|
||||
import sys;
|
||||
try:
|
||||
from packaging import version;
|
||||
except ImportError:
|
||||
from distlib import version;
|
||||
ver = sys.version.split ()[[0]];
|
||||
(tst_cmp, tst_ver) = "$1".split ();
|
||||
tst_ver = tst_ver.strip ("'");
|
||||
eval ("print (version.LegacyVersion (ver)"+ tst_cmp +"version.LegacyVersion (tst_ver))")
|
||||
EOD`
|
||||
cat << EOF > ax_python_devel_vpy.py
|
||||
class VPy:
|
||||
def vtup(self, s):
|
||||
return tuple(map(int, s.strip().replace("rc", ".").split(".")))
|
||||
def __init__(self):
|
||||
import sys
|
||||
self.vpy = tuple(sys.version_info)
|
||||
def __eq__(self, s):
|
||||
return self.vpy == self.vtup(s)
|
||||
def __ne__(self, s):
|
||||
return self.vpy != self.vtup(s)
|
||||
def __lt__(self, s):
|
||||
return self.vpy < self.vtup(s)
|
||||
def __gt__(self, s):
|
||||
return self.vpy > self.vtup(s)
|
||||
def __le__(self, s):
|
||||
return self.vpy <= self.vtup(s)
|
||||
def __ge__(self, s):
|
||||
return self.vpy >= self.vtup(s)
|
||||
EOF
|
||||
ac_supports_python_ver=`$PYTHON -c "import ax_python_devel_vpy; \
|
||||
ver = ax_python_devel_vpy.VPy(); \
|
||||
print (ver $1)"`
|
||||
rm -rf ax_python_devel_vpy*.py* __pycache__/ax_python_devel_vpy*.py*
|
||||
if test "$ac_supports_python_ver" = "True"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_ERROR([this package requires Python $1.
|
||||
AC_MSG_ERROR([this package requires Python $1.
|
||||
If you have it installed, but it isn't the default Python
|
||||
interpreter in your system path, please pass the PYTHON_VERSION
|
||||
variable to configure. See ``configure --help'' for reference.
|
||||
])
|
||||
PYTHON_VERSION=""
|
||||
])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
+2
-2
@@ -66,7 +66,7 @@ deb-utils: deb-local rpm-utils-initramfs
|
||||
## to do this, so we install a shim onto the path which calls the real
|
||||
## dh_shlibdeps with the required arguments.
|
||||
path_prepend=`mktemp -d /tmp/intercept.XXXXXX`; \
|
||||
echo "#$(SHELL)" > $${path_prepend}/dh_shlibdeps; \
|
||||
echo "#!$(SHELL)" > $${path_prepend}/dh_shlibdeps; \
|
||||
echo "`which dh_shlibdeps` -- \
|
||||
-xlibuutil3linux -xlibnvpair3linux -xlibzfs5linux -xlibzpool5linux" \
|
||||
>> $${path_prepend}/dh_shlibdeps; \
|
||||
@@ -74,7 +74,7 @@ deb-utils: deb-local rpm-utils-initramfs
|
||||
## Debianized packages from the auto-generated dependencies of the new debs,
|
||||
## which should NOT be mixed with the alien-generated debs created here
|
||||
chmod +x $${path_prepend}/dh_shlibdeps; \
|
||||
env PATH=$${path_prepend}:$${PATH} \
|
||||
env "PATH=$${path_prepend}:$${PATH}" \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch \
|
||||
$$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
|
||||
$$pkg8 $$pkg9 $$pkg10 || exit 1; \
|
||||
|
||||
+46
-4
@@ -165,6 +165,9 @@ dnl #
|
||||
dnl # 5.15 API change,
|
||||
dnl # Added the bool rcu argument to get_acl for rcu path walk.
|
||||
dnl #
|
||||
dnl # 6.2 API change,
|
||||
dnl # get_acl() was renamed to get_inode_acl()
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
|
||||
#include <linux/fs.h>
|
||||
@@ -189,6 +192,18 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
|
||||
.get_acl = get_acl_fn,
|
||||
};
|
||||
],[])
|
||||
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_get_inode_acl], [
|
||||
#include <linux/fs.h>
|
||||
|
||||
struct posix_acl *get_inode_acl_fn(struct inode *inode, int type,
|
||||
bool rcu) { return NULL; }
|
||||
|
||||
static const struct inode_operations
|
||||
iops __attribute__ ((unused)) = {
|
||||
.get_inode_acl = get_inode_acl_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
|
||||
@@ -201,7 +216,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_GET_ACL_RCU, 1, [iops->get_acl() takes rcu])
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([iops->get_acl()])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_get_inode_acl], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_GET_INODE_ACL, 1, [has iops->get_inode_acl()])
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([iops->get_acl() or iops->get_inode_acl()])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
@@ -213,7 +233,22 @@ dnl #
|
||||
dnl # 5.12 API change,
|
||||
dnl # set_acl() added a user_namespace* parameter first
|
||||
dnl #
|
||||
dnl # 6.2 API change,
|
||||
dnl # set_acl() second paramter changed to a struct dentry *
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns_dentry], [
|
||||
#include <linux/fs.h>
|
||||
|
||||
int set_acl_fn(struct user_namespace *userns,
|
||||
struct dentry *dent, struct posix_acl *acl,
|
||||
int type) { return 0; }
|
||||
|
||||
static const struct inode_operations
|
||||
iops __attribute__ ((unused)) = {
|
||||
.set_acl = set_acl_fn,
|
||||
};
|
||||
],[])
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns], [
|
||||
#include <linux/fs.h>
|
||||
|
||||
@@ -246,11 +281,18 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
|
||||
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
|
||||
AC_DEFINE(HAVE_SET_ACL_USERNS, 1, [iops->set_acl() takes 4 args])
|
||||
],[
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns_dentry], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args])
|
||||
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
|
||||
AC_DEFINE(HAVE_SET_ACL_USERNS_DENTRY_ARG2, 1,
|
||||
[iops->set_acl() takes 4 args, arg2 is struct dentry *])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args])
|
||||
],[
|
||||
ZFS_LINUX_REQUIRE_API([i_op->set_acl()], [3.14])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
@@ -103,6 +103,57 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_CHECK_DISK_CHANGE], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # bdev_kobj() is introduced from 5.12
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_KOBJ], [
|
||||
ZFS_LINUX_TEST_SRC([bdev_kobj], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/kobject.h>
|
||||
], [
|
||||
struct block_device *bdev = NULL;
|
||||
struct kobject *disk_kobj;
|
||||
disk_kobj = bdev_kobj(bdev);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BDEV_KOBJ], [
|
||||
AC_MSG_CHECKING([whether bdev_kobj() exists])
|
||||
ZFS_LINUX_TEST_RESULT([bdev_kobj], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_BDEV_KOBJ, 1,
|
||||
[bdev_kobj() exists])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # part_to_dev() was removed in 5.12
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV], [
|
||||
ZFS_LINUX_TEST_SRC([part_to_dev], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
], [
|
||||
struct hd_struct *p = NULL;
|
||||
struct device *pdev;
|
||||
pdev = part_to_dev(p);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV], [
|
||||
AC_MSG_CHECKING([whether part_to_dev() exists])
|
||||
ZFS_LINUX_TEST_RESULT([part_to_dev], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_PART_TO_DEV, 1,
|
||||
[part_to_dev() exists])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 5.10 API, check_disk_change() is removed, in favor of
|
||||
dnl # bdev_check_media_change(), which doesn't force revalidation
|
||||
@@ -405,6 +456,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_WHOLE
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_BDEVNAME
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_KOBJ
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
||||
@@ -421,4 +474,6 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
||||
ZFS_AC_KERNEL_BLKDEV_BDEVNAME
|
||||
ZFS_AC_KERNEL_BLKDEV_GET_ERESTARTSYS
|
||||
ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE
|
||||
ZFS_AC_KERNEL_BLKDEV_BDEV_KOBJ
|
||||
ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV
|
||||
])
|
||||
|
||||
@@ -2,7 +2,20 @@ 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], [
|
||||
ZFS_LINUX_TEST_SRC([bdev_io_acct_63], [
|
||||
#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_op(bio),
|
||||
passed_time);
|
||||
bdev_end_io_acct(bdev, bio_op(bio), bio_sectors(bio), start_time);
|
||||
])
|
||||
|
||||
ZFS_LINUX_TEST_SRC([bdev_io_acct_old], [
|
||||
#include <linux/blkdev.h>
|
||||
], [
|
||||
struct block_device *bdev = NULL;
|
||||
@@ -63,74 +76,85 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT], [
|
||||
dnl #
|
||||
dnl # 5.19 API,
|
||||
dnl # Linux 6.3, and then backports thereof, changed
|
||||
dnl # the signatures on bdev_start_io_acct/bdev_end_io_acct
|
||||
dnl #
|
||||
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 bdev_*_io_acct() are available])
|
||||
ZFS_LINUX_TEST_RESULT([bdev_io_acct], [
|
||||
AC_MSG_CHECKING([whether 6.3+ bdev_*_io_acct() are available])
|
||||
ZFS_LINUX_TEST_RESULT([bdev_io_acct_63], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_BDEV_IO_ACCT, 1, [bdev_*_io_acct() available])
|
||||
AC_DEFINE(HAVE_BDEV_IO_ACCT_63, 1, [bdev_*_io_acct() available])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
|
||||
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 pre-6.3 bdev_*_io_acct() are available])
|
||||
ZFS_LINUX_TEST_RESULT([bdev_io_acct_old], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_DISK_IO_ACCT, 1, [disk_*_io_acct() available])
|
||||
AC_DEFINE(HAVE_BDEV_IO_ACCT_OLD, 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)
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
@@ -55,7 +55,7 @@ dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_ENUM_MEMBER], [
|
||||
AC_MSG_CHECKING([whether enum $2 contains $1])
|
||||
AS_IF([AC_TRY_COMMAND(
|
||||
"${srcdir}/scripts/enum-extract.pl" "$2" "$3" | egrep -qx $1)],[
|
||||
"${srcdir}/scripts/enum-extract.pl" "$2" "$3" | grep -Eqx $1)],[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(m4_join([_], [ZFS_ENUM], m4_toupper($2), $1), 1,
|
||||
[enum $2 contains $1])
|
||||
|
||||
@@ -3,11 +3,25 @@ dnl # 3.11 API change
|
||||
dnl # Add support for i_op->tmpfile
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
|
||||
dnl #
|
||||
dnl # 6.1 API change
|
||||
dnl # use struct file instead of struct dentry
|
||||
dnl #
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [
|
||||
#include <linux/fs.h>
|
||||
int tmpfile(struct user_namespace *userns,
|
||||
struct inode *inode, struct file *file,
|
||||
umode_t mode) { return 0; }
|
||||
static struct inode_operations
|
||||
iops __attribute__ ((unused)) = {
|
||||
.tmpfile = tmpfile,
|
||||
};
|
||||
],[])
|
||||
dnl #
|
||||
dnl # 5.11 API change
|
||||
dnl # add support for userns parameter to tmpfile
|
||||
dnl #
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_userns], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_dentry_userns], [
|
||||
#include <linux/fs.h>
|
||||
int tmpfile(struct user_namespace *userns,
|
||||
struct inode *inode, struct dentry *dentry,
|
||||
@@ -17,7 +31,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
|
||||
.tmpfile = tmpfile,
|
||||
};
|
||||
],[])
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_dentry], [
|
||||
#include <linux/fs.h>
|
||||
int tmpfile(struct inode *inode, struct dentry *dentry,
|
||||
umode_t mode) { return 0; }
|
||||
@@ -30,16 +44,24 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
|
||||
AC_MSG_CHECKING([whether i_op->tmpfile() exists])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_userns], [
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
|
||||
AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns])
|
||||
],[
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry_userns], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
|
||||
AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns])
|
||||
AC_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
|
||||
AC_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature])
|
||||
],[
|
||||
ZFS_LINUX_REQUIRE_API([i_op->tmpfile()], [3.11])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
+35
-3
@@ -404,11 +404,11 @@ AC_DEFUN([ZFS_AC_KERNEL], [
|
||||
utsrelease1=$kernelbuild/include/linux/version.h
|
||||
utsrelease2=$kernelbuild/include/linux/utsrelease.h
|
||||
utsrelease3=$kernelbuild/include/generated/utsrelease.h
|
||||
AS_IF([test -r $utsrelease1 && fgrep -q UTS_RELEASE $utsrelease1], [
|
||||
AS_IF([test -r $utsrelease1 && grep -qF UTS_RELEASE $utsrelease1], [
|
||||
utsrelease=$utsrelease1
|
||||
], [test -r $utsrelease2 && fgrep -q UTS_RELEASE $utsrelease2], [
|
||||
], [test -r $utsrelease2 && grep -qF UTS_RELEASE $utsrelease2], [
|
||||
utsrelease=$utsrelease2
|
||||
], [test -r $utsrelease3 && fgrep -q UTS_RELEASE $utsrelease3], [
|
||||
], [test -r $utsrelease3 && grep -qF UTS_RELEASE $utsrelease3], [
|
||||
utsrelease=$utsrelease3
|
||||
])
|
||||
|
||||
@@ -946,3 +946,35 @@ AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER], [
|
||||
[test -f build/conftest/conftest.ko], [$3], [$4], [$5])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # AS_VERSION_COMPARE_LE
|
||||
dnl # like AS_VERSION_COMPARE_LE, but runs $3 if (and only if) $1 <= $2
|
||||
dnl # AS_VERSION_COMPARE_LE (version-1, version-2, [action-if-less-or-equal], [action-if-greater])
|
||||
dnl #
|
||||
AC_DEFUN([AS_VERSION_COMPARE_LE], [
|
||||
AS_VERSION_COMPARE([$1], [$2], [$3], [$3], [$4])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # ZFS_LINUX_REQUIRE_API
|
||||
dnl # like ZFS_LINUX_TEST_ERROR, except only fails if the kernel is
|
||||
dnl # at least some specified version.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_LINUX_REQUIRE_API], [
|
||||
AS_VERSION_COMPARE_LE([$2], [$kernsrcver], [
|
||||
AC_MSG_ERROR([
|
||||
*** None of the expected "$1" interfaces were detected. This
|
||||
*** interface is expected for kernels version "$2" and above.
|
||||
*** This may be because your kernel version is newer than what is
|
||||
*** supported, or you are using a patched custom kernel with
|
||||
*** incompatible modifications. Newer kernels may have incompatible
|
||||
*** APIs.
|
||||
***
|
||||
*** ZFS Version: $ZFS_META_ALIAS
|
||||
*** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
|
||||
])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
+10
-27
@@ -173,7 +173,7 @@ AC_DEFUN([ZFS_AC_DEBUG_KMEM_TRACKING], [
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS_DETECT_FREEBSD], [
|
||||
AS_IF([sysctl -n kern.conftxt | fgrep -qx $'options\tINVARIANTS'],
|
||||
AS_IF([sysctl -n kern.conftxt | grep -Fqx $'options\tINVARIANTS'],
|
||||
[enable_invariants="yes"],
|
||||
[enable_invariants="no"])
|
||||
])
|
||||
@@ -518,6 +518,8 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
|
||||
VENDOR=alpine ;
|
||||
elif test -f /bin/freebsd-version ; then
|
||||
VENDOR=freebsd ;
|
||||
elif test -f /etc/openEuler-release ; then
|
||||
VENDOR=openeuler ;
|
||||
else
|
||||
VENDOR= ;
|
||||
fi],
|
||||
@@ -542,6 +544,7 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
|
||||
ubuntu) DEFAULT_PACKAGE=deb ;;
|
||||
debian) DEFAULT_PACKAGE=deb ;;
|
||||
freebsd) DEFAULT_PACKAGE=pkg ;;
|
||||
openeuler) DEFAULT_PACKAGE=rpm ;;
|
||||
*) DEFAULT_PACKAGE=rpm ;;
|
||||
esac
|
||||
AC_MSG_RESULT([$DEFAULT_PACKAGE])
|
||||
@@ -555,35 +558,14 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
|
||||
AC_MSG_RESULT([$initdir])
|
||||
AC_SUBST(initdir)
|
||||
|
||||
AC_MSG_CHECKING([default init script type and shell])
|
||||
AC_MSG_CHECKING([default shell])
|
||||
case "$VENDOR" in
|
||||
toss) DEFAULT_INIT_SCRIPT=redhat ;;
|
||||
redhat) DEFAULT_INIT_SCRIPT=redhat ;;
|
||||
fedora) DEFAULT_INIT_SCRIPT=fedora ;;
|
||||
gentoo) DEFAULT_INIT_SCRIPT=openrc ;;
|
||||
alpine) DEFAULT_INIT_SCRIPT=openrc ;;
|
||||
arch) DEFAULT_INIT_SCRIPT=lsb ;;
|
||||
sles) DEFAULT_INIT_SCRIPT=lsb ;;
|
||||
slackware) DEFAULT_INIT_SCRIPT=lsb ;;
|
||||
lunar) DEFAULT_INIT_SCRIPT=lunar ;;
|
||||
ubuntu) DEFAULT_INIT_SCRIPT=lsb ;;
|
||||
debian) DEFAULT_INIT_SCRIPT=lsb ;;
|
||||
freebsd) DEFAULT_INIT_SCRIPT=freebsd;;
|
||||
*) DEFAULT_INIT_SCRIPT=lsb ;;
|
||||
gentoo) DEFAULT_INIT_SHELL="/sbin/openrc-run";;
|
||||
alpine) DEFAULT_INIT_SHELL="/sbin/openrc-run";;
|
||||
*) DEFAULT_INIT_SHELL="/bin/sh" ;;
|
||||
esac
|
||||
|
||||
# On gentoo, it's possible that OpenRC isn't installed. Check if
|
||||
# /sbin/openrc-run exists, and if not, fall back to generic defaults.
|
||||
|
||||
DEFAULT_INIT_SHELL="/bin/sh"
|
||||
AS_IF([test "$DEFAULT_INIT_SCRIPT" = "openrc"], [
|
||||
AS_IF([test -x "/sbin/openrc-run"],
|
||||
[DEFAULT_INIT_SHELL="/sbin/openrc-run"],
|
||||
[DEFAULT_INIT_SCRIPT=lsb])
|
||||
])
|
||||
|
||||
AC_MSG_RESULT([$DEFAULT_INIT_SCRIPT:$DEFAULT_INIT_SHELL])
|
||||
AC_SUBST(DEFAULT_INIT_SCRIPT)
|
||||
AC_MSG_RESULT([$DEFAULT_INIT_SHELL])
|
||||
AC_SUBST(DEFAULT_INIT_SHELL)
|
||||
|
||||
AC_MSG_CHECKING([default nfs server init script])
|
||||
@@ -602,6 +584,7 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
|
||||
redhat) initconfdir=/etc/sysconfig ;;
|
||||
fedora) initconfdir=/etc/sysconfig ;;
|
||||
sles) initconfdir=/etc/sysconfig ;;
|
||||
openeuler) initconfdir=/etc/sysconfig ;;
|
||||
ubuntu) initconfdir=/etc/default ;;
|
||||
debian) initconfdir=/etc/default ;;
|
||||
freebsd) initconfdir=$sysconfdir/rc.conf.d;;
|
||||
|
||||
@@ -57,6 +57,12 @@ array_contains () {
|
||||
}
|
||||
|
||||
check() {
|
||||
# https://github.com/dracutdevs/dracut/pull/1711 provides a zfs_devs
|
||||
# function to detect the physical devices backing zfs pools. If this
|
||||
# function exists in the version of dracut this module is being called
|
||||
# from, then it does not need to run.
|
||||
type zfs_devs >/dev/null 2>&1 && return 1
|
||||
|
||||
local mp
|
||||
local dev
|
||||
local blockdevs
|
||||
|
||||
@@ -15,6 +15,7 @@ pkgdracut_SCRIPTS = \
|
||||
|
||||
pkgdracut_DATA = \
|
||||
zfs-env-bootfs.service \
|
||||
zfs-nonroot-necessities.service \
|
||||
zfs-snapshot-bootfs.service \
|
||||
zfs-rollback-bootfs.service
|
||||
|
||||
|
||||
@@ -84,11 +84,24 @@ install() {
|
||||
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
|
||||
|
||||
inst_simple "${moddir}/zfs-nonroot-necessities.service" "${systemdsystemunitdir}/zfs-nonroot-necessities.service"
|
||||
systemctl -q --root "${initdir}" add-requires initrd-root-fs.target zfs-nonroot-necessities.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}"
|
||||
|
||||
# Add user-provided unit overrides
|
||||
# - /etc/systemd/system/zfs-import-{scan,cache}.service
|
||||
# - /etc/systemd/system/zfs-import-{scan,cache}.service.d/overrides.conf
|
||||
# -H ensures they are marked host-only
|
||||
# -o ensures there is no error upon absence of these files
|
||||
inst_multiple -o -H \
|
||||
"${systemdsystemconfdir}/${_service}" \
|
||||
"${systemdsystemconfdir}/${_service}.d/"*.conf
|
||||
|
||||
done
|
||||
|
||||
for _service in \
|
||||
|
||||
@@ -82,7 +82,7 @@ ZFS_DATASET="${ZFS_DATASET:-${root}}"
|
||||
ZFS_POOL="${ZFS_DATASET%%/*}"
|
||||
|
||||
|
||||
if ! zpool get -Ho name "${ZFS_POOL}" > /dev/null 2>&1; then
|
||||
if ! zpool get -Ho value 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
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[Unit]
|
||||
Description=Set BOOTFS environment for dracut
|
||||
Documentation=man:zpool(8)
|
||||
Description=Set BOOTFS and BOOTFSFLAGS environment variables for dracut
|
||||
DefaultDependencies=no
|
||||
After=zfs-import-cache.service
|
||||
After=zfs-import-scan.service
|
||||
@@ -8,7 +7,17 @@ Before=zfs-import.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"
|
||||
ExecStart=/bin/sh -c ' \
|
||||
. /lib/dracut-zfs-lib.sh; \
|
||||
decode_root_args || exit 0; \
|
||||
[ "$root" = "zfs:AUTO" ] && root="$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"; \
|
||||
rootflags="$(getarg rootflags=)"; \
|
||||
case ",$rootflags," in \
|
||||
*,zfsutil,*) ;; \
|
||||
,,) rootflags=zfsutil ;; \
|
||||
*) rootflags="zfsutil,$rootflags" ;; \
|
||||
esac; \
|
||||
exec systemctl set-environment BOOTFS="$root" BOOTFSFLAGS="$rootflags"'
|
||||
|
||||
[Install]
|
||||
WantedBy=zfs-import.target
|
||||
|
||||
@@ -14,81 +14,24 @@ GENERATOR_DIR="$1"
|
||||
. /lib/dracut-zfs-lib.sh
|
||||
decode_root_args || exit 0
|
||||
|
||||
[ -z "${rootflags}" ] && rootflags=$(getarg rootflags=)
|
||||
case ",${rootflags}," in
|
||||
*,zfsutil,*) ;;
|
||||
,,) rootflags=zfsutil ;;
|
||||
*) rootflags="zfsutil,${rootflags}" ;;
|
||||
esac
|
||||
|
||||
[ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
|
||||
|
||||
|
||||
mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/initrd-root-fs.target.requires "$GENERATOR_DIR"/dracut-pre-mount.service.d
|
||||
mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/dracut-pre-mount.service.d
|
||||
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "Before=initrd-root-fs.target"
|
||||
echo "After=zfs-import.target"
|
||||
echo
|
||||
echo "[Mount]"
|
||||
if [ "${root}" = "zfs:AUTO" ]; then
|
||||
echo "PassEnvironment=BOOTFS"
|
||||
echo 'What=${BOOTFS}'
|
||||
else
|
||||
echo "What=${root}"
|
||||
fi
|
||||
echo "PassEnvironment=BOOTFS BOOTFSFLAGS"
|
||||
echo 'What=${BOOTFS}'
|
||||
echo "Type=zfs"
|
||||
echo "Options=${rootflags}"
|
||||
echo 'Options=${BOOTFSFLAGS}'
|
||||
} > "$GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf
|
||||
ln -fs ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
|
||||
|
||||
|
||||
if [ "${root}" = "zfs:AUTO" ]; then
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "Before=initrd-root-fs.target"
|
||||
echo "After=sysroot.mount"
|
||||
echo "DefaultDependencies=no"
|
||||
echo
|
||||
echo "[Service]"
|
||||
echo "Type=oneshot"
|
||||
echo "PassEnvironment=BOOTFS"
|
||||
echo "ExecStart=/bin/sh -c '" ' \
|
||||
. /lib/dracut-zfs-lib.sh; \
|
||||
_zfs_nonroot_necessities_cb() { \
|
||||
zfs mount | grep -m1 -q "^$1 " && return 0; \
|
||||
echo "Mounting $1 on /sysroot$2"; \
|
||||
mount -o zfsutil -t zfs "$1" "/sysroot$2"; \
|
||||
}; \
|
||||
for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb;' \
|
||||
"'"
|
||||
} > "$GENERATOR_DIR"/zfs-nonroot-necessities.service
|
||||
ln -fs ../zfs-nonroot-necessities.service "$GENERATOR_DIR"/initrd-root-fs.target.requires/zfs-nonroot-necessities.service
|
||||
else
|
||||
# We can solve this statically at generation time, so do!
|
||||
_zfs_generator_cb() {
|
||||
dset="${1}"
|
||||
mpnt="${2}"
|
||||
unit="$(systemd-escape --suffix=mount -p "/sysroot${mpnt}")"
|
||||
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "Before=initrd-root-fs.target"
|
||||
echo "After=sysroot.mount"
|
||||
echo
|
||||
echo "[Mount]"
|
||||
echo "Where=/sysroot${mpnt}"
|
||||
echo "What=${dset}"
|
||||
echo "Type=zfs"
|
||||
echo "Options=zfsutil"
|
||||
} > "$GENERATOR_DIR/${unit}"
|
||||
ln -fs ../"${unit}" "$GENERATOR_DIR"/initrd-root-fs.target.requires/"${unit}"
|
||||
}
|
||||
|
||||
for_relevant_root_children "${root}" _zfs_generator_cb
|
||||
fi
|
||||
|
||||
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "After=zfs-import.target"
|
||||
|
||||
@@ -38,7 +38,7 @@ mount_dataset() {
|
||||
|
||||
# for_relevant_root_children DATASET EXEC
|
||||
# Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup
|
||||
# Used by zfs-generator.sh and friends, too!
|
||||
# Used by zfs-nonroot-necessities.service and friends, too!
|
||||
for_relevant_root_children() {
|
||||
dataset="${1}"
|
||||
exec="${2}"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[Unit]
|
||||
Before=initrd-root-fs.target
|
||||
After=sysroot.mount
|
||||
DefaultDependencies=no
|
||||
ConditionEnvironment=BOOTFS
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
PassEnvironment=BOOTFS
|
||||
ExecStart=/bin/sh -c ' \
|
||||
. /lib/dracut-zfs-lib.sh; \
|
||||
_zfs_nonroot_necessities_cb() { \
|
||||
@sbindir@/zfs mount | grep -m1 -q "^$1 " && return 0; \
|
||||
echo "Mounting $1 on /sysroot$2"; \
|
||||
mount -o zfsutil -t zfs "$1" "/sysroot$2"; \
|
||||
}; \
|
||||
for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb'
|
||||
|
||||
[Install]
|
||||
RequiredBy=initrd-root-fs.target
|
||||
@@ -5,8 +5,9 @@ After=zfs-import.target dracut-pre-mount.service zfs-snapshot-bootfs.service
|
||||
Before=dracut-mount.service
|
||||
DefaultDependencies=no
|
||||
ConditionKernelCommandLine=bootfs.rollback
|
||||
ConditionEnvironment=BOOTFS
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
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}"'
|
||||
ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$BOOTFS@${SNAPNAME:-%v}"'
|
||||
RemainAfterExit=yes
|
||||
|
||||
@@ -5,8 +5,9 @@ After=zfs-import.target dracut-pre-mount.service
|
||||
Before=dracut-mount.service
|
||||
DefaultDependencies=no
|
||||
ConditionKernelCommandLine=bootfs.snapshot
|
||||
ConditionEnvironment=BOOTFS
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
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}"'
|
||||
ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$BOOTFS@${SNAPNAME:-%v}"'
|
||||
RemainAfterExit=yes
|
||||
|
||||
@@ -7,5 +7,6 @@ dist_scripts_SCRIPTS = \
|
||||
|
||||
SUBDIRS = local-top
|
||||
|
||||
SHELLCHECK_IGNORE = ,SC2295
|
||||
SHELLCHECKDIRS = $(SUBDIRS)
|
||||
SHELLCHECK_SHELL = sh
|
||||
|
||||
@@ -192,7 +192,7 @@ import_pool()
|
||||
|
||||
# Verify that the pool isn't already imported
|
||||
# Make as sure as we can to not require '-f' to import.
|
||||
"${ZPOOL}" get name,guid -o value -H 2>/dev/null | grep -Fxq "$pool" && return 0
|
||||
"${ZPOOL}" get -H -o value name,guid 2>/dev/null | grep -Fxq "$pool" && return 0
|
||||
|
||||
# For backwards compatibility, make sure that ZPOOL_IMPORT_PATH is set
|
||||
# to something we can use later with the real import(s). We want to
|
||||
@@ -331,25 +331,24 @@ mount_fs()
|
||||
# Can't use the mountpoint property. Might be one of our
|
||||
# clones. Check the 'org.zol:mountpoint' property set in
|
||||
# clone_snap() if that's usable.
|
||||
mountpoint=$(get_fs_value "$fs" org.zol:mountpoint)
|
||||
if [ "$mountpoint" = "legacy" ] ||
|
||||
[ "$mountpoint" = "none" ] ||
|
||||
[ "$mountpoint" = "-" ]
|
||||
mountpoint1=$(get_fs_value "$fs" org.zol:mountpoint)
|
||||
if [ "$mountpoint1" = "legacy" ] ||
|
||||
[ "$mountpoint1" = "none" ] ||
|
||||
[ "$mountpoint1" = "-" ]
|
||||
then
|
||||
if [ "$fs" != "${ZFS_BOOTFS}" ]; then
|
||||
# We don't have a proper mountpoint and this
|
||||
# isn't the root fs.
|
||||
return 0
|
||||
else
|
||||
# Last hail-mary: Hope 'rootmnt' is set!
|
||||
mountpoint=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# If it's not a legacy filesystem, it can only be a
|
||||
# native one...
|
||||
if [ "$mountpoint" = "legacy" ]; then
|
||||
ZFS_CMD="mount.zfs"
|
||||
# Don't use mount.zfs -o zfsutils for legacy mountpoint
|
||||
if [ "$mountpoint" = "legacy" ]; then
|
||||
ZFS_CMD="mount.zfs"
|
||||
fi
|
||||
# Last hail-mary: Hope 'rootmnt' is set!
|
||||
mountpoint=""
|
||||
else
|
||||
mountpoint="$mountpoint1"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -503,7 +502,7 @@ clone_snap()
|
||||
echo "Error: $ZFS_ERROR"
|
||||
echo ""
|
||||
echo "Failed to clone snapshot."
|
||||
echo "Make sure that the any problems are corrected and then make sure"
|
||||
echo "Make sure that any problems are corrected and then make sure"
|
||||
echo "that the dataset '$destfs' exists and is bootable."
|
||||
shell
|
||||
else
|
||||
@@ -884,12 +883,12 @@ mountroot()
|
||||
fi
|
||||
|
||||
# In case the pool was specified as guid, resolve guid to name
|
||||
pool="$("${ZPOOL}" get name,guid -o name,value -H | \
|
||||
pool="$("${ZPOOL}" get -H -o name,value name,guid | \
|
||||
awk -v pool="${ZFS_RPOOL}" '$2 == pool { print $1 }')"
|
||||
if [ -n "$pool" ]; then
|
||||
# If $ZFS_BOOTFS contains guid, replace the guid portion with $pool
|
||||
ZFS_BOOTFS=$(echo "$ZFS_BOOTFS" | \
|
||||
sed -e "s/$("${ZPOOL}" get guid -o value "$pool" -H)/$pool/g")
|
||||
sed -e "s/$("${ZPOOL}" get -H -o value guid "$pool")/$pool/g")
|
||||
ZFS_RPOOL="${pool}"
|
||||
fi
|
||||
|
||||
|
||||
@@ -29,13 +29,12 @@ setup(
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Topic :: System :: Filesystems",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
],
|
||||
@@ -53,7 +52,7 @@ setup(
|
||||
setup_requires=[
|
||||
"cffi",
|
||||
],
|
||||
python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4',
|
||||
python_requires='>=3.6,<4',
|
||||
zip_safe=False,
|
||||
test_suite="libzfs_core.test",
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ ConditionPathIsDirectory=/sys/module/zfs
|
||||
|
||||
[Service]
|
||||
ExecStart=@sbindir@/zed -F
|
||||
Restart=on-abort
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
Alias=zed.service
|
||||
|
||||
@@ -307,6 +307,7 @@ extern int zpool_vdev_remove_cancel(zpool_handle_t *);
|
||||
extern int zpool_vdev_indirect_size(zpool_handle_t *, const char *, uint64_t *);
|
||||
extern int zpool_vdev_split(zpool_handle_t *, char *, nvlist_t **, nvlist_t *,
|
||||
splitflags_t);
|
||||
_LIBZFS_H int zpool_vdev_remove_wanted(zpool_handle_t *, const char *);
|
||||
|
||||
extern int zpool_vdev_fault(zpool_handle_t *, uint64_t, vdev_aux_t);
|
||||
extern int zpool_vdev_degrade(zpool_handle_t *, uint64_t, vdev_aux_t);
|
||||
@@ -692,6 +693,9 @@ typedef struct sendflags {
|
||||
/* show progress (ie. -v) */
|
||||
boolean_t progress;
|
||||
|
||||
/* show progress as process title (ie. -V) */
|
||||
boolean_t progressastitle;
|
||||
|
||||
/* large blocks (>128K) are permitted */
|
||||
boolean_t largeblock;
|
||||
|
||||
|
||||
+20
-2
@@ -150,14 +150,32 @@ int zfs_ioctl_fd(int fd, unsigned long request, struct zfs_cmd *zc);
|
||||
/*
|
||||
* List of colors to use
|
||||
*/
|
||||
#define ANSI_BLACK "\033[0;30m"
|
||||
#define ANSI_RED "\033[0;31m"
|
||||
#define ANSI_GREEN "\033[0;32m"
|
||||
#define ANSI_YELLOW "\033[0;33m"
|
||||
#define ANSI_BLUE "\033[0;34m"
|
||||
#define ANSI_BOLD_BLUE "\033[1;34m" /* light blue */
|
||||
#define ANSI_MAGENTA "\033[0;35m"
|
||||
#define ANSI_CYAN "\033[0;36m"
|
||||
#define ANSI_GRAY "\033[0;37m"
|
||||
|
||||
#define ANSI_RESET "\033[0m"
|
||||
#define ANSI_BOLD "\033[1m"
|
||||
|
||||
void color_start(char *color);
|
||||
int use_color(void);
|
||||
void color_start(const char *color);
|
||||
void color_end(void);
|
||||
int printf_color(char *color, char *format, ...);
|
||||
int printf_color(const char *color, char *format, ...);
|
||||
|
||||
#ifdef __linux__
|
||||
extern char **environ;
|
||||
_LIBZUTIL_H void zfs_setproctitle_init(int argc, char *argv[], char *envp[]);
|
||||
_LIBZUTIL_H void zfs_setproctitle(const char *fmt, ...);
|
||||
#else
|
||||
#define zfs_setproctitle(fmt, ...) setproctitle(fmt, ##__VA_ARGS__)
|
||||
#define zfs_setproctitle_init(x, y, z) ((void)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These functions are used by the ZFS libraries and cmd/zpool code, but are
|
||||
|
||||
@@ -256,6 +256,32 @@ bio_set_bi_error(struct bio *bio, int error)
|
||||
#define BIO_END_IO(bio, error) bio_endio(bio, error);
|
||||
#endif /* HAVE_1ARG_BIO_END_IO_T */
|
||||
|
||||
/*
|
||||
* 5.15 MACRO,
|
||||
* GD_DEAD
|
||||
*
|
||||
* 2.6.36 - 5.14 MACRO,
|
||||
* GENHD_FL_UP
|
||||
*
|
||||
* Check the disk status and return B_TRUE if alive
|
||||
* otherwise B_FALSE
|
||||
*/
|
||||
static inline boolean_t
|
||||
zfs_check_disk_status(struct block_device *bdev)
|
||||
{
|
||||
#if defined(GENHD_FL_UP)
|
||||
return (!!(bdev->bd_disk->flags & GENHD_FL_UP));
|
||||
#elif defined(GD_DEAD)
|
||||
return (!test_bit(GD_DEAD, &bdev->bd_disk->state));
|
||||
#else
|
||||
/*
|
||||
* This is encountered if neither GENHD_FL_UP nor GD_DEAD is available in
|
||||
* the kernel - likely due to an MACRO change that needs to be chased down.
|
||||
*/
|
||||
#error "Unsupported kernel: no usable disk status check"
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 4.1 API,
|
||||
* 3.10.0 CentOS 7.x API,
|
||||
@@ -357,7 +383,11 @@ vdev_lookup_bdev(const char *path, dev_t *dev)
|
||||
static inline void
|
||||
bio_set_op_attrs(struct bio *bio, unsigned rw, unsigned flags)
|
||||
{
|
||||
#if defined(HAVE_BIO_BI_OPF)
|
||||
bio->bi_opf = rw | flags;
|
||||
#else
|
||||
bio->bi_rw |= rw | flags;
|
||||
#endif /* HAVE_BIO_BI_OPF */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -385,7 +415,7 @@ static inline void
|
||||
bio_set_flush(struct bio *bio)
|
||||
{
|
||||
#if defined(HAVE_REQ_PREFLUSH) /* >= 4.10 */
|
||||
bio_set_op_attrs(bio, 0, REQ_PREFLUSH);
|
||||
bio_set_op_attrs(bio, 0, REQ_PREFLUSH | REQ_OP_WRITE);
|
||||
#elif defined(WRITE_FLUSH_FUA) /* >= 2.6.37 and <= 4.9 */
|
||||
bio_set_op_attrs(bio, 0, WRITE_FLUSH_FUA);
|
||||
#else
|
||||
@@ -551,7 +581,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_BDEV_IO_ACCT)
|
||||
#if defined(HAVE_BDEV_IO_ACCT_63)
|
||||
return (bdev_start_io_acct(bio->bi_bdev, bio_op(bio),
|
||||
jiffies));
|
||||
#elif defined(HAVE_BDEV_IO_ACCT_OLD)
|
||||
return (bdev_start_io_acct(bio->bi_bdev, bio_sectors(bio),
|
||||
bio_op(bio), jiffies));
|
||||
#elif defined(HAVE_DISK_IO_ACCT)
|
||||
@@ -577,7 +610,10 @@ 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_BDEV_IO_ACCT)
|
||||
#if defined(HAVE_BDEV_IO_ACCT_63)
|
||||
bdev_end_io_acct(bio->bi_bdev, bio_op(bio), bio_sectors(bio),
|
||||
start_time);
|
||||
#elif defined(HAVE_BDEV_IO_ACCT_OLD)
|
||||
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);
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
#define d_make_root(inode) d_alloc_root(inode)
|
||||
#endif /* HAVE_D_MAKE_ROOT */
|
||||
|
||||
#ifdef HAVE_DENTRY_D_U_ALIASES
|
||||
#define d_alias d_u.d_alias
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2.6.30 API change,
|
||||
* The const keyword was added to the 'struct dentry_operations' in
|
||||
@@ -70,11 +74,7 @@ zpl_d_drop_aliases(struct inode *inode)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
spin_lock(&inode->i_lock);
|
||||
#ifdef HAVE_DENTRY_D_U_ALIASES
|
||||
hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
|
||||
#else
|
||||
hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
|
||||
#endif
|
||||
if (!IS_ROOT(dentry) && !d_mountpoint(dentry) &&
|
||||
(dentry->d_inode == inode)) {
|
||||
d_drop(dentry);
|
||||
|
||||
@@ -20,6 +20,7 @@ KERNEL_H = \
|
||||
kmem.h \
|
||||
kstat.h \
|
||||
list.h \
|
||||
misc.h \
|
||||
mod_os.h \
|
||||
mutex.h \
|
||||
param.h \
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or https://opensource.org/licenses/CDDL-1.0.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
#ifndef _OS_LINUX_SPL_MISC_H
|
||||
#define _OS_LINUX_SPL_MISC_H
|
||||
|
||||
#include <linux/kobject.h>
|
||||
|
||||
extern void spl_signal_kobj_evt(struct block_device *bdev);
|
||||
|
||||
#endif
|
||||
@@ -67,11 +67,14 @@ extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip,
|
||||
#if defined(HAVE_SET_ACL_USERNS)
|
||||
extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip,
|
||||
struct posix_acl *acl, int type);
|
||||
#elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2)
|
||||
extern int zpl_set_acl(struct user_namespace *userns, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type);
|
||||
#else
|
||||
extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type);
|
||||
#endif /* HAVE_SET_ACL_USERNS */
|
||||
#endif /* HAVE_SET_ACL */
|
||||
#if defined(HAVE_GET_ACL_RCU)
|
||||
#if defined(HAVE_GET_ACL_RCU) || defined(HAVE_GET_INODE_ACL)
|
||||
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type, bool rcu);
|
||||
#elif defined(HAVE_GET_ACL)
|
||||
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#define _SYS_ARC_IMPL_H
|
||||
|
||||
#include <sys/arc.h>
|
||||
#include <sys/multilist.h>
|
||||
#include <sys/zio_crypt.h>
|
||||
#include <sys/zthr.h>
|
||||
#include <sys/aggsum.h>
|
||||
|
||||
@@ -87,6 +87,7 @@ int livelist_bpobj_iterate_from_nofree(bpobj_t *bpo, bpobj_itor_t func,
|
||||
void *arg, int64_t start);
|
||||
|
||||
void bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx);
|
||||
void bpobj_prefetch_subobj(bpobj_t *bpo, uint64_t subobj);
|
||||
void bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, boolean_t bp_freed,
|
||||
dmu_tx_t *tx);
|
||||
|
||||
|
||||
+8
-7
@@ -65,7 +65,7 @@ extern "C" {
|
||||
* them, and increased memory overhead. Increasing these values results in
|
||||
* higher variance in operation time, and reduces memory overhead.
|
||||
*/
|
||||
#define BTREE_CORE_ELEMS 128
|
||||
#define BTREE_CORE_ELEMS 126
|
||||
#define BTREE_LEAF_SIZE 4096
|
||||
|
||||
extern kmem_cache_t *zfs_btree_leaf_cache;
|
||||
@@ -95,9 +95,6 @@ typedef struct zfs_btree_leaf {
|
||||
uint8_t btl_elems[];
|
||||
} zfs_btree_leaf_t;
|
||||
|
||||
#define BTREE_LEAF_ESIZE (BTREE_LEAF_SIZE - \
|
||||
offsetof(zfs_btree_leaf_t, btl_elems))
|
||||
|
||||
typedef struct zfs_btree_index {
|
||||
zfs_btree_hdr_t *bti_node;
|
||||
uint32_t bti_offset;
|
||||
@@ -109,14 +106,15 @@ typedef struct zfs_btree_index {
|
||||
} zfs_btree_index_t;
|
||||
|
||||
typedef struct btree {
|
||||
zfs_btree_hdr_t *bt_root;
|
||||
int64_t bt_height;
|
||||
int (*bt_compar) (const void *, const void *);
|
||||
size_t bt_elem_size;
|
||||
size_t bt_leaf_size;
|
||||
uint32_t bt_leaf_cap;
|
||||
int32_t bt_height;
|
||||
uint64_t bt_num_elems;
|
||||
uint64_t bt_num_nodes;
|
||||
zfs_btree_hdr_t *bt_root;
|
||||
zfs_btree_leaf_t *bt_bulk; // non-null if bulk loading
|
||||
int (*bt_compar) (const void *, const void *);
|
||||
} zfs_btree_t;
|
||||
|
||||
/*
|
||||
@@ -132,9 +130,12 @@ void zfs_btree_fini(void);
|
||||
* compar - function to compare two nodes, it must return exactly: -1, 0, or +1
|
||||
* -1 for <, 0 for ==, and +1 for >
|
||||
* size - the value of sizeof(struct my_type)
|
||||
* lsize - custom leaf size
|
||||
*/
|
||||
void zfs_btree_create(zfs_btree_t *, int (*) (const void *, const void *),
|
||||
size_t);
|
||||
void zfs_btree_create_custom(zfs_btree_t *, int (*)(const void *, const void *),
|
||||
size_t, size_t);
|
||||
|
||||
/*
|
||||
* Find a node with a matching value in the tree. Returns the matching node
|
||||
|
||||
+34
-1
@@ -36,6 +36,7 @@
|
||||
#include <sys/dmu_zfetch.h>
|
||||
#include <sys/zrlock.h>
|
||||
#include <sys/multilist.h>
|
||||
#include <sys/wmsum.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -587,10 +588,42 @@ typedef struct dnode_stats {
|
||||
kstat_named_t dnode_move_active;
|
||||
} dnode_stats_t;
|
||||
|
||||
typedef struct dnode_sums {
|
||||
wmsum_t dnode_hold_dbuf_hold;
|
||||
wmsum_t dnode_hold_dbuf_read;
|
||||
wmsum_t dnode_hold_alloc_hits;
|
||||
wmsum_t dnode_hold_alloc_misses;
|
||||
wmsum_t dnode_hold_alloc_interior;
|
||||
wmsum_t dnode_hold_alloc_lock_retry;
|
||||
wmsum_t dnode_hold_alloc_lock_misses;
|
||||
wmsum_t dnode_hold_alloc_type_none;
|
||||
wmsum_t dnode_hold_free_hits;
|
||||
wmsum_t dnode_hold_free_misses;
|
||||
wmsum_t dnode_hold_free_lock_misses;
|
||||
wmsum_t dnode_hold_free_lock_retry;
|
||||
wmsum_t dnode_hold_free_refcount;
|
||||
wmsum_t dnode_hold_free_overflow;
|
||||
wmsum_t dnode_free_interior_lock_retry;
|
||||
wmsum_t dnode_allocate;
|
||||
wmsum_t dnode_reallocate;
|
||||
wmsum_t dnode_buf_evict;
|
||||
wmsum_t dnode_alloc_next_chunk;
|
||||
wmsum_t dnode_alloc_race;
|
||||
wmsum_t dnode_alloc_next_block;
|
||||
wmsum_t dnode_move_invalid;
|
||||
wmsum_t dnode_move_recheck1;
|
||||
wmsum_t dnode_move_recheck2;
|
||||
wmsum_t dnode_move_special;
|
||||
wmsum_t dnode_move_handle;
|
||||
wmsum_t dnode_move_rwlock;
|
||||
wmsum_t dnode_move_active;
|
||||
} dnode_sums_t;
|
||||
|
||||
extern dnode_stats_t dnode_stats;
|
||||
extern dnode_sums_t dnode_sums;
|
||||
|
||||
#define DNODE_STAT_INCR(stat, val) \
|
||||
atomic_add_64(&dnode_stats.stat.value.ui64, (val));
|
||||
wmsum_add(&dnode_sums.stat, (val))
|
||||
#define DNODE_STAT_BUMP(stat) \
|
||||
DNODE_STAT_INCR(stat, 1);
|
||||
|
||||
|
||||
@@ -1518,6 +1518,7 @@ typedef enum {
|
||||
#define ZFS_ONLINE_UNSPARE 0x2
|
||||
#define ZFS_ONLINE_FORCEFAULT 0x4
|
||||
#define ZFS_ONLINE_EXPAND 0x8
|
||||
#define ZFS_ONLINE_SPARE 0x10
|
||||
#define ZFS_OFFLINE_TEMPORARY 0x1
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -837,7 +837,7 @@ extern kmutex_t spa_namespace_lock;
|
||||
#define SPA_CONFIG_UPDATE_POOL 0
|
||||
#define SPA_CONFIG_UPDATE_VDEVS 1
|
||||
|
||||
extern void spa_write_cachefile(spa_t *, boolean_t, boolean_t);
|
||||
extern void spa_write_cachefile(spa_t *, boolean_t, boolean_t, boolean_t);
|
||||
extern void spa_config_load(void);
|
||||
extern nvlist_t *spa_all_configs(uint64_t *);
|
||||
extern void spa_config_set(spa_t *spa, nvlist_t *config);
|
||||
|
||||
@@ -147,6 +147,7 @@ extern int vdev_degrade(spa_t *spa, uint64_t guid, vdev_aux_t aux);
|
||||
extern int vdev_online(spa_t *spa, uint64_t guid, uint64_t flags,
|
||||
vdev_state_t *);
|
||||
extern int vdev_offline(spa_t *spa, uint64_t guid, uint64_t flags);
|
||||
extern int vdev_remove_wanted(spa_t *spa, uint64_t guid);
|
||||
extern void vdev_clear(spa_t *spa, vdev_t *vd);
|
||||
|
||||
extern boolean_t vdev_is_dead(vdev_t *vd);
|
||||
@@ -189,6 +190,8 @@ typedef enum vdev_config_flag {
|
||||
VDEV_CONFIG_MISSING = 1 << 4
|
||||
} vdev_config_flag_t;
|
||||
|
||||
extern void vdev_post_kobj_evt(vdev_t *vd);
|
||||
extern void vdev_clear_kobj_evt(vdev_t *vd);
|
||||
extern void vdev_top_config_generate(spa_t *spa, nvlist_t *config);
|
||||
extern nvlist_t *vdev_config_generate(spa_t *spa, vdev_t *vd,
|
||||
boolean_t getstats, vdev_config_flag_t flags);
|
||||
|
||||
@@ -69,6 +69,7 @@ extern uint32_t zfs_vdev_async_write_max_active;
|
||||
* Virtual device operations
|
||||
*/
|
||||
typedef int vdev_init_func_t(spa_t *spa, nvlist_t *nv, void **tsd);
|
||||
typedef void vdev_kobj_post_evt_func_t(vdev_t *vd);
|
||||
typedef void vdev_fini_func_t(vdev_t *vd);
|
||||
typedef int vdev_open_func_t(vdev_t *vd, uint64_t *size, uint64_t *max_size,
|
||||
uint64_t *ashift, uint64_t *pshift);
|
||||
@@ -123,6 +124,7 @@ typedef const struct vdev_ops {
|
||||
vdev_config_generate_func_t *vdev_op_config_generate;
|
||||
vdev_nparity_func_t *vdev_op_nparity;
|
||||
vdev_ndisks_func_t *vdev_op_ndisks;
|
||||
vdev_kobj_post_evt_func_t *vdev_op_kobj_evt_post;
|
||||
char vdev_op_type[16];
|
||||
boolean_t vdev_op_leaf;
|
||||
} vdev_ops_t;
|
||||
@@ -435,6 +437,7 @@ struct vdev {
|
||||
boolean_t vdev_isl2cache; /* was a l2cache device */
|
||||
boolean_t vdev_copy_uberblocks; /* post expand copy uberblocks */
|
||||
boolean_t vdev_resilver_deferred; /* resilver deferred */
|
||||
boolean_t vdev_kobj_flag; /* kobj event record */
|
||||
vdev_queue_t vdev_queue; /* I/O deadline schedule queue */
|
||||
vdev_cache_t vdev_cache; /* physical block cache */
|
||||
spa_aux_vdev_t *vdev_aux; /* for l2cache and spares vdevs */
|
||||
|
||||
@@ -66,10 +66,9 @@ typedef struct mzap_phys {
|
||||
} mzap_phys_t;
|
||||
|
||||
typedef struct mzap_ent {
|
||||
avl_node_t mze_node;
|
||||
int mze_chunkid;
|
||||
uint64_t mze_hash;
|
||||
uint32_t mze_cd; /* copy from mze_phys->mze_cd */
|
||||
uint32_t mze_hash;
|
||||
uint16_t mze_cd; /* copy from mze_phys->mze_cd */
|
||||
uint16_t mze_chunkid;
|
||||
} mzap_ent_t;
|
||||
|
||||
#define MZE_PHYS(zap, mze) \
|
||||
@@ -164,7 +163,7 @@ typedef struct zap {
|
||||
int16_t zap_num_entries;
|
||||
int16_t zap_num_chunks;
|
||||
int16_t zap_alloc_next;
|
||||
avl_tree_t zap_avl;
|
||||
zfs_btree_t zap_tree;
|
||||
} zap_micro;
|
||||
} zap_u;
|
||||
} zap_t;
|
||||
@@ -202,7 +201,7 @@ int zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
|
||||
krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp);
|
||||
void zap_unlockdir(zap_t *zap, void *tag);
|
||||
void zap_evict_sync(void *dbu);
|
||||
zap_name_t *zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt);
|
||||
zap_name_t *zap_name_alloc_str(zap_t *zap, const char *key, matchtype_t mt);
|
||||
void zap_name_free(zap_name_t *zn);
|
||||
int zap_hashbits(zap_t *zap);
|
||||
uint32_t zap_maxcd(zap_t *zap);
|
||||
|
||||
@@ -51,6 +51,7 @@ extern "C" {
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/kmem_cache.h>
|
||||
#include <sys/vmem.h>
|
||||
#include <sys/misc.h>
|
||||
#include <sys/taskq.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/disp.h>
|
||||
|
||||
@@ -217,9 +217,9 @@ typedef struct znode {
|
||||
|
||||
typedef struct znode_hold {
|
||||
uint64_t zh_obj; /* object id */
|
||||
kmutex_t zh_lock; /* lock serializing object access */
|
||||
avl_node_t zh_node; /* avl tree linkage */
|
||||
zfs_refcount_t zh_refcount; /* active consumer reference count */
|
||||
kmutex_t zh_lock; /* lock serializing object access */
|
||||
int zh_refcount; /* active consumer reference count */
|
||||
} znode_hold_t;
|
||||
|
||||
static inline uint64_t
|
||||
|
||||
@@ -34,9 +34,8 @@ extern "C" {
|
||||
|
||||
typedef struct zrlock {
|
||||
kmutex_t zr_mtx;
|
||||
volatile int32_t zr_refcount;
|
||||
kcondvar_t zr_cv;
|
||||
uint16_t zr_pad;
|
||||
volatile int32_t zr_refcount;
|
||||
#ifdef ZFS_DEBUG
|
||||
kthread_t *zr_owner;
|
||||
const char *zr_caller;
|
||||
|
||||
+25
-7
@@ -99,6 +99,7 @@
|
||||
<elf-symbol name='sa_validate_shareopts' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='snapshot_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='unshare_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='use_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zcmd_alloc_dst_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zcmd_expand_dst_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zcmd_free_nvlists' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
@@ -378,6 +379,7 @@
|
||||
<elf-symbol name='zpool_vdev_path_to_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_vdev_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_vdev_remove_cancel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_vdev_remove_wanted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_vdev_split' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
@@ -5069,6 +5071,9 @@
|
||||
<parameter type-id='9cf59a50'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='mkdirp' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='d50d396c'/>
|
||||
@@ -5858,6 +5863,11 @@
|
||||
<parameter type-id='c19b74c3' name='istmp'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_vdev_remove_wanted' mangled-name='zpool_vdev_remove_wanted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_remove_wanted'>
|
||||
<parameter type-id='4c81de99' name='zhp'/>
|
||||
<parameter type-id='80f4b756' name='path'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_vdev_fault' mangled-name='zpool_vdev_fault' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_fault'>
|
||||
<parameter type-id='4c81de99' name='zhp'/>
|
||||
<parameter type-id='9c313c2d' name='guid'/>
|
||||
@@ -6098,7 +6108,7 @@
|
||||
<array-type-def dimensions='1' type-id='b96825af' size-in-bits='64' id='13339fda'>
|
||||
<subrange length='8' type-id='7359adad' id='56e0c0b1'/>
|
||||
</array-type-def>
|
||||
<class-decl name='sendflags' size-in-bits='544' is-struct='yes' visibility='default' id='f6aa15be'>
|
||||
<class-decl name='sendflags' size-in-bits='576' is-struct='yes' visibility='default' id='f6aa15be'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='verbosity' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
@@ -6130,24 +6140,27 @@
|
||||
<var-decl name='progress' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='largeblock' type-id='c19b74c3' visibility='default'/>
|
||||
<var-decl name='progressastitle' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='352'>
|
||||
<var-decl name='embed_data' type-id='c19b74c3' visibility='default'/>
|
||||
<var-decl name='largeblock' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='compress' type-id='c19b74c3' visibility='default'/>
|
||||
<var-decl name='embed_data' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='416'>
|
||||
<var-decl name='raw' type-id='c19b74c3' visibility='default'/>
|
||||
<var-decl name='compress' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='backup' type-id='c19b74c3' visibility='default'/>
|
||||
<var-decl name='raw' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='480'>
|
||||
<var-decl name='holds' type-id='c19b74c3' visibility='default'/>
|
||||
<var-decl name='backup' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='holds' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='544'>
|
||||
<var-decl name='saved' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
@@ -6728,6 +6741,11 @@
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_setproctitle' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='avl_insert' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='a3681dea'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
|
||||
+66
-49
@@ -45,16 +45,21 @@
|
||||
#include <pthread.h>
|
||||
#include <sys/zfs_ioctl.h>
|
||||
#include <libzfs.h>
|
||||
#include <libzutil.h>
|
||||
#include "libzfs_impl.h"
|
||||
|
||||
#define ZDIFF_SNAPDIR "/.zfs/snapshot/"
|
||||
#define ZDIFF_PREFIX "zfs-diff-%d"
|
||||
|
||||
#define ZDIFF_ADDED '+'
|
||||
#define ZDIFF_MODIFIED 'M'
|
||||
#define ZDIFF_MODIFIED "M"
|
||||
#define ZDIFF_REMOVED '-'
|
||||
#define ZDIFF_RENAMED 'R'
|
||||
#define ZDIFF_RENAMED "R"
|
||||
|
||||
#define ZDIFF_ADDED_COLOR ANSI_GREEN
|
||||
#define ZDIFF_MODIFIED_COLOR ANSI_YELLOW
|
||||
#define ZDIFF_REMOVED_COLOR ANSI_RED
|
||||
#define ZDIFF_RENAMED_COLOR ANSI_BOLD_BLUE
|
||||
|
||||
/*
|
||||
* Given a {dsname, object id}, get the object path
|
||||
@@ -129,48 +134,54 @@ stream_bytes(FILE *fp, const char *string)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_what(FILE *fp, mode_t what)
|
||||
/*
|
||||
* Takes the type of change (like `print_file`), outputs the appropriate color
|
||||
*/
|
||||
static const char *
|
||||
type_to_color(char type)
|
||||
{
|
||||
char symbol;
|
||||
if (type == '+')
|
||||
return (ZDIFF_ADDED_COLOR);
|
||||
else if (type == '-')
|
||||
return (ZDIFF_REMOVED_COLOR);
|
||||
else if (type == 'M')
|
||||
return (ZDIFF_MODIFIED_COLOR);
|
||||
else if (type == 'R')
|
||||
return (ZDIFF_RENAMED_COLOR);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
static char
|
||||
get_what(mode_t what)
|
||||
{
|
||||
switch (what & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
symbol = 'B';
|
||||
break;
|
||||
return ('B');
|
||||
case S_IFCHR:
|
||||
symbol = 'C';
|
||||
break;
|
||||
return ('C');
|
||||
case S_IFDIR:
|
||||
symbol = '/';
|
||||
break;
|
||||
return ('/');
|
||||
#ifdef S_IFDOOR
|
||||
case S_IFDOOR:
|
||||
symbol = '>';
|
||||
break;
|
||||
return ('>');
|
||||
#endif
|
||||
case S_IFIFO:
|
||||
symbol = '|';
|
||||
break;
|
||||
return ('|');
|
||||
case S_IFLNK:
|
||||
symbol = '@';
|
||||
break;
|
||||
return ('@');
|
||||
#ifdef S_IFPORT
|
||||
case S_IFPORT:
|
||||
symbol = 'P';
|
||||
break;
|
||||
return ('P');
|
||||
#endif
|
||||
case S_IFSOCK:
|
||||
symbol = '=';
|
||||
break;
|
||||
return ('=');
|
||||
case S_IFREG:
|
||||
symbol = 'F';
|
||||
break;
|
||||
return ('F');
|
||||
default:
|
||||
symbol = '?';
|
||||
break;
|
||||
return ('?');
|
||||
}
|
||||
(void) fprintf(fp, "%c", symbol);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -189,57 +200,63 @@ static void
|
||||
print_rename(FILE *fp, differ_info_t *di, const char *old, const char *new,
|
||||
zfs_stat_t *isb)
|
||||
{
|
||||
if (isatty(fileno(fp)))
|
||||
color_start(ZDIFF_RENAMED_COLOR);
|
||||
if (di->timestamped)
|
||||
(void) fprintf(fp, "%10lld.%09lld\t",
|
||||
(longlong_t)isb->zs_ctime[0],
|
||||
(longlong_t)isb->zs_ctime[1]);
|
||||
(void) fprintf(fp, "%c\t", ZDIFF_RENAMED);
|
||||
if (di->classify) {
|
||||
print_what(fp, isb->zs_mode);
|
||||
(void) fprintf(fp, "\t");
|
||||
}
|
||||
(void) fputs(ZDIFF_RENAMED "\t", fp);
|
||||
if (di->classify)
|
||||
(void) fprintf(fp, "%c\t", get_what(isb->zs_mode));
|
||||
print_cmn(fp, di, old);
|
||||
if (di->scripted)
|
||||
(void) fprintf(fp, "\t");
|
||||
else
|
||||
(void) fprintf(fp, " -> ");
|
||||
(void) fputs(di->scripted ? "\t" : " -> ", fp);
|
||||
print_cmn(fp, di, new);
|
||||
(void) fprintf(fp, "\n");
|
||||
(void) fputc('\n', fp);
|
||||
|
||||
if (isatty(fileno(fp)))
|
||||
color_end();
|
||||
}
|
||||
|
||||
static void
|
||||
print_link_change(FILE *fp, differ_info_t *di, int delta, const char *file,
|
||||
zfs_stat_t *isb)
|
||||
{
|
||||
if (isatty(fileno(fp)))
|
||||
color_start(ZDIFF_MODIFIED_COLOR);
|
||||
|
||||
if (di->timestamped)
|
||||
(void) fprintf(fp, "%10lld.%09lld\t",
|
||||
(longlong_t)isb->zs_ctime[0],
|
||||
(longlong_t)isb->zs_ctime[1]);
|
||||
(void) fprintf(fp, "%c\t", ZDIFF_MODIFIED);
|
||||
if (di->classify) {
|
||||
print_what(fp, isb->zs_mode);
|
||||
(void) fprintf(fp, "\t");
|
||||
}
|
||||
(void) fputs(ZDIFF_MODIFIED "\t", fp);
|
||||
if (di->classify)
|
||||
(void) fprintf(fp, "%c\t", get_what(isb->zs_mode));
|
||||
print_cmn(fp, di, file);
|
||||
(void) fprintf(fp, "\t(%+d)", delta);
|
||||
(void) fprintf(fp, "\n");
|
||||
(void) fprintf(fp, "\t(%+d)\n", delta);
|
||||
if (isatty(fileno(fp)))
|
||||
color_end();
|
||||
}
|
||||
|
||||
static void
|
||||
print_file(FILE *fp, differ_info_t *di, char type, const char *file,
|
||||
zfs_stat_t *isb)
|
||||
{
|
||||
if (isatty(fileno(fp)))
|
||||
color_start(type_to_color(type));
|
||||
|
||||
if (di->timestamped)
|
||||
(void) fprintf(fp, "%10lld.%09lld\t",
|
||||
(longlong_t)isb->zs_ctime[0],
|
||||
(longlong_t)isb->zs_ctime[1]);
|
||||
(void) fprintf(fp, "%c\t", type);
|
||||
if (di->classify) {
|
||||
print_what(fp, isb->zs_mode);
|
||||
(void) fprintf(fp, "\t");
|
||||
}
|
||||
if (di->classify)
|
||||
(void) fprintf(fp, "%c\t", get_what(isb->zs_mode));
|
||||
print_cmn(fp, di, file);
|
||||
(void) fprintf(fp, "\n");
|
||||
(void) fputc('\n', fp);
|
||||
|
||||
if (isatty(fileno(fp)))
|
||||
color_end();
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -332,7 +349,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
|
||||
print_link_change(fp, di, change,
|
||||
change > 0 ? fobjname : tobjname, &tsb);
|
||||
} else if (strcmp(fobjname, tobjname) == 0) {
|
||||
print_file(fp, di, ZDIFF_MODIFIED, fobjname, &tsb);
|
||||
print_file(fp, di, *ZDIFF_MODIFIED, fobjname, &tsb);
|
||||
} else {
|
||||
print_rename(fp, di, fobjname, tobjname, &tsb);
|
||||
}
|
||||
|
||||
@@ -3051,7 +3051,7 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
|
||||
|
||||
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, &zc.zc_guid) == 0);
|
||||
|
||||
if (avail_spare)
|
||||
if (!(flags & ZFS_ONLINE_SPARE) && avail_spare)
|
||||
return (zfs_error(hdl, EZFS_ISSPARE, msg));
|
||||
|
||||
if ((flags & ZFS_ONLINE_EXPAND ||
|
||||
@@ -3158,6 +3158,40 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the specified vdev asynchronously from the configuration, so
|
||||
* that it may come ONLINE if reinserted. This is called from zed on
|
||||
* Udev remove event.
|
||||
* Note: We also have a similar function zpool_vdev_remove() that
|
||||
* removes the vdev from the pool.
|
||||
*/
|
||||
int
|
||||
zpool_vdev_remove_wanted(zpool_handle_t *zhp, const char *path)
|
||||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
char errbuf[1024];
|
||||
nvlist_t *tgt;
|
||||
boolean_t avail_spare, l2cache;
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
|
||||
(void) snprintf(errbuf, sizeof (errbuf),
|
||||
dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
|
||||
NULL)) == NULL)
|
||||
return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
|
||||
|
||||
zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
|
||||
|
||||
zc.zc_cookie = VDEV_STATE_REMOVED;
|
||||
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
|
||||
return (0);
|
||||
|
||||
return (zpool_standard_error(hdl, errno, errbuf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the given vdev faulted.
|
||||
*/
|
||||
|
||||
@@ -83,6 +83,9 @@ typedef struct progress_arg {
|
||||
boolean_t pa_parsable;
|
||||
boolean_t pa_estimate;
|
||||
int pa_verbosity;
|
||||
boolean_t pa_astitle;
|
||||
boolean_t pa_progress;
|
||||
uint64_t pa_size;
|
||||
} progress_arg_t;
|
||||
|
||||
static int
|
||||
@@ -712,6 +715,7 @@ typedef struct send_dump_data {
|
||||
boolean_t seenfrom, seento, replicate, doall, fromorigin;
|
||||
boolean_t dryrun, parsable, progress, embed_data, std_out;
|
||||
boolean_t large_block, compress, raw, holds;
|
||||
boolean_t progressastitle;
|
||||
int outfd;
|
||||
boolean_t err;
|
||||
nvlist_t *fss;
|
||||
@@ -904,6 +908,7 @@ send_progress_thread(void *arg)
|
||||
zfs_handle_t *zhp = pa->pa_zhp;
|
||||
uint64_t bytes;
|
||||
uint64_t blocks;
|
||||
uint64_t total = pa->pa_size / 100;
|
||||
char buf[16];
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
@@ -922,7 +927,7 @@ send_progress_thread(void *arg)
|
||||
return ((void *)(uintptr_t)err);
|
||||
}
|
||||
|
||||
if (firstloop && !pa->pa_parsable) {
|
||||
if (firstloop && !pa->pa_parsable && pa->pa_progress) {
|
||||
(void) fprintf(stderr,
|
||||
"TIME %s %sSNAPSHOT %s\n",
|
||||
pa->pa_estimate ? "BYTES" : " SENT",
|
||||
@@ -934,6 +939,17 @@ send_progress_thread(void *arg)
|
||||
(void) time(&t);
|
||||
tm = localtime(&t);
|
||||
|
||||
if (pa->pa_astitle) {
|
||||
char buf_bytes[16];
|
||||
char buf_size[16];
|
||||
int pct;
|
||||
zfs_nicenum(bytes, buf_bytes, sizeof (buf_bytes));
|
||||
zfs_nicenum(pa->pa_size, buf_size, sizeof (buf_size));
|
||||
pct = (total > 0) ? bytes / total : 100;
|
||||
zfs_setproctitle("sending %s (%d%%: %s/%s)",
|
||||
zhp->zfs_name, MIN(pct, 100), buf_bytes, buf_size);
|
||||
}
|
||||
|
||||
if (pa->pa_verbosity >= 2 && pa->pa_parsable) {
|
||||
(void) fprintf(stderr,
|
||||
"%02d:%02d:%02d\t%llu\t%llu\t%s\n",
|
||||
@@ -950,7 +966,7 @@ send_progress_thread(void *arg)
|
||||
(void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
(u_longlong_t)bytes, zhp->zfs_name);
|
||||
} else {
|
||||
} else if (pa->pa_progress) {
|
||||
zfs_nicebytes(bytes, buf, sizeof (buf));
|
||||
(void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n",
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
@@ -1114,12 +1130,15 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
|
||||
* If progress reporting is requested, spawn a new thread to
|
||||
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
|
||||
*/
|
||||
if (sdd->progress) {
|
||||
if (sdd->progress || sdd->progressastitle) {
|
||||
pa.pa_zhp = zhp;
|
||||
pa.pa_fd = sdd->outfd;
|
||||
pa.pa_parsable = sdd->parsable;
|
||||
pa.pa_estimate = B_FALSE;
|
||||
pa.pa_verbosity = sdd->verbosity;
|
||||
pa.pa_size = sdd->size;
|
||||
pa.pa_astitle = sdd->progressastitle;
|
||||
pa.pa_progress = sdd->progress;
|
||||
|
||||
if ((err = pthread_create(&tid, NULL,
|
||||
send_progress_thread, &pa)) != 0) {
|
||||
@@ -1131,7 +1150,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
|
||||
err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
|
||||
fromorigin, sdd->outfd, flags, sdd->debugnv);
|
||||
|
||||
if (sdd->progress) {
|
||||
if (sdd->progress || sdd->progressastitle) {
|
||||
void *status = NULL;
|
||||
(void) pthread_cancel(tid);
|
||||
(void) pthread_join(tid, &status);
|
||||
@@ -1462,7 +1481,7 @@ lzc_flags_from_sendflags(const sendflags_t *flags)
|
||||
static int
|
||||
estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
uint64_t resumeobj, uint64_t resumeoff, uint64_t bytes,
|
||||
const char *redactbook, char *errbuf)
|
||||
const char *redactbook, char *errbuf, uint64_t *sizep)
|
||||
{
|
||||
uint64_t size;
|
||||
FILE *fout = flags->dryrun ? stdout : stderr;
|
||||
@@ -1470,7 +1489,7 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
int err = 0;
|
||||
pthread_t ptid;
|
||||
|
||||
if (flags->progress) {
|
||||
if (flags->progress || flags->progressastitle) {
|
||||
pa.pa_zhp = zhp;
|
||||
pa.pa_fd = fd;
|
||||
pa.pa_parsable = flags->parsable;
|
||||
@@ -1489,8 +1508,9 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
err = lzc_send_space_resume_redacted(zhp->zfs_name, from,
|
||||
lzc_flags_from_sendflags(flags), resumeobj, resumeoff, bytes,
|
||||
redactbook, fd, &size);
|
||||
*sizep = size;
|
||||
|
||||
if (flags->progress) {
|
||||
if (flags->progress || flags->progressastitle) {
|
||||
void *status = NULL;
|
||||
(void) pthread_cancel(ptid);
|
||||
(void) pthread_join(ptid, &status);
|
||||
@@ -1505,6 +1525,9 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
}
|
||||
}
|
||||
|
||||
if (!flags->progress && !flags->parsable)
|
||||
return (err);
|
||||
|
||||
if (err != 0) {
|
||||
zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
|
||||
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
|
||||
@@ -1638,6 +1661,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
uint64_t *redact_snap_guids = NULL;
|
||||
int num_redact_snaps = 0;
|
||||
char *redact_book = NULL;
|
||||
uint64_t size = 0;
|
||||
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
"cannot resume send"));
|
||||
@@ -1731,7 +1755,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
}
|
||||
}
|
||||
|
||||
if (flags->verbosity != 0) {
|
||||
if (flags->verbosity != 0 || flags->progressastitle) {
|
||||
/*
|
||||
* Some of these may have come from the resume token, set them
|
||||
* here for size estimate purposes.
|
||||
@@ -1748,7 +1772,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
if (lzc_flags & LZC_SEND_FLAG_SAVED)
|
||||
tmpflags.saved = B_TRUE;
|
||||
error = estimate_size(zhp, fromname, outfd, &tmpflags,
|
||||
resumeobj, resumeoff, bytes, redact_book, errbuf);
|
||||
resumeobj, resumeoff, bytes, redact_book, errbuf, &size);
|
||||
}
|
||||
|
||||
if (!flags->dryrun) {
|
||||
@@ -1758,12 +1782,15 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
* If progress reporting is requested, spawn a new thread to
|
||||
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
|
||||
*/
|
||||
if (flags->progress) {
|
||||
if (flags->progress || flags->progressastitle) {
|
||||
pa.pa_zhp = zhp;
|
||||
pa.pa_fd = outfd;
|
||||
pa.pa_parsable = flags->parsable;
|
||||
pa.pa_estimate = B_FALSE;
|
||||
pa.pa_verbosity = flags->verbosity;
|
||||
pa.pa_size = size;
|
||||
pa.pa_astitle = flags->progressastitle;
|
||||
pa.pa_progress = flags->progress;
|
||||
|
||||
error = pthread_create(&tid, NULL,
|
||||
send_progress_thread, &pa);
|
||||
@@ -1780,7 +1807,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
if (redact_book != NULL)
|
||||
free(redact_book);
|
||||
|
||||
if (flags->progress) {
|
||||
if (flags->progress || flags->progress) {
|
||||
void *status = NULL;
|
||||
(void) pthread_cancel(tid);
|
||||
(void) pthread_join(tid, &status);
|
||||
@@ -1790,6 +1817,7 @@ zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
(void) snprintf(errbuf, sizeof (errbuf),
|
||||
dgettext(TEXT_DOMAIN,
|
||||
"progress thread exited nonzero"));
|
||||
zfs_close(zhp);
|
||||
return (zfs_standard_error(hdl, error, errbuf));
|
||||
}
|
||||
}
|
||||
@@ -2199,6 +2227,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
sdd.verbosity = flags->verbosity;
|
||||
sdd.parsable = flags->parsable;
|
||||
sdd.progress = flags->progress;
|
||||
sdd.progressastitle = flags->progressastitle;
|
||||
sdd.dryrun = flags->dryrun;
|
||||
sdd.large_block = flags->largeblock;
|
||||
sdd.embed_data = flags->embed_data;
|
||||
@@ -2410,6 +2439,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
char *name = zhp->zfs_name;
|
||||
pthread_t ptid;
|
||||
progress_arg_t pa = { 0 };
|
||||
uint64_t size = 0;
|
||||
|
||||
char errbuf[1024];
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
@@ -2492,9 +2522,9 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
/*
|
||||
* Perform size estimate if verbose was specified.
|
||||
*/
|
||||
if (flags->verbosity != 0) {
|
||||
if (flags->verbosity != 0 || flags->progressastitle) {
|
||||
err = estimate_size(zhp, from, fd, flags, 0, 0, 0, redactbook,
|
||||
errbuf);
|
||||
errbuf, &size);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
}
|
||||
@@ -2506,12 +2536,15 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
* If progress reporting is requested, spawn a new thread to poll
|
||||
* ZFS_IOC_SEND_PROGRESS at a regular interval.
|
||||
*/
|
||||
if (flags->progress) {
|
||||
if (flags->progress || flags->progressastitle) {
|
||||
pa.pa_zhp = zhp;
|
||||
pa.pa_fd = fd;
|
||||
pa.pa_parsable = flags->parsable;
|
||||
pa.pa_estimate = B_FALSE;
|
||||
pa.pa_verbosity = flags->verbosity;
|
||||
pa.pa_size = size;
|
||||
pa.pa_astitle = flags->progressastitle;
|
||||
pa.pa_progress = flags->progress;
|
||||
|
||||
err = pthread_create(&ptid, NULL,
|
||||
send_progress_thread, &pa);
|
||||
@@ -2525,7 +2558,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
|
||||
err = lzc_send_redacted(name, from, fd,
|
||||
lzc_flags_from_sendflags(flags), redactbook);
|
||||
|
||||
if (flags->progress) {
|
||||
if (flags->progress || flags->progressastitle) {
|
||||
void *status = NULL;
|
||||
(void) pthread_cancel(ptid);
|
||||
(void) pthread_join(ptid, &status);
|
||||
@@ -3966,6 +3999,15 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* For plain replicated send, we can ignore encryption
|
||||
* properties other than first stream
|
||||
*/
|
||||
if ((zfs_prop_encryption_key_param(prop) || prop ==
|
||||
ZFS_PROP_ENCRYPTION) && !newfs && recursive && !raw) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* incremental streams can only exclude encryption properties */
|
||||
if ((zfs_prop_encryption_key_param(prop) ||
|
||||
prop == ZFS_PROP_ENCRYPTION) && !newfs &&
|
||||
@@ -4065,7 +4107,8 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
|
||||
if (cp != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
if (!raw && zfs_crypto_create(hdl, namebuf, voprops, NULL,
|
||||
if (!raw && !(!newfs && recursive) &&
|
||||
zfs_crypto_create(hdl, namebuf, voprops, NULL,
|
||||
B_FALSE, wkeydata_out, wkeylen_out) != 0) {
|
||||
fnvlist_free(voprops);
|
||||
ret = zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
|
||||
|
||||
+18
-11
@@ -2027,7 +2027,7 @@ zfs_version_print(void)
|
||||
* Return 1 if the user requested ANSI color output, and our terminal supports
|
||||
* it. Return 0 for no color.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
use_color(void)
|
||||
{
|
||||
static int use_color = -1;
|
||||
@@ -2073,31 +2073,38 @@ use_color(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* color_start() and color_end() are used for when you want to colorize a block
|
||||
* of text. For example:
|
||||
* The functions color_start() and color_end() are used for when you want
|
||||
* to colorize a block of text.
|
||||
*
|
||||
* color_start(ANSI_RED_FG)
|
||||
* For example:
|
||||
* color_start(ANSI_RED)
|
||||
* printf("hello");
|
||||
* printf("world");
|
||||
* color_end();
|
||||
*/
|
||||
void
|
||||
color_start(char *color)
|
||||
color_start(const char *color)
|
||||
{
|
||||
if (use_color())
|
||||
printf("%s", color);
|
||||
if (color && use_color()) {
|
||||
fputs(color, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
color_end(void)
|
||||
{
|
||||
if (use_color())
|
||||
printf(ANSI_RESET);
|
||||
if (use_color()) {
|
||||
fputs(ANSI_RESET, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/* printf() with a color. If color is NULL, then do a normal printf. */
|
||||
/*
|
||||
* printf() with a color. If color is NULL, then do a normal printf.
|
||||
*/
|
||||
int
|
||||
printf_color(char *color, char *format, ...)
|
||||
printf_color(const char *color, char *format, ...)
|
||||
{
|
||||
va_list aptr;
|
||||
int rc;
|
||||
|
||||
@@ -35,6 +35,22 @@
|
||||
void
|
||||
libzfs_set_pipe_max(int infd)
|
||||
{
|
||||
#if __linux__
|
||||
/*
|
||||
* Sadly, Linux has an unfixed deadlock if you do SETPIPE_SZ on a pipe
|
||||
* with data in it.
|
||||
* cf. #13232, https://bugzilla.kernel.org/show_bug.cgi?id=212295
|
||||
*
|
||||
* And since the problem is in waking up the writer, there's nothing
|
||||
* we can do about it from here.
|
||||
*
|
||||
* So if people want to, they can set this, but they
|
||||
* may regret it...
|
||||
*/
|
||||
if (getenv("ZFS_SET_PIPE_MAX") == NULL)
|
||||
return;
|
||||
#endif
|
||||
|
||||
FILE *procf = fopen("/proc/sys/fs/pipe-max-size", "re");
|
||||
|
||||
if (procf != NULL) {
|
||||
|
||||
@@ -272,6 +272,8 @@
|
||||
<elf-symbol name='zfs_niceraw' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_nicetime' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_resolve_shortname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_setproctitle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_setproctitle_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_strcmp_pathname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_strip_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_strip_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
@@ -3340,6 +3342,30 @@
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='os/linux/zutil_setproctitle.c' language='LANG_C99'>
|
||||
<function-decl name='warnx' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='setenv' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_setproctitle_init' mangled-name='zfs_setproctitle_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle_init'>
|
||||
<parameter type-id='95e97e5e' name='argc'/>
|
||||
<parameter type-id='9b23c9ad' name='argv'/>
|
||||
<parameter type-id='9b23c9ad' name='envp'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_setproctitle' mangled-name='zfs_setproctitle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle'>
|
||||
<parameter type-id='80f4b756' name='fmt'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='zutil_device_path.c' language='LANG_C99'>
|
||||
<qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
|
||||
<qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
|
||||
|
||||
@@ -18,6 +18,7 @@ USER_C = \
|
||||
|
||||
if BUILD_LINUX
|
||||
USER_C += \
|
||||
os/linux/zutil_setproctitle.c \
|
||||
os/linux/zutil_device_path_os.c \
|
||||
os/linux/zutil_import_os.c \
|
||||
os/linux/zutil_compat.c
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
|
||||
*
|
||||
* 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <libzutil.h>
|
||||
|
||||
static struct {
|
||||
/* Original value. */
|
||||
const char *arg0;
|
||||
|
||||
/* Title space available. */
|
||||
char *base, *end;
|
||||
|
||||
/* Pointer to original nul character within base. */
|
||||
char *nul;
|
||||
|
||||
boolean_t warned;
|
||||
boolean_t reset;
|
||||
int error;
|
||||
} SPT;
|
||||
|
||||
#define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/')
|
||||
#define SPT_MAXTITLE 255
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
static const char *
|
||||
getprogname(void)
|
||||
{
|
||||
return (__progname);
|
||||
}
|
||||
|
||||
static void
|
||||
setprogname(const char *progname)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = strlen(progname); i > 0; i--) {
|
||||
if (LIBBSD_IS_PATHNAME_SEPARATOR(progname[i - 1])) {
|
||||
__progname = progname + i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
__progname = progname;
|
||||
}
|
||||
|
||||
|
||||
static inline size_t
|
||||
spt_min(size_t a, size_t b)
|
||||
{
|
||||
return ((a < b) ? a : b);
|
||||
}
|
||||
|
||||
/*
|
||||
* For discussion on the portability of the various methods, see
|
||||
* https://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
|
||||
*/
|
||||
static int
|
||||
spt_clearenv(void)
|
||||
{
|
||||
char **tmp;
|
||||
|
||||
tmp = malloc(sizeof (*tmp));
|
||||
if (tmp == NULL)
|
||||
return (errno);
|
||||
|
||||
tmp[0] = NULL;
|
||||
environ = tmp;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
spt_copyenv(int envc, char *envp[])
|
||||
{
|
||||
char **envcopy;
|
||||
char *eq;
|
||||
int envsize;
|
||||
int i, error;
|
||||
|
||||
if (environ != envp)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Make a copy of the old environ array of pointers, in case
|
||||
* clearenv() or setenv() is implemented to free the internal
|
||||
* environ array, because we will need to access the old environ
|
||||
* contents to make the new copy.
|
||||
*/
|
||||
envsize = (envc + 1) * sizeof (char *);
|
||||
envcopy = malloc(envsize);
|
||||
if (envcopy == NULL)
|
||||
return (errno);
|
||||
memcpy(envcopy, envp, envsize);
|
||||
|
||||
error = spt_clearenv();
|
||||
if (error) {
|
||||
environ = envp;
|
||||
free(envcopy);
|
||||
return (error);
|
||||
}
|
||||
|
||||
for (i = 0; envcopy[i]; i++) {
|
||||
eq = strchr(envcopy[i], '=');
|
||||
if (eq == NULL)
|
||||
continue;
|
||||
|
||||
*eq = '\0';
|
||||
if (setenv(envcopy[i], eq + 1, 1) < 0)
|
||||
error = errno;
|
||||
*eq = '=';
|
||||
|
||||
if (error) {
|
||||
environ = envp;
|
||||
free(envcopy);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispose of the shallow copy, now that we've finished transfering
|
||||
* the old environment.
|
||||
*/
|
||||
free(envcopy);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
spt_copyargs(int argc, char *argv[])
|
||||
{
|
||||
char *tmp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
|
||||
if (argv[i] == NULL)
|
||||
continue;
|
||||
|
||||
tmp = strdup(argv[i]);
|
||||
if (tmp == NULL)
|
||||
return (errno);
|
||||
|
||||
argv[i] = tmp;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
zfs_setproctitle_init(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
char *base, *end, *nul, *tmp;
|
||||
int i, envc, error;
|
||||
|
||||
/* Try to make sure we got called with main() arguments. */
|
||||
if (argc < 0)
|
||||
return;
|
||||
|
||||
base = argv[0];
|
||||
if (base == NULL)
|
||||
return;
|
||||
|
||||
nul = base + strlen(base);
|
||||
end = nul + 1;
|
||||
|
||||
for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
|
||||
if (argv[i] == NULL || argv[i] != end)
|
||||
continue;
|
||||
|
||||
end = argv[i] + strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
for (i = 0; envp[i]; i++) {
|
||||
if (envp[i] != end)
|
||||
continue;
|
||||
|
||||
end = envp[i] + strlen(envp[i]) + 1;
|
||||
}
|
||||
envc = i;
|
||||
|
||||
SPT.arg0 = strdup(argv[0]);
|
||||
if (SPT.arg0 == NULL) {
|
||||
SPT.error = errno;
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = strdup(getprogname());
|
||||
if (tmp == NULL) {
|
||||
SPT.error = errno;
|
||||
return;
|
||||
}
|
||||
setprogname(tmp);
|
||||
|
||||
error = spt_copyenv(envc, envp);
|
||||
if (error) {
|
||||
SPT.error = error;
|
||||
return;
|
||||
}
|
||||
|
||||
error = spt_copyargs(argc, argv);
|
||||
if (error) {
|
||||
SPT.error = error;
|
||||
return;
|
||||
}
|
||||
|
||||
SPT.nul = nul;
|
||||
SPT.base = base;
|
||||
SPT.end = end;
|
||||
}
|
||||
|
||||
void
|
||||
zfs_setproctitle(const char *fmt, ...)
|
||||
{
|
||||
/* Use buffer in case argv[0] is passed. */
|
||||
char buf[SPT_MAXTITLE + 1];
|
||||
va_list ap;
|
||||
char *nul;
|
||||
int len;
|
||||
if (SPT.base == NULL) {
|
||||
if (!SPT.warned) {
|
||||
warnx("setproctitle not initialized, please"
|
||||
"call zfs_setproctitle_init()");
|
||||
SPT.warned = B_TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fmt) {
|
||||
if (fmt[0] == '-') {
|
||||
/* Skip program name prefix. */
|
||||
fmt++;
|
||||
len = 0;
|
||||
} else {
|
||||
/* Print program name heading for grep. */
|
||||
snprintf(buf, sizeof (buf), "%s: ", getprogname());
|
||||
len = strlen(buf);
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
len += vsnprintf(buf + len, sizeof (buf) - len, fmt, ap);
|
||||
va_end(ap);
|
||||
} else {
|
||||
len = snprintf(buf, sizeof (buf), "%s", SPT.arg0);
|
||||
}
|
||||
|
||||
if (len <= 0) {
|
||||
SPT.error = errno;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SPT.reset) {
|
||||
memset(SPT.base, 0, SPT.end - SPT.base);
|
||||
SPT.reset = B_TRUE;
|
||||
} else {
|
||||
memset(SPT.base, 0, spt_min(sizeof (buf), SPT.end - SPT.base));
|
||||
}
|
||||
|
||||
len = spt_min(len, spt_min(sizeof (buf), SPT.end - SPT.base) - 1);
|
||||
memcpy(SPT.base, buf, len);
|
||||
nul = SPT.base + len;
|
||||
|
||||
if (nul < SPT.nul) {
|
||||
*SPT.nul = '.';
|
||||
} else if (nul == SPT.nul && nul + 1 < SPT.end) {
|
||||
*SPT.nul = ' ';
|
||||
*++nul = '\0';
|
||||
}
|
||||
}
|
||||
+14
-1
@@ -15,7 +15,7 @@
|
||||
.\" own identifying information:
|
||||
.\" Portions Copyright [yyyy] [name of copyright owner]
|
||||
.\"
|
||||
.Dd June 1, 2021
|
||||
.Dd January 10, 2023
|
||||
.Dt ZFS 4
|
||||
.Os
|
||||
.
|
||||
@@ -233,6 +233,12 @@ relative to the pool.
|
||||
Make some blocks above a certain size be gang blocks.
|
||||
This option is used by the test suite to facilitate testing.
|
||||
.
|
||||
.It Sy zfs_default_bs Ns = Ns Sy 9 Po 512 B Pc Pq int
|
||||
Default dnode block size as a power of 2.
|
||||
.
|
||||
.It Sy zfs_default_ibs Ns = Ns Sy 17 Po 128 KiB Pc Pq int
|
||||
Default dnode indirect block size as a power of 2.
|
||||
.
|
||||
.It Sy zfs_history_output_max Ns = Ns Sy 1048576 Ns B Ns B Po 1MB Pc Pq int
|
||||
When attempting to log an output nvlist of an ioctl in the on-disk history,
|
||||
the output will not be stored if it is larger than this size (in bytes).
|
||||
@@ -2126,6 +2132,13 @@ On very fragmented pools, lowering this
|
||||
.Pq typically to Sy 36kB
|
||||
can improve performance.
|
||||
.
|
||||
.It Sy zil_min_commit_timeout Ns = Ns Sy 5000 Pq u64
|
||||
This sets the minimum delay in nanoseconds ZIL care to delay block commit,
|
||||
waiting for more records.
|
||||
If ZIL writes are too fast, kernel may not be able sleep for so short interval,
|
||||
increasing log latency above allowed by
|
||||
.Sy zfs_commit_timeout_pct .
|
||||
.
|
||||
.It Sy zil_nocacheflush Ns = Ns Sy 0 Ns | Ns 1 Pq int
|
||||
Disable the cache flush commands that are normally sent to disk by
|
||||
the ZIL after an LWB write has completed.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" SPDX-License-Identifier: 0BSD
|
||||
.\"
|
||||
.Dd April 4, 2022
|
||||
.Dd March 28, 2023
|
||||
.Dt DRACUT.ZFS 7
|
||||
.Os
|
||||
.
|
||||
@@ -28,13 +28,13 @@ zfs-import-scan.service \(da \(da | zfs-import-c
|
||||
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
|
||||
| sysroot.mount \(<-\(em\(em\(em dracut-zfs-generator
|
||||
| |
|
||||
| \(da
|
||||
| initrd-root-fs.target \(<-\(em zfs-nonroot-necessities.service
|
||||
| | |
|
||||
| \(da |
|
||||
\(da dracut-mount.service |
|
||||
zfs-snapshot-bootfs.service | |
|
||||
@@ -42,7 +42,7 @@ zfs-import-scan.service \(da \(da | zfs-import-c
|
||||
\(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/
|
||||
| /sysroot/{usr,etc,lib,&c.} \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/
|
||||
| |
|
||||
| \(da
|
||||
| initrd-fs.target
|
||||
|
||||
+13
-11
@@ -29,7 +29,7 @@
|
||||
.\" Copyright 2018 Nexenta Systems, Inc.
|
||||
.\" Copyright 2019 Joyent, Inc.
|
||||
.\"
|
||||
.Dd April 15, 2021
|
||||
.Dd January 12, 2023
|
||||
.Dt ZFS-SEND 8
|
||||
.Os
|
||||
.
|
||||
@@ -39,28 +39,28 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl DLPRbcehnpsvw
|
||||
.Op Fl DLPVRbcehnpsvw
|
||||
.Op Oo Fl I Ns | Ns Fl i Oc Ar snapshot
|
||||
.Ar snapshot
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl DLPcensvw
|
||||
.Op Fl DLPVcensvw
|
||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Fl -redact Ar redaction_bookmark
|
||||
.Op Fl DLPcenpv
|
||||
.Op Fl DLPVcenpv
|
||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||
.Ar snapshot
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl Penv
|
||||
.Op Fl PVenv
|
||||
.Fl t
|
||||
.Ar receive_resume_token
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl Pnv
|
||||
.Op Fl PVnv
|
||||
.Fl S Ar filesystem
|
||||
.Nm zfs
|
||||
.Cm redact
|
||||
@@ -72,7 +72,7 @@
|
||||
.It Xo
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl DLPRbcehnpvw
|
||||
.Op Fl DLPVRbcehnpvw
|
||||
.Op Oo Fl I Ns | Ns Fl i Oc Ar snapshot
|
||||
.Ar snapshot
|
||||
.Xc
|
||||
@@ -140,6 +140,8 @@ If the
|
||||
flag is used to send encrypted datasets, then
|
||||
.Fl w
|
||||
must also be specified.
|
||||
.It Fl V , -proctitle
|
||||
Set the process title to a per-second report of how much data has been sent.
|
||||
.It Fl e , -embed
|
||||
Generate a more compact stream by using
|
||||
.Sy WRITE_EMBEDDED
|
||||
@@ -285,7 +287,7 @@ You will be able to receive your streams on future versions of ZFS.
|
||||
.It Xo
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl DLPcenvw
|
||||
.Op Fl DLPVcenvw
|
||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||
.Xc
|
||||
@@ -417,7 +419,7 @@ This information includes a per-second report of how much data has been sent.
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Fl -redact Ar redaction_bookmark
|
||||
.Op Fl DLPcenpv
|
||||
.Op Fl DLPVcenpv
|
||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||
.Ar snapshot
|
||||
.Xc
|
||||
@@ -511,7 +513,7 @@ raw sends and redacted sends cannot be combined at this time.
|
||||
.It Xo
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl Penv
|
||||
.Op Fl PVenv
|
||||
.Fl t
|
||||
.Ar receive_resume_token
|
||||
.Xc
|
||||
@@ -526,7 +528,7 @@ for more details.
|
||||
.It Xo
|
||||
.Nm zfs
|
||||
.Cm send
|
||||
.Op Fl Pnv
|
||||
.Op Fl PVnv
|
||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||
.Fl S
|
||||
.Ar filesystem
|
||||
|
||||
@@ -704,6 +704,14 @@ command will be undone if the share is ever unshared (like via a reboot).
|
||||
.El
|
||||
.
|
||||
.Sh ENVIRONMENT VARIABLES
|
||||
.Bl -tag -width "ZFS_COLOR"
|
||||
.It Sy ZFS_COLOR
|
||||
Use ANSI color in
|
||||
.Nm zfs Cm diff
|
||||
and
|
||||
.Nm zfs Cm list
|
||||
output.
|
||||
.El
|
||||
.Bl -tag -width "ZFS_MOUNT_HELPER"
|
||||
.It Sy ZFS_MOUNT_HELPER
|
||||
Cause
|
||||
@@ -713,6 +721,14 @@ to use
|
||||
to mount ZFS datasets.
|
||||
This option is provided for backwards compatibility with older ZFS versions.
|
||||
.El
|
||||
.Bl -tag -width "ZFS_SET_PIPE_MAX"
|
||||
.It Sy ZFS_SET_PIPE_MAX
|
||||
Tells
|
||||
.Nm zfs
|
||||
to set the maximum pipe size for sends/recieves.
|
||||
Disabled by default on Linux
|
||||
due to an unfixed deadlock in Linux's pipe size handling code.
|
||||
.El
|
||||
.
|
||||
.Sh INTERFACE STABILITY
|
||||
.Sy Committed .
|
||||
|
||||
@@ -433,6 +433,8 @@ to dump core on exit for the purposes of running
|
||||
.It Sy ZFS_COLOR
|
||||
Use ANSI color in
|
||||
.Nm zpool status
|
||||
and
|
||||
.Nm zpool iostat
|
||||
output.
|
||||
.It Sy ZPOOL_IMPORT_PATH
|
||||
The search path for devices or files to use with the pool.
|
||||
|
||||
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/kstat.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/zone.h>
|
||||
|
||||
static MALLOC_DEFINE(M_KSTAT, "kstat_data", "Kernel statistics");
|
||||
|
||||
@@ -134,6 +135,55 @@ kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
|
||||
return (sysctl_handle_string(oidp, val, len, req));
|
||||
}
|
||||
|
||||
static int
|
||||
kstat_sysctl_dataset(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
kstat_t *ksp = arg1;
|
||||
kstat_named_t *ksent;
|
||||
kstat_named_t *ksent_ds;
|
||||
uint64_t val;
|
||||
char *ds_name;
|
||||
uint32_t ds_len = 0;
|
||||
|
||||
ksent_ds = ksent = ksp->ks_data;
|
||||
ds_name = KSTAT_NAMED_STR_PTR(ksent_ds);
|
||||
ds_len = KSTAT_NAMED_STR_BUFLEN(ksent_ds);
|
||||
ds_name[ds_len-1] = '\0';
|
||||
|
||||
if (!zone_dataset_visible(ds_name, NULL)) {
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/* Select the correct element */
|
||||
ksent += arg2;
|
||||
/* Update the aggsums before reading */
|
||||
(void) ksp->ks_update(ksp, KSTAT_READ);
|
||||
val = ksent->value.ui64;
|
||||
|
||||
return (sysctl_handle_64(oidp, &val, 0, req));
|
||||
}
|
||||
|
||||
static int
|
||||
kstat_sysctl_dataset_string(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
kstat_t *ksp = arg1;
|
||||
kstat_named_t *ksent = ksp->ks_data;
|
||||
char *val;
|
||||
uint32_t len = 0;
|
||||
|
||||
/* Select the correct element */
|
||||
ksent += arg2;
|
||||
val = KSTAT_NAMED_STR_PTR(ksent);
|
||||
len = KSTAT_NAMED_STR_BUFLEN(ksent);
|
||||
val[len-1] = '\0';
|
||||
|
||||
if (!zone_dataset_visible(val, NULL)) {
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
return (sysctl_handle_string(oidp, val, len, req));
|
||||
}
|
||||
|
||||
static int
|
||||
kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
@@ -422,11 +472,20 @@ kstat_install_named(kstat_t *ksp)
|
||||
ksp, i, kstat_sysctl, "Q", namelast);
|
||||
break;
|
||||
case KSTAT_DATA_UINT64:
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
|
||||
OID_AUTO, namelast,
|
||||
CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, i, kstat_sysctl, "QU", namelast);
|
||||
if (strcmp(ksp->ks_class, "dataset") == 0) {
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
|
||||
OID_AUTO, namelast,
|
||||
CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, i, kstat_sysctl_dataset, "QU",
|
||||
namelast);
|
||||
} else {
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
|
||||
OID_AUTO, namelast,
|
||||
CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, i, kstat_sysctl, "QU", namelast);
|
||||
}
|
||||
break;
|
||||
case KSTAT_DATA_LONG:
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
@@ -443,11 +502,21 @@ kstat_install_named(kstat_t *ksp)
|
||||
ksp, i, kstat_sysctl, "LU", namelast);
|
||||
break;
|
||||
case KSTAT_DATA_STRING:
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
|
||||
OID_AUTO, namelast,
|
||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, i, kstat_sysctl_string, "A", namelast);
|
||||
if (strcmp(ksp->ks_class, "dataset") == 0) {
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
|
||||
OID_AUTO, namelast, CTLTYPE_STRING |
|
||||
CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, i, kstat_sysctl_dataset_string, "A",
|
||||
namelast);
|
||||
} else {
|
||||
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
|
||||
OID_AUTO, namelast, CTLTYPE_STRING |
|
||||
CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
ksp, i, kstat_sysctl_string, "A",
|
||||
namelast);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("unsupported type: %d", typelast);
|
||||
|
||||
@@ -125,7 +125,6 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
|
||||
struct vfsconf *vfsp;
|
||||
struct mount *mp;
|
||||
vnode_t *vp, *mvp;
|
||||
struct ucred *cr;
|
||||
int error;
|
||||
|
||||
ASSERT_VOP_ELOCKED(*vpp, "mount_snapshot");
|
||||
@@ -194,15 +193,8 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
|
||||
* mount(8) and df(1) output.
|
||||
*/
|
||||
mp->mnt_flag |= MNT_IGNORE;
|
||||
/*
|
||||
* XXX: This is evil, but we can't mount a snapshot as a regular user.
|
||||
* XXX: Is is safe when snapshot is mounted from within a jail?
|
||||
*/
|
||||
cr = td->td_ucred;
|
||||
td->td_ucred = kcred;
|
||||
error = VFS_MOUNT(mp);
|
||||
td->td_ucred = cr;
|
||||
|
||||
error = VFS_MOUNT(mp);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* Clear VI_MOUNT and decrement the use count "atomically",
|
||||
|
||||
@@ -160,8 +160,6 @@ arc_prune_task(void *arg)
|
||||
{
|
||||
int64_t nr_scan = (intptr_t)arg;
|
||||
|
||||
arc_reduce_target_size(ptob(nr_scan));
|
||||
|
||||
#ifndef __ILP32__
|
||||
if (nr_scan > INT_MAX)
|
||||
nr_scan = INT_MAX;
|
||||
|
||||
@@ -132,16 +132,13 @@ zfsdev_ioctl(struct cdev *dev, ulong_t zcmd, caddr_t arg, int flag,
|
||||
len = IOCPARM_LEN(zcmd);
|
||||
vecnum = zcmd & 0xff;
|
||||
zp = (void *)arg;
|
||||
uaddr = (void *)zp->zfs_cmd;
|
||||
error = 0;
|
||||
zcl = NULL;
|
||||
|
||||
if (len != sizeof (zfs_iocparm_t)) {
|
||||
printf("len %d vecnum: %d sizeof (zfs_cmd_t) %ju\n",
|
||||
len, vecnum, (uintmax_t)sizeof (zfs_cmd_t));
|
||||
if (len != sizeof (zfs_iocparm_t))
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
uaddr = (void *)zp->zfs_cmd;
|
||||
zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
|
||||
/*
|
||||
* Remap ioctl code for legacy user binaries
|
||||
|
||||
@@ -95,6 +95,8 @@ spa_generate_rootconf(const char *name)
|
||||
for (i = 0; i < count; i++) {
|
||||
uint64_t txg;
|
||||
|
||||
if (configs[i] == NULL)
|
||||
continue;
|
||||
txg = fnvlist_lookup_uint64(configs[i], ZPOOL_CONFIG_POOL_TXG);
|
||||
if (txg > best_txg) {
|
||||
best_txg = txg;
|
||||
|
||||
@@ -356,14 +356,6 @@ SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, max_idistance, CTLFLAG_RWTUN,
|
||||
/* dsl_pool.c */
|
||||
|
||||
/* dnode.c */
|
||||
extern int zfs_default_bs;
|
||||
SYSCTL_INT(_vfs_zfs, OID_AUTO, default_bs, CTLFLAG_RWTUN,
|
||||
&zfs_default_bs, 0, "Default dnode block shift");
|
||||
|
||||
extern int zfs_default_ibs;
|
||||
SYSCTL_INT(_vfs_zfs, OID_AUTO, default_ibs, CTLFLAG_RWTUN,
|
||||
&zfs_default_ibs, 0, "Default dnode indirect block shift");
|
||||
|
||||
|
||||
/* dsl_scan.c */
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include <sys/dsl_dir.h>
|
||||
#include <sys/spa_boot.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/osd.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <sys/zfs_quota.h>
|
||||
|
||||
@@ -90,6 +91,20 @@ int zfs_debug_level;
|
||||
SYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RWTUN, &zfs_debug_level, 0,
|
||||
"Debug level");
|
||||
|
||||
struct zfs_jailparam {
|
||||
int mount_snapshot;
|
||||
};
|
||||
|
||||
static struct zfs_jailparam zfs_jailparam0 = {
|
||||
.mount_snapshot = 0,
|
||||
};
|
||||
|
||||
static int zfs_jailparam_slot;
|
||||
|
||||
SYSCTL_JAIL_PARAM_SYS_NODE(zfs, CTLFLAG_RW, "Jail ZFS parameters");
|
||||
SYSCTL_JAIL_PARAM(_zfs, mount_snapshot, CTLTYPE_INT | CTLFLAG_RW, "I",
|
||||
"Allow mounting snapshots in the .zfs directory for unjailed datasets");
|
||||
|
||||
SYSCTL_NODE(_vfs_zfs, OID_AUTO, version, CTLFLAG_RD, 0, "ZFS versions");
|
||||
static int zfs_version_acl = ZFS_ACL_VERSION;
|
||||
SYSCTL_INT(_vfs_zfs_version, OID_AUTO, acl, CTLFLAG_RD, &zfs_version_acl, 0,
|
||||
@@ -720,7 +735,7 @@ zfs_register_callbacks(vfs_t *vfsp)
|
||||
nbmand = B_FALSE;
|
||||
} else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) {
|
||||
nbmand = B_TRUE;
|
||||
} else if ((error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand) != 0)) {
|
||||
} else if ((error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand)) != 0) {
|
||||
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
|
||||
return (error);
|
||||
}
|
||||
@@ -1332,7 +1347,7 @@ zfs_mount(vfs_t *vfsp)
|
||||
char *osname;
|
||||
int error = 0;
|
||||
int canwrite;
|
||||
bool checkpointrewind;
|
||||
bool checkpointrewind, isctlsnap = false;
|
||||
|
||||
if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL))
|
||||
return (SET_ERROR(EINVAL));
|
||||
@@ -1347,6 +1362,8 @@ zfs_mount(vfs_t *vfsp)
|
||||
}
|
||||
|
||||
fetch_osname_options(osname, &checkpointrewind);
|
||||
isctlsnap = (mvp != NULL && zfsctl_is_node(mvp) &&
|
||||
strchr(osname, '@') != NULL);
|
||||
|
||||
/*
|
||||
* Check for mount privilege?
|
||||
@@ -1355,7 +1372,9 @@ zfs_mount(vfs_t *vfsp)
|
||||
* we have local permission to allow it
|
||||
*/
|
||||
error = secpolicy_fs_mount(cr, mvp, vfsp);
|
||||
if (error) {
|
||||
if (error && isctlsnap) {
|
||||
secpolicy_fs_mount_clearopts(cr, vfsp);
|
||||
} else if (error) {
|
||||
if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != 0)
|
||||
goto out;
|
||||
|
||||
@@ -1392,8 +1411,27 @@ zfs_mount(vfs_t *vfsp)
|
||||
*/
|
||||
if (!INGLOBALZONE(curproc) &&
|
||||
(!zone_dataset_visible(osname, &canwrite) || !canwrite)) {
|
||||
error = SET_ERROR(EPERM);
|
||||
goto out;
|
||||
boolean_t mount_snapshot = B_FALSE;
|
||||
|
||||
/*
|
||||
* Snapshots may be mounted in .zfs for unjailed datasets
|
||||
* if allowed by the jail param zfs.mount_snapshot.
|
||||
*/
|
||||
if (isctlsnap) {
|
||||
struct prison *pr;
|
||||
struct zfs_jailparam *zjp;
|
||||
|
||||
pr = curthread->td_ucred->cr_prison;
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
zjp = osd_jail_get(pr, zfs_jailparam_slot);
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
if (zjp && zjp->mount_snapshot)
|
||||
mount_snapshot = B_TRUE;
|
||||
}
|
||||
if (!mount_snapshot) {
|
||||
error = SET_ERROR(EPERM);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
vfsp->vfs_flag |= MNT_NFS4ACLS;
|
||||
@@ -2343,3 +2381,236 @@ zfsvfs_update_fromname(const char *oldname, const char *newname)
|
||||
mtx_unlock(&mountlist_mtx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find a prison with ZFS info.
|
||||
* Return the ZFS info and the (locked) prison.
|
||||
*/
|
||||
static struct zfs_jailparam *
|
||||
zfs_jailparam_find(struct prison *spr, struct prison **prp)
|
||||
{
|
||||
struct prison *pr;
|
||||
struct zfs_jailparam *zjp;
|
||||
|
||||
for (pr = spr; ; pr = pr->pr_parent) {
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
if (pr == &prison0) {
|
||||
zjp = &zfs_jailparam0;
|
||||
break;
|
||||
}
|
||||
zjp = osd_jail_get(pr, zfs_jailparam_slot);
|
||||
if (zjp != NULL)
|
||||
break;
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
}
|
||||
*prp = pr;
|
||||
|
||||
return (zjp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure a prison has its own ZFS info. If zjpp is non-null, point it to the
|
||||
* ZFS info and lock the prison.
|
||||
*/
|
||||
static void
|
||||
zfs_jailparam_alloc(struct prison *pr, struct zfs_jailparam **zjpp)
|
||||
{
|
||||
struct prison *ppr;
|
||||
struct zfs_jailparam *zjp, *nzjp;
|
||||
void **rsv;
|
||||
|
||||
/* If this prison already has ZFS info, return that. */
|
||||
zjp = zfs_jailparam_find(pr, &ppr);
|
||||
if (ppr == pr)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Allocate a new info record. Then check again, in case something
|
||||
* changed during the allocation.
|
||||
*/
|
||||
mtx_unlock(&ppr->pr_mtx);
|
||||
nzjp = malloc(sizeof (struct zfs_jailparam), M_PRISON, M_WAITOK);
|
||||
rsv = osd_reserve(zfs_jailparam_slot);
|
||||
zjp = zfs_jailparam_find(pr, &ppr);
|
||||
if (ppr == pr) {
|
||||
free(nzjp, M_PRISON);
|
||||
osd_free_reserved(rsv);
|
||||
goto done;
|
||||
}
|
||||
/* Inherit the initial values from the ancestor. */
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
(void) osd_jail_set_reserved(pr, zfs_jailparam_slot, rsv, nzjp);
|
||||
(void) memcpy(nzjp, zjp, sizeof (*zjp));
|
||||
zjp = nzjp;
|
||||
mtx_unlock(&ppr->pr_mtx);
|
||||
done:
|
||||
if (zjpp != NULL)
|
||||
*zjpp = zjp;
|
||||
else
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Jail OSD methods for ZFS VFS info.
|
||||
*/
|
||||
static int
|
||||
zfs_jailparam_create(void *obj, void *data)
|
||||
{
|
||||
struct prison *pr = obj;
|
||||
struct vfsoptlist *opts = data;
|
||||
int jsys;
|
||||
|
||||
if (vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys)) == 0 &&
|
||||
jsys == JAIL_SYS_INHERIT)
|
||||
return (0);
|
||||
/*
|
||||
* Inherit a prison's initial values from its parent
|
||||
* (different from JAIL_SYS_INHERIT which also inherits changes).
|
||||
*/
|
||||
zfs_jailparam_alloc(pr, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_jailparam_get(void *obj, void *data)
|
||||
{
|
||||
struct prison *ppr, *pr = obj;
|
||||
struct vfsoptlist *opts = data;
|
||||
struct zfs_jailparam *zjp;
|
||||
int jsys, error;
|
||||
|
||||
zjp = zfs_jailparam_find(pr, &ppr);
|
||||
jsys = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
|
||||
error = vfs_setopt(opts, "zfs", &jsys, sizeof (jsys));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
if (jsys == JAIL_SYS_NEW) {
|
||||
error = vfs_setopt(opts, "zfs.mount_snapshot",
|
||||
&zjp->mount_snapshot, sizeof (zjp->mount_snapshot));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
} else {
|
||||
/*
|
||||
* If this prison is inheriting its ZFS info, report
|
||||
* empty/zero parameters.
|
||||
*/
|
||||
static int mount_snapshot = 0;
|
||||
|
||||
error = vfs_setopt(opts, "zfs.mount_snapshot",
|
||||
&mount_snapshot, sizeof (mount_snapshot));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
}
|
||||
error = 0;
|
||||
done:
|
||||
mtx_unlock(&ppr->pr_mtx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_jailparam_set(void *obj, void *data)
|
||||
{
|
||||
struct prison *pr = obj;
|
||||
struct prison *ppr;
|
||||
struct vfsoptlist *opts = data;
|
||||
int error, jsys, mount_snapshot;
|
||||
|
||||
/* Set the parameters, which should be correct. */
|
||||
error = vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys));
|
||||
if (error == ENOENT)
|
||||
jsys = -1;
|
||||
error = vfs_copyopt(opts, "zfs.mount_snapshot", &mount_snapshot,
|
||||
sizeof (mount_snapshot));
|
||||
if (error == ENOENT)
|
||||
mount_snapshot = -1;
|
||||
else
|
||||
jsys = JAIL_SYS_NEW;
|
||||
if (jsys == JAIL_SYS_NEW) {
|
||||
/* "zfs=new" or "zfs.*": the prison gets its own ZFS info. */
|
||||
struct zfs_jailparam *zjp;
|
||||
|
||||
/*
|
||||
* A child jail cannot have more permissions than its parent
|
||||
*/
|
||||
if (pr->pr_parent != &prison0) {
|
||||
zjp = zfs_jailparam_find(pr->pr_parent, &ppr);
|
||||
mtx_unlock(&ppr->pr_mtx);
|
||||
if (zjp->mount_snapshot < mount_snapshot) {
|
||||
return (EPERM);
|
||||
}
|
||||
}
|
||||
zfs_jailparam_alloc(pr, &zjp);
|
||||
if (mount_snapshot != -1)
|
||||
zjp->mount_snapshot = mount_snapshot;
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
} else {
|
||||
/* "zfs=inherit": inherit the parent's ZFS info. */
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
osd_jail_del(pr, zfs_jailparam_slot);
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_jailparam_check(void *obj __unused, void *data)
|
||||
{
|
||||
struct vfsoptlist *opts = data;
|
||||
int error, jsys, mount_snapshot;
|
||||
|
||||
/* Check that the parameters are correct. */
|
||||
error = vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys));
|
||||
if (error != ENOENT) {
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT)
|
||||
return (EINVAL);
|
||||
}
|
||||
error = vfs_copyopt(opts, "zfs.mount_snapshot", &mount_snapshot,
|
||||
sizeof (mount_snapshot));
|
||||
if (error != ENOENT) {
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (mount_snapshot != 0 && mount_snapshot != 1)
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
zfs_jailparam_destroy(void *data)
|
||||
{
|
||||
|
||||
free(data, M_PRISON);
|
||||
}
|
||||
|
||||
static void
|
||||
zfs_jailparam_sysinit(void *arg __unused)
|
||||
{
|
||||
struct prison *pr;
|
||||
osd_method_t methods[PR_MAXMETHOD] = {
|
||||
[PR_METHOD_CREATE] = zfs_jailparam_create,
|
||||
[PR_METHOD_GET] = zfs_jailparam_get,
|
||||
[PR_METHOD_SET] = zfs_jailparam_set,
|
||||
[PR_METHOD_CHECK] = zfs_jailparam_check,
|
||||
};
|
||||
|
||||
zfs_jailparam_slot = osd_jail_register(zfs_jailparam_destroy, methods);
|
||||
/* Copy the defaults to any existing prisons. */
|
||||
sx_slock(&allprison_lock);
|
||||
TAILQ_FOREACH(pr, &allprison, pr_list)
|
||||
zfs_jailparam_alloc(pr, NULL);
|
||||
sx_sunlock(&allprison_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
zfs_jailparam_sysuninit(void *arg __unused)
|
||||
{
|
||||
|
||||
osd_jail_deregister(zfs_jailparam_slot);
|
||||
}
|
||||
|
||||
SYSINIT(zfs_jailparam_sysinit, SI_SUB_DRIVERS, SI_ORDER_ANY,
|
||||
zfs_jailparam_sysinit, NULL);
|
||||
SYSUNINIT(zfs_jailparam_sysuninit, SI_SUB_DRIVERS, SI_ORDER_ANY,
|
||||
zfs_jailparam_sysuninit, NULL);
|
||||
|
||||
@@ -536,6 +536,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
|
||||
* Acquire vnode lock before making it available to the world.
|
||||
*/
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
#if __FreeBSD_version >= 1400077
|
||||
vn_set_state(vp, VSTATE_CONSTRUCTED);
|
||||
#endif
|
||||
VN_LOCK_AREC(vp);
|
||||
if (vp->v_type != VFIFO)
|
||||
VN_LOCK_ASHARE(vp);
|
||||
|
||||
@@ -1161,7 +1161,10 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
|
||||
|
||||
hole = (cmd == FIOSEEKHOLE);
|
||||
noff = *off;
|
||||
lr = zfs_rangelock_enter(&zv->zv_rangelock, 0, UINT64_MAX,
|
||||
RL_READER);
|
||||
error = dmu_offset_next(zv->zv_objset, ZVOL_OBJ, hole, &noff);
|
||||
zfs_rangelock_exit(lr);
|
||||
*off = noff;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <linux/mod_compat.h>
|
||||
#include <sys/cred.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/misc.h>
|
||||
|
||||
char spl_gitrev[64] = ZFS_META_GITREV;
|
||||
|
||||
@@ -540,6 +541,38 @@ ddi_copyin(const void *from, void *to, size_t len, int flags)
|
||||
}
|
||||
EXPORT_SYMBOL(ddi_copyin);
|
||||
|
||||
/*
|
||||
* Post a uevent to userspace whenever a new vdev adds to the pool. It is
|
||||
* necessary to sync blkid information with udev, which zed daemon uses
|
||||
* during device hotplug to identify the vdev.
|
||||
*/
|
||||
void
|
||||
spl_signal_kobj_evt(struct block_device *bdev)
|
||||
{
|
||||
#if defined(HAVE_BDEV_KOBJ) || defined(HAVE_PART_TO_DEV)
|
||||
#ifdef HAVE_BDEV_KOBJ
|
||||
struct kobject *disk_kobj = bdev_kobj(bdev);
|
||||
#else
|
||||
struct kobject *disk_kobj = &part_to_dev(bdev->bd_part)->kobj;
|
||||
#endif
|
||||
if (disk_kobj) {
|
||||
int ret = kobject_uevent(disk_kobj, KOBJ_CHANGE);
|
||||
if (ret) {
|
||||
pr_warn("ZFS: Sending event '%d' to kobject: '%s'"
|
||||
" (%p): failed(ret:%d)\n", KOBJ_CHANGE,
|
||||
kobject_name(disk_kobj), disk_kobj, ret);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* This is encountered if neither bdev_kobj() nor part_to_dev() is available
|
||||
* in the kernel - likely due to an API change that needs to be chased down.
|
||||
*/
|
||||
#error "Unsupported kernel: unable to get struct kobj from bdev"
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(spl_signal_kobj_evt);
|
||||
|
||||
int
|
||||
ddi_copyout(const void *from, void *to, size_t len, int flags)
|
||||
{
|
||||
|
||||
@@ -247,7 +247,7 @@ qat_compress_impl(qat_compress_dir_t dir, char *src, int src_len,
|
||||
Cpa8U *buffer_meta_src = NULL;
|
||||
Cpa8U *buffer_meta_dst = NULL;
|
||||
Cpa32U buffer_meta_size = 0;
|
||||
CpaDcRqResults dc_results;
|
||||
CpaDcRqResults dc_results = {.checksum = 1};
|
||||
CpaStatus status = CPA_STATUS_FAIL;
|
||||
Cpa32U hdr_sz = 0;
|
||||
Cpa32U compressed_sz;
|
||||
|
||||
@@ -179,6 +179,18 @@ vdev_disk_error(zio_t *zio)
|
||||
zio->io_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
vdev_disk_kobj_evt_post(vdev_t *v)
|
||||
{
|
||||
vdev_disk_t *vd = v->vdev_tsd;
|
||||
if (vd && vd->vd_bdev) {
|
||||
spl_signal_kobj_evt(vd->vd_bdev);
|
||||
} else {
|
||||
vdev_dbgmsg(v, "vdev_disk_t is NULL for VDEV:%s\n",
|
||||
v->vdev_path);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||
uint64_t *logical_ashift, uint64_t *physical_ashift)
|
||||
@@ -290,6 +302,13 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||
bdev = blkdev_get_by_path(v->vdev_path, mode | FMODE_EXCL,
|
||||
zfs_vdev_holder);
|
||||
if (unlikely(PTR_ERR(bdev) == -ENOENT)) {
|
||||
/*
|
||||
* There is no point of waiting since device is removed
|
||||
* explicitly
|
||||
*/
|
||||
if (v->vdev_removed)
|
||||
break;
|
||||
|
||||
schedule_timeout(MSEC_TO_TICK(10));
|
||||
} else if (unlikely(PTR_ERR(bdev) == -ERESTARTSYS)) {
|
||||
timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms * 10);
|
||||
@@ -899,7 +918,7 @@ vdev_disk_io_done(zio_t *zio)
|
||||
vdev_t *v = zio->io_vd;
|
||||
vdev_disk_t *vd = v->vdev_tsd;
|
||||
|
||||
if (zfs_check_media_change(vd->vd_bdev)) {
|
||||
if (!zfs_check_disk_status(vd->vd_bdev)) {
|
||||
invalidate_bdev(vd->vd_bdev);
|
||||
v->vdev_remove_wanted = B_TRUE;
|
||||
spa_async_request(zio->io_spa, SPA_ASYNC_REMOVE);
|
||||
@@ -955,7 +974,8 @@ vdev_ops_t vdev_disk_ops = {
|
||||
.vdev_op_nparity = NULL,
|
||||
.vdev_op_ndisks = NULL,
|
||||
.vdev_op_type = VDEV_TYPE_DISK, /* name of this vdev type */
|
||||
.vdev_op_leaf = B_TRUE /* leaf vdev */
|
||||
.vdev_op_leaf = B_TRUE, /* leaf vdev */
|
||||
.vdev_op_kobj_evt_post = vdev_disk_kobj_evt_post
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1066,9 +1066,6 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr)
|
||||
|
||||
*xzpp = NULL;
|
||||
|
||||
if ((error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr)))
|
||||
return (error);
|
||||
|
||||
if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL,
|
||||
&acl_ids)) != 0)
|
||||
return (error);
|
||||
|
||||
@@ -579,6 +579,7 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
|
||||
boolean_t fuid_dirtied;
|
||||
boolean_t have_acl = B_FALSE;
|
||||
boolean_t waited = B_FALSE;
|
||||
boolean_t skip_acl = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
|
||||
|
||||
/*
|
||||
* If we have an ephemeral id, ACL, or XVATTR then
|
||||
@@ -651,7 +652,7 @@ top:
|
||||
* Create a new file object and update the directory
|
||||
* to reference it.
|
||||
*/
|
||||
if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
|
||||
if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, skip_acl, cr))) {
|
||||
if (have_acl)
|
||||
zfs_acl_ids_free(&acl_ids);
|
||||
goto out;
|
||||
|
||||
@@ -162,8 +162,7 @@ zfs_znode_hold_cache_constructor(void *buf, void *arg, int kmflags)
|
||||
znode_hold_t *zh = buf;
|
||||
|
||||
mutex_init(&zh->zh_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
zfs_refcount_create(&zh->zh_refcount);
|
||||
zh->zh_obj = ZFS_NO_OBJECT;
|
||||
zh->zh_refcount = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -174,7 +173,6 @@ zfs_znode_hold_cache_destructor(void *buf, void *arg)
|
||||
znode_hold_t *zh = buf;
|
||||
|
||||
mutex_destroy(&zh->zh_lock);
|
||||
zfs_refcount_destroy(&zh->zh_refcount);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -273,26 +271,26 @@ zfs_znode_hold_enter(zfsvfs_t *zfsvfs, uint64_t obj)
|
||||
boolean_t found = B_FALSE;
|
||||
|
||||
zh_new = kmem_cache_alloc(znode_hold_cache, KM_SLEEP);
|
||||
zh_new->zh_obj = obj;
|
||||
search.zh_obj = obj;
|
||||
|
||||
mutex_enter(&zfsvfs->z_hold_locks[i]);
|
||||
zh = avl_find(&zfsvfs->z_hold_trees[i], &search, NULL);
|
||||
if (likely(zh == NULL)) {
|
||||
zh = zh_new;
|
||||
zh->zh_obj = obj;
|
||||
avl_add(&zfsvfs->z_hold_trees[i], zh);
|
||||
} else {
|
||||
ASSERT3U(zh->zh_obj, ==, obj);
|
||||
found = B_TRUE;
|
||||
}
|
||||
zfs_refcount_add(&zh->zh_refcount, NULL);
|
||||
zh->zh_refcount++;
|
||||
ASSERT3S(zh->zh_refcount, >, 0);
|
||||
mutex_exit(&zfsvfs->z_hold_locks[i]);
|
||||
|
||||
if (found == B_TRUE)
|
||||
kmem_cache_free(znode_hold_cache, zh_new);
|
||||
|
||||
ASSERT(MUTEX_NOT_HELD(&zh->zh_lock));
|
||||
ASSERT3S(zfs_refcount_count(&zh->zh_refcount), >, 0);
|
||||
mutex_enter(&zh->zh_lock);
|
||||
|
||||
return (zh);
|
||||
@@ -305,11 +303,11 @@ zfs_znode_hold_exit(zfsvfs_t *zfsvfs, znode_hold_t *zh)
|
||||
boolean_t remove = B_FALSE;
|
||||
|
||||
ASSERT(zfs_znode_held(zfsvfs, zh->zh_obj));
|
||||
ASSERT3S(zfs_refcount_count(&zh->zh_refcount), >, 0);
|
||||
mutex_exit(&zh->zh_lock);
|
||||
|
||||
mutex_enter(&zfsvfs->z_hold_locks[i]);
|
||||
if (zfs_refcount_remove(&zh->zh_refcount, NULL) == 0) {
|
||||
ASSERT3S(zh->zh_refcount, >, 0);
|
||||
if (--zh->zh_refcount == 0) {
|
||||
avl_remove(&zfsvfs->z_hold_trees[i], zh);
|
||||
remove = B_TRUE;
|
||||
}
|
||||
|
||||
@@ -224,12 +224,17 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
|
||||
#ifdef HAVE_TMPFILE
|
||||
static int
|
||||
#ifndef HAVE_TMPFILE_DENTRY
|
||||
zpl_tmpfile(struct user_namespace *userns, struct inode *dir,
|
||||
struct file *file, umode_t mode)
|
||||
#else
|
||||
#ifdef HAVE_TMPFILE_USERNS
|
||||
zpl_tmpfile(struct user_namespace *userns, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
#else
|
||||
zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
cred_t *cr = CRED();
|
||||
struct inode *ip;
|
||||
@@ -252,11 +257,21 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
if (error == 0) {
|
||||
/* d_tmpfile will do drop_nlink, so we should set it first */
|
||||
set_nlink(ip, 1);
|
||||
#ifndef HAVE_TMPFILE_DENTRY
|
||||
d_tmpfile(file, ip);
|
||||
|
||||
error = zpl_xattr_security_init(ip, dir,
|
||||
&file->f_path.dentry->d_name);
|
||||
#else
|
||||
d_tmpfile(dentry, ip);
|
||||
|
||||
error = zpl_xattr_security_init(ip, dir, &dentry->d_name);
|
||||
#endif
|
||||
if (error == 0)
|
||||
error = zpl_init_acl(ip, dir);
|
||||
#ifndef HAVE_TMPFILE_DENTRY
|
||||
error = finish_open_simple(file, error);
|
||||
#endif
|
||||
/*
|
||||
* don't need to handle error here, file is already in
|
||||
* unlinked set.
|
||||
@@ -711,7 +726,11 @@ const struct inode_operations zpl_inode_operations = {
|
||||
#if defined(HAVE_SET_ACL)
|
||||
.set_acl = zpl_set_acl,
|
||||
#endif /* HAVE_SET_ACL */
|
||||
#if defined(HAVE_GET_INODE_ACL)
|
||||
.get_inode_acl = zpl_get_acl,
|
||||
#else
|
||||
.get_acl = zpl_get_acl,
|
||||
#endif /* HAVE_GET_INODE_ACL */
|
||||
#endif /* CONFIG_FS_POSIX_ACL */
|
||||
};
|
||||
|
||||
@@ -744,7 +763,11 @@ const struct inode_operations zpl_dir_inode_operations = {
|
||||
#if defined(HAVE_SET_ACL)
|
||||
.set_acl = zpl_set_acl,
|
||||
#endif /* HAVE_SET_ACL */
|
||||
#if defined(HAVE_GET_INODE_ACL)
|
||||
.get_inode_acl = zpl_get_acl,
|
||||
#else
|
||||
.get_acl = zpl_get_acl,
|
||||
#endif /* HAVE_GET_INODE_ACL */
|
||||
#endif /* CONFIG_FS_POSIX_ACL */
|
||||
};
|
||||
|
||||
@@ -783,6 +806,10 @@ const struct inode_operations zpl_special_inode_operations = {
|
||||
#if defined(HAVE_SET_ACL)
|
||||
.set_acl = zpl_set_acl,
|
||||
#endif /* HAVE_SET_ACL */
|
||||
#if defined(HAVE_GET_INODE_ACL)
|
||||
.get_inode_acl = zpl_get_acl,
|
||||
#else
|
||||
.get_acl = zpl_get_acl,
|
||||
#endif /* HAVE_GET_INODE_ACL */
|
||||
#endif /* CONFIG_FS_POSIX_ACL */
|
||||
};
|
||||
|
||||
@@ -496,7 +496,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
|
||||
vap->va_gid = crgetgid(cr);
|
||||
|
||||
error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp,
|
||||
cr, 0, NULL);
|
||||
cr, ATTR_NOACLCHECK, NULL);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
@@ -1004,11 +1004,18 @@ int
|
||||
#ifdef HAVE_SET_ACL_USERNS
|
||||
zpl_set_acl(struct user_namespace *userns, struct inode *ip,
|
||||
struct posix_acl *acl, int type)
|
||||
#elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2)
|
||||
zpl_set_acl(struct user_namespace *userns, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type)
|
||||
#else
|
||||
zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type)
|
||||
#endif /* HAVE_SET_ACL_USERNS */
|
||||
{
|
||||
#ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2
|
||||
return (zpl_set_acl_impl(d_inode(dentry), acl, type));
|
||||
#else
|
||||
return (zpl_set_acl_impl(ip, acl, type));
|
||||
#endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */
|
||||
}
|
||||
#endif /* HAVE_SET_ACL */
|
||||
|
||||
@@ -1067,7 +1074,7 @@ zpl_get_acl_impl(struct inode *ip, int type)
|
||||
return (acl);
|
||||
}
|
||||
|
||||
#if defined(HAVE_GET_ACL_RCU)
|
||||
#if defined(HAVE_GET_ACL_RCU) || defined(HAVE_GET_INODE_ACL)
|
||||
struct posix_acl *
|
||||
zpl_get_acl(struct inode *ip, int type, bool rcu)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2022 MNX Cloud, Inc.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -213,10 +216,10 @@ const int8_t u8_number_of_bytes[0x100] = {
|
||||
/* 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F */
|
||||
I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
|
||||
|
||||
/* 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F */
|
||||
/* 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F */
|
||||
I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
|
||||
|
||||
/* A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF */
|
||||
/* A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF */
|
||||
I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
|
||||
|
||||
/* B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF */
|
||||
@@ -1286,8 +1289,12 @@ TRY_THE_NEXT_MARK:
|
||||
saved_l = l - disp[last];
|
||||
|
||||
while (p < oslast) {
|
||||
size = u8_number_of_bytes[*p];
|
||||
if (size <= 1 || (p + size) > oslast)
|
||||
int8_t number_of_bytes = u8_number_of_bytes[*p];
|
||||
|
||||
if (number_of_bytes <= 1)
|
||||
break;
|
||||
size = number_of_bytes;
|
||||
if ((p + size) > oslast)
|
||||
break;
|
||||
|
||||
saved_p = p;
|
||||
@@ -1378,8 +1385,10 @@ SAFE_RETURN:
|
||||
*/
|
||||
static size_t
|
||||
collect_a_seq(size_t uv, uchar_t *u8s, uchar_t **source, uchar_t *slast,
|
||||
boolean_t is_it_toupper, boolean_t is_it_tolower,
|
||||
boolean_t canonical_decomposition, boolean_t compatibility_decomposition,
|
||||
boolean_t is_it_toupper,
|
||||
boolean_t is_it_tolower,
|
||||
boolean_t canonical_decomposition,
|
||||
boolean_t compatibility_decomposition,
|
||||
boolean_t canonical_composition,
|
||||
int *errnum, u8_normalization_states_t *state)
|
||||
{
|
||||
|
||||
+16
-8
@@ -5943,6 +5943,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
|
||||
(zio_flags & ZIO_FLAG_RAW_ENCRYPT) != 0;
|
||||
boolean_t embedded_bp = !!BP_IS_EMBEDDED(bp);
|
||||
boolean_t no_buf = *arc_flags & ARC_FLAG_NO_BUF;
|
||||
arc_buf_t *buf = NULL;
|
||||
int rc = 0;
|
||||
|
||||
ASSERT(!embedded_bp ||
|
||||
@@ -5972,7 +5973,7 @@ top:
|
||||
if (!zfs_blkptr_verify(spa, bp, zio_flags & ZIO_FLAG_CONFIG_WRITER,
|
||||
BLK_VERIFY_LOG)) {
|
||||
rc = SET_ERROR(ECKSUM);
|
||||
goto out;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!embedded_bp) {
|
||||
@@ -5992,7 +5993,6 @@ top:
|
||||
*/
|
||||
if (hdr != NULL && HDR_HAS_L1HDR(hdr) && (HDR_HAS_RABD(hdr) ||
|
||||
(hdr->b_l1hdr.b_pabd != NULL && !encrypted_read))) {
|
||||
arc_buf_t *buf = NULL;
|
||||
*arc_flags |= ARC_FLAG_CACHED;
|
||||
|
||||
if (HDR_IO_IN_PROGRESS(hdr)) {
|
||||
@@ -6002,7 +6002,7 @@ top:
|
||||
mutex_exit(hash_lock);
|
||||
ARCSTAT_BUMP(arcstat_cached_only_in_progress);
|
||||
rc = SET_ERROR(ENOENT);
|
||||
goto out;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ASSERT3P(head_zio, !=, NULL);
|
||||
@@ -6130,9 +6130,7 @@ top:
|
||||
ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
|
||||
demand, prefetch, !HDR_ISTYPE_METADATA(hdr),
|
||||
data, metadata, hits);
|
||||
|
||||
if (done)
|
||||
done(NULL, zb, bp, buf, private);
|
||||
goto done;
|
||||
} else {
|
||||
uint64_t lsize = BP_GET_LSIZE(bp);
|
||||
uint64_t psize = BP_GET_PSIZE(bp);
|
||||
@@ -6145,10 +6143,10 @@ top:
|
||||
int alloc_flags = encrypted_read ? ARC_HDR_ALLOC_RDATA : 0;
|
||||
|
||||
if (*arc_flags & ARC_FLAG_CACHED_ONLY) {
|
||||
rc = SET_ERROR(ENOENT);
|
||||
if (hash_lock != NULL)
|
||||
mutex_exit(hash_lock);
|
||||
goto out;
|
||||
rc = SET_ERROR(ENOENT);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (hdr == NULL) {
|
||||
@@ -6474,6 +6472,16 @@ out:
|
||||
spa_read_history_add(spa, zb, *arc_flags);
|
||||
spl_fstrans_unmark(cookie);
|
||||
return (rc);
|
||||
|
||||
done:
|
||||
if (done)
|
||||
done(NULL, zb, bp, buf, private);
|
||||
if (pio && rc != 0) {
|
||||
zio_t *zio = zio_null(pio, spa, NULL, NULL, NULL, zio_flags);
|
||||
zio->io_error = rc;
|
||||
zio_nowait(zio);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
arc_prune_t *
|
||||
|
||||
+63
-2
@@ -663,14 +663,13 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
|
||||
}
|
||||
|
||||
VERIFY3U(0, ==, bpobj_open(&subbpo, bpo->bpo_os, subobj));
|
||||
VERIFY3U(0, ==, bpobj_space(&subbpo, &used, &comp, &uncomp));
|
||||
|
||||
if (bpobj_is_empty(&subbpo)) {
|
||||
/* No point in having an empty subobj. */
|
||||
bpobj_close(&subbpo);
|
||||
bpobj_free(bpo->bpo_os, subobj, tx);
|
||||
return;
|
||||
}
|
||||
VERIFY3U(0, ==, bpobj_space(&subbpo, &used, &comp, &uncomp));
|
||||
|
||||
mutex_enter(&bpo->bpo_lock);
|
||||
dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
|
||||
@@ -780,6 +779,68 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Prefetch metadata required for bpobj_enqueue_subobj().
|
||||
*/
|
||||
void
|
||||
bpobj_prefetch_subobj(bpobj_t *bpo, uint64_t subobj)
|
||||
{
|
||||
dmu_object_info_t doi;
|
||||
bpobj_t subbpo;
|
||||
uint64_t subsubobjs;
|
||||
boolean_t copy_subsub = B_TRUE;
|
||||
boolean_t copy_bps = B_TRUE;
|
||||
|
||||
ASSERT(bpobj_is_open(bpo));
|
||||
ASSERT(subobj != 0);
|
||||
|
||||
if (subobj == dmu_objset_pool(bpo->bpo_os)->dp_empty_bpobj)
|
||||
return;
|
||||
|
||||
if (bpobj_open(&subbpo, bpo->bpo_os, subobj) != 0)
|
||||
return;
|
||||
if (bpobj_is_empty(&subbpo)) {
|
||||
bpobj_close(&subbpo);
|
||||
return;
|
||||
}
|
||||
subsubobjs = subbpo.bpo_phys->bpo_subobjs;
|
||||
bpobj_close(&subbpo);
|
||||
|
||||
if (subsubobjs != 0) {
|
||||
if (dmu_object_info(bpo->bpo_os, subsubobjs, &doi) != 0)
|
||||
return;
|
||||
if (doi.doi_max_offset > doi.doi_data_block_size)
|
||||
copy_subsub = B_FALSE;
|
||||
}
|
||||
|
||||
if (dmu_object_info(bpo->bpo_os, subobj, &doi) != 0)
|
||||
return;
|
||||
if (doi.doi_max_offset > doi.doi_data_block_size || !copy_subsub)
|
||||
copy_bps = B_FALSE;
|
||||
|
||||
if (copy_subsub && subsubobjs != 0) {
|
||||
if (bpo->bpo_phys->bpo_subobjs) {
|
||||
dmu_prefetch(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs, 0,
|
||||
bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj), 1,
|
||||
ZIO_PRIORITY_ASYNC_READ);
|
||||
}
|
||||
dmu_prefetch(bpo->bpo_os, subsubobjs, 0, 0, 1,
|
||||
ZIO_PRIORITY_ASYNC_READ);
|
||||
}
|
||||
|
||||
if (copy_bps) {
|
||||
dmu_prefetch(bpo->bpo_os, bpo->bpo_object, 0,
|
||||
bpo->bpo_phys->bpo_num_blkptrs * sizeof (blkptr_t), 1,
|
||||
ZIO_PRIORITY_ASYNC_READ);
|
||||
dmu_prefetch(bpo->bpo_os, subobj, 0, 0, 1,
|
||||
ZIO_PRIORITY_ASYNC_READ);
|
||||
} else if (bpo->bpo_phys->bpo_subobjs) {
|
||||
dmu_prefetch(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs, 0,
|
||||
bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj), 1,
|
||||
ZIO_PRIORITY_ASYNC_READ);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, boolean_t bp_freed,
|
||||
dmu_tx_t *tx)
|
||||
|
||||
+40
-12
@@ -102,7 +102,7 @@ zfs_btree_poison_node(zfs_btree_t *tree, zfs_btree_hdr_t *hdr)
|
||||
(void) memset(leaf->btl_elems, 0x0f, hdr->bth_first * size);
|
||||
(void) memset(leaf->btl_elems +
|
||||
(hdr->bth_first + hdr->bth_count) * size, 0x0f,
|
||||
BTREE_LEAF_ESIZE -
|
||||
tree->bt_leaf_size - offsetof(zfs_btree_leaf_t, btl_elems) -
|
||||
(hdr->bth_first + hdr->bth_count) * size);
|
||||
}
|
||||
#endif
|
||||
@@ -173,16 +173,44 @@ zfs_btree_fini(void)
|
||||
kmem_cache_destroy(zfs_btree_leaf_cache);
|
||||
}
|
||||
|
||||
static void *
|
||||
zfs_btree_leaf_alloc(zfs_btree_t *tree)
|
||||
{
|
||||
if (tree->bt_leaf_size == BTREE_LEAF_SIZE)
|
||||
return (kmem_cache_alloc(zfs_btree_leaf_cache, KM_SLEEP));
|
||||
else
|
||||
return (kmem_alloc(tree->bt_leaf_size, KM_SLEEP));
|
||||
}
|
||||
|
||||
static void
|
||||
zfs_btree_leaf_free(zfs_btree_t *tree, void *ptr)
|
||||
{
|
||||
if (tree->bt_leaf_size == BTREE_LEAF_SIZE)
|
||||
return (kmem_cache_free(zfs_btree_leaf_cache, ptr));
|
||||
else
|
||||
return (kmem_free(ptr, tree->bt_leaf_size));
|
||||
}
|
||||
|
||||
void
|
||||
zfs_btree_create(zfs_btree_t *tree, int (*compar) (const void *, const void *),
|
||||
size_t size)
|
||||
{
|
||||
ASSERT3U(size, <=, BTREE_LEAF_ESIZE / 2);
|
||||
zfs_btree_create_custom(tree, compar, size, BTREE_LEAF_SIZE);
|
||||
}
|
||||
|
||||
bzero(tree, sizeof (*tree));
|
||||
void
|
||||
zfs_btree_create_custom(zfs_btree_t *tree,
|
||||
int (*compar) (const void *, const void *),
|
||||
size_t size, size_t lsize)
|
||||
{
|
||||
size_t esize = lsize - offsetof(zfs_btree_leaf_t, btl_elems);
|
||||
|
||||
ASSERT3U(size, <=, esize / 2);
|
||||
memset(tree, 0, sizeof (*tree));
|
||||
tree->bt_compar = compar;
|
||||
tree->bt_elem_size = size;
|
||||
tree->bt_leaf_cap = P2ALIGN(BTREE_LEAF_ESIZE / size, 2);
|
||||
tree->bt_leaf_size = lsize;
|
||||
tree->bt_leaf_cap = P2ALIGN(esize / size, 2);
|
||||
tree->bt_height = -1;
|
||||
tree->bt_bulk = NULL;
|
||||
}
|
||||
@@ -290,7 +318,7 @@ zfs_btree_find(zfs_btree_t *tree, const void *value, zfs_btree_index_t *where)
|
||||
|
||||
zfs_btree_core_t *node = NULL;
|
||||
uint32_t child = 0;
|
||||
uint64_t depth = 0;
|
||||
uint32_t depth = 0;
|
||||
|
||||
/*
|
||||
* Iterate down the tree, finding which child the value should be in
|
||||
@@ -811,8 +839,7 @@ zfs_btree_insert_into_leaf(zfs_btree_t *tree, zfs_btree_leaf_t *leaf,
|
||||
move_count++;
|
||||
}
|
||||
tree->bt_num_nodes++;
|
||||
zfs_btree_leaf_t *new_leaf = kmem_cache_alloc(zfs_btree_leaf_cache,
|
||||
KM_SLEEP);
|
||||
zfs_btree_leaf_t *new_leaf = zfs_btree_leaf_alloc(tree);
|
||||
zfs_btree_hdr_t *new_hdr = &new_leaf->btl_hdr;
|
||||
new_hdr->bth_parent = leaf->btl_hdr.bth_parent;
|
||||
new_hdr->bth_first = (tree->bt_bulk ? 0 : capacity / 4) +
|
||||
@@ -1078,8 +1105,7 @@ zfs_btree_add_idx(zfs_btree_t *tree, const void *value,
|
||||
ASSERT0(where->bti_offset);
|
||||
|
||||
tree->bt_num_nodes++;
|
||||
zfs_btree_leaf_t *leaf = kmem_cache_alloc(zfs_btree_leaf_cache,
|
||||
KM_SLEEP);
|
||||
zfs_btree_leaf_t *leaf = zfs_btree_leaf_alloc(tree);
|
||||
tree->bt_root = &leaf->btl_hdr;
|
||||
tree->bt_height++;
|
||||
|
||||
@@ -1378,7 +1404,7 @@ zfs_btree_node_destroy(zfs_btree_t *tree, zfs_btree_hdr_t *node)
|
||||
{
|
||||
tree->bt_num_nodes--;
|
||||
if (!zfs_btree_is_core(node)) {
|
||||
kmem_cache_free(zfs_btree_leaf_cache, node);
|
||||
zfs_btree_leaf_free(tree, node);
|
||||
} else {
|
||||
kmem_free(node, sizeof (zfs_btree_core_t) +
|
||||
BTREE_CORE_ELEMS * tree->bt_elem_size);
|
||||
@@ -1991,7 +2017,7 @@ zfs_btree_verify_counts(zfs_btree_t *tree)
|
||||
*/
|
||||
static uint64_t
|
||||
zfs_btree_verify_height_helper(zfs_btree_t *tree, zfs_btree_hdr_t *hdr,
|
||||
int64_t height)
|
||||
int32_t height)
|
||||
{
|
||||
if (!zfs_btree_is_core(hdr)) {
|
||||
VERIFY0(height);
|
||||
@@ -2117,8 +2143,10 @@ zfs_btree_verify_poison_helper(zfs_btree_t *tree, zfs_btree_hdr_t *hdr)
|
||||
zfs_btree_leaf_t *leaf = (zfs_btree_leaf_t *)hdr;
|
||||
for (size_t i = 0; i < hdr->bth_first * size; i++)
|
||||
VERIFY3U(leaf->btl_elems[i], ==, 0x0f);
|
||||
size_t esize = tree->bt_leaf_size -
|
||||
offsetof(zfs_btree_leaf_t, btl_elems);
|
||||
for (size_t i = (hdr->bth_first + hdr->bth_count) * size;
|
||||
i < BTREE_LEAF_ESIZE; i++)
|
||||
i < esize; i++)
|
||||
VERIFY3U(leaf->btl_elems[i], ==, 0x0f);
|
||||
} else {
|
||||
zfs_btree_core_t *node = (zfs_btree_core_t *)hdr;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user