mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 21:05:08 +00:00
Notable upstream pull request merges:
#15539687e4d7f9
Extend import_progress kstat with a notes field #15544c7b611926
Allow block cloning across encrypted datasets #15553adcea23cb
ZIO: Add overflow checks for linear buffers #155935f2700eee
zpool: flush output before sleeping #156093e4bef52b
Only provide execvpe(3) when needed #15610735ba3a7b
Use uint64_t instead of u_int64_t #15612bcd83ccd2
ZIL: Remove TX_CLONE_RANGE replay for ZVOLs #1561755b764e06
ZIL: Do not clone blocks from the future #15623727497ccd
module/icp/asm-arm/sha2: enable non-SIMD asm kernels on armv5/6 #156259743d0963
BRT: Limit brt_vdev_dump() to only one vdev #15629f9765b182
zdb: Dump encrypted write and clone ZIL records #156342aa3a482a
ZIL: Remove 128K into 2x68K LWB split optimization #1563911656234b
FreeBSD: Ensure that zfs_getattr() initializes the va_rdev field #156474836d293c
zfs_refcount_remove: explictly ignore returns #15649f0cb6482e
setproctitle: fix ununitialised variable #15650450f2d0b0
import: ignore return on hostid lookups Obtained from: OpenZFS OpenZFS commit:450f2d0b08
This commit is contained in:
commit
3494f7c019
|
@ -168,7 +168,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
|
||||
(u_longlong_t)lr->lr_length);
|
||||
|
||||
if (txtype == TX_WRITE2 || verbose < 5)
|
||||
if (txtype == TX_WRITE2 || verbose < 4)
|
||||
return;
|
||||
|
||||
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
|
||||
|
@ -178,6 +178,8 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||
"will claim" : "won't claim");
|
||||
print_log_bp(bp, tab_prefix);
|
||||
|
||||
if (verbose < 5)
|
||||
return;
|
||||
if (BP_IS_HOLE(bp)) {
|
||||
(void) printf("\t\t\tLSIZE 0x%llx\n",
|
||||
(u_longlong_t)BP_GET_LSIZE(bp));
|
||||
|
@ -202,6 +204,9 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||
if (error)
|
||||
goto out;
|
||||
} else {
|
||||
if (verbose < 5)
|
||||
return;
|
||||
|
||||
/* data is stored after the end of the lr_write record */
|
||||
data = abd_alloc(lr->lr_length, B_FALSE);
|
||||
abd_copy_from_buf(data, lr + 1, lr->lr_length);
|
||||
|
@ -217,6 +222,28 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||
abd_free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
zil_prt_rec_write_enc(zilog_t *zilog, int txtype, const void *arg)
|
||||
{
|
||||
(void) txtype;
|
||||
const lr_write_t *lr = arg;
|
||||
const blkptr_t *bp = &lr->lr_blkptr;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
|
||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
||||
|
||||
if (verbose < 4)
|
||||
return;
|
||||
|
||||
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
|
||||
(void) printf("%shas blkptr, %s\n", tab_prefix,
|
||||
!BP_IS_HOLE(bp) &&
|
||||
bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa) ?
|
||||
"will claim" : "won't claim");
|
||||
print_log_bp(bp, tab_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
|
||||
{
|
||||
|
@ -312,11 +339,34 @@ zil_prt_rec_clone_range(zilog_t *zilog, int txtype, const void *arg)
|
|||
{
|
||||
(void) zilog, (void) txtype;
|
||||
const lr_clone_range_t *lr = arg;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
|
||||
(void) printf("%sfoid %llu, offset %llx, length %llx, blksize %llx\n",
|
||||
tab_prefix, (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
|
||||
(u_longlong_t)lr->lr_length, (u_longlong_t)lr->lr_blksz);
|
||||
|
||||
if (verbose < 4)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < lr->lr_nbps; i++) {
|
||||
(void) printf("%s[%u/%llu] ", tab_prefix, i + 1,
|
||||
(u_longlong_t)lr->lr_nbps);
|
||||
print_log_bp(&lr->lr_bps[i], "");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zil_prt_rec_clone_range_enc(zilog_t *zilog, int txtype, const void *arg)
|
||||
{
|
||||
(void) zilog, (void) txtype;
|
||||
const lr_clone_range_t *lr = arg;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
|
||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
||||
|
||||
if (verbose < 4)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < lr->lr_nbps; i++) {
|
||||
(void) printf("%s[%u/%llu] ", tab_prefix, i + 1,
|
||||
(u_longlong_t)lr->lr_nbps);
|
||||
|
@ -327,6 +377,7 @@ zil_prt_rec_clone_range(zilog_t *zilog, int txtype, const void *arg)
|
|||
typedef void (*zil_prt_rec_func_t)(zilog_t *, int, const void *);
|
||||
typedef struct zil_rec_info {
|
||||
zil_prt_rec_func_t zri_print;
|
||||
zil_prt_rec_func_t zri_print_enc;
|
||||
const char *zri_name;
|
||||
uint64_t zri_count;
|
||||
} zil_rec_info_t;
|
||||
|
@ -341,7 +392,9 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
|||
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_RMDIR "},
|
||||
{.zri_print = zil_prt_rec_link, .zri_name = "TX_LINK "},
|
||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME "},
|
||||
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE "},
|
||||
{.zri_print = zil_prt_rec_write,
|
||||
.zri_print_enc = zil_prt_rec_write_enc,
|
||||
.zri_name = "TX_WRITE "},
|
||||
{.zri_print = zil_prt_rec_truncate, .zri_name = "TX_TRUNCATE "},
|
||||
{.zri_print = zil_prt_rec_setattr, .zri_name = "TX_SETATTR "},
|
||||
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_V0 "},
|
||||
|
@ -358,6 +411,7 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
|||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME_EXCHANGE "},
|
||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME_WHITEOUT "},
|
||||
{.zri_print = zil_prt_rec_clone_range,
|
||||
.zri_print_enc = zil_prt_rec_clone_range_enc,
|
||||
.zri_name = "TX_CLONE_RANGE "},
|
||||
};
|
||||
|
||||
|
@ -384,6 +438,8 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
|||
if (txtype && verbose >= 3) {
|
||||
if (!zilog->zl_os->os_encrypted) {
|
||||
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
|
||||
} else if (zil_rec_info[txtype].zri_print_enc) {
|
||||
zil_rec_info[txtype].zri_print_enc(zilog, txtype, lr);
|
||||
} else {
|
||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
||||
}
|
||||
|
|
|
@ -205,6 +205,10 @@ zed_notify()
|
|||
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
|
||||
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
|
||||
|
||||
zed_notify_ntfy "${subject}" "${pathname}"; rv=$?
|
||||
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
|
||||
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
|
||||
|
||||
[ "${num_success}" -gt 0 ] && return 0
|
||||
[ "${num_failure}" -gt 0 ] && return 1
|
||||
return 2
|
||||
|
@ -527,6 +531,100 @@ zed_notify_pushover()
|
|||
}
|
||||
|
||||
|
||||
# zed_notify_ntfy (subject, pathname)
|
||||
#
|
||||
# Send a notification via Ntfy.sh <https://ntfy.sh/>.
|
||||
# The ntfy topic (ZED_NTFY_TOPIC) identifies the topic that the notification
|
||||
# will be sent to Ntfy.sh server. The ntfy url (ZED_NTFY_URL) defines the
|
||||
# self-hosted or provided hosted ntfy service location. The ntfy access token
|
||||
# <https://docs.ntfy.sh/publish/#access-tokens> (ZED_NTFY_ACCESS_TOKEN) reprsents an
|
||||
# access token that could be used if a topic is read/write protected. If a
|
||||
# topic can be written to publicaly, a ZED_NTFY_ACCESS_TOKEN is not required.
|
||||
#
|
||||
# Requires curl and sed executables to be installed in the standard PATH.
|
||||
#
|
||||
# References
|
||||
# https://docs.ntfy.sh
|
||||
#
|
||||
# Arguments
|
||||
# subject: notification subject
|
||||
# pathname: pathname containing the notification message (OPTIONAL)
|
||||
#
|
||||
# Globals
|
||||
# ZED_NTFY_TOPIC
|
||||
# ZED_NTFY_ACCESS_TOKEN (OPTIONAL)
|
||||
# ZED_NTFY_URL
|
||||
#
|
||||
# Return
|
||||
# 0: notification sent
|
||||
# 1: notification failed
|
||||
# 2: not configured
|
||||
#
|
||||
zed_notify_ntfy()
|
||||
{
|
||||
local subject="$1"
|
||||
local pathname="${2:-"/dev/null"}"
|
||||
local msg_body
|
||||
local msg_out
|
||||
local msg_err
|
||||
|
||||
[ -n "${ZED_NTFY_TOPIC}" ] || return 2
|
||||
local url="${ZED_NTFY_URL:-"https://ntfy.sh"}/${ZED_NTFY_TOPIC}"
|
||||
|
||||
if [ ! -r "${pathname}" ]; then
|
||||
zed_log_err "ntfy cannot read \"${pathname}\""
|
||||
return 1
|
||||
fi
|
||||
|
||||
zed_check_cmd "curl" "sed" || return 1
|
||||
|
||||
# Read the message body in.
|
||||
#
|
||||
msg_body="$(cat "${pathname}")"
|
||||
|
||||
if [ -z "${msg_body}" ]
|
||||
then
|
||||
msg_body=$subject
|
||||
subject=""
|
||||
fi
|
||||
|
||||
# Send the POST request and check for errors.
|
||||
#
|
||||
if [ -n "${ZED_NTFY_ACCESS_TOKEN}" ]; then
|
||||
msg_out="$( \
|
||||
curl \
|
||||
-u ":${ZED_NTFY_ACCESS_TOKEN}" \
|
||||
-H "Title: ${subject}" \
|
||||
-d "${msg_body}" \
|
||||
-H "Priority: high" \
|
||||
"${url}" \
|
||||
2>/dev/null \
|
||||
)"; rv=$?
|
||||
else
|
||||
msg_out="$( \
|
||||
curl \
|
||||
-H "Title: ${subject}" \
|
||||
-d "${msg_body}" \
|
||||
-H "Priority: high" \
|
||||
"${url}" \
|
||||
2>/dev/null \
|
||||
)"; rv=$?
|
||||
fi
|
||||
if [ "${rv}" -ne 0 ]; then
|
||||
zed_log_err "curl exit=${rv}"
|
||||
return 1
|
||||
fi
|
||||
msg_err="$(echo "${msg_out}" \
|
||||
| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
|
||||
if [ -n "${msg_err}" ]; then
|
||||
zed_log_err "ntfy \"${msg_err}"\"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
# zed_rate_limit (tag, [interval])
|
||||
#
|
||||
# Check whether an event of a given type [tag] has already occurred within the
|
||||
|
|
|
@ -147,3 +147,25 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
|
|||
# help silence misbehaving drives. This assumes your drive enclosure fully
|
||||
# supports slot power control via sysfs.
|
||||
#ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT=1
|
||||
|
||||
##
|
||||
# Ntfy topic
|
||||
# This defines which topic will receive the ntfy notification.
|
||||
# <https://docs.ntfy.sh/publish/>
|
||||
# Disabled by default; uncomment to enable.
|
||||
#ZED_NTFY_TOPIC=""
|
||||
|
||||
##
|
||||
# Ntfy access token (optional for public topics)
|
||||
# This defines an access token which can be used
|
||||
# to allow you to authenticate when sending to topics
|
||||
# <https://docs.ntfy.sh/publish/#access-tokens>
|
||||
# Disabled by default; uncomment to enable.
|
||||
#ZED_NTFY_ACCESS_TOKEN=""
|
||||
|
||||
##
|
||||
# Ntfy Service URL
|
||||
# This defines which service the ntfy call will be directed toward
|
||||
# <https://docs.ntfy.sh/install/>
|
||||
# https://ntfy.sh by default; uncomment to enable an alternative service url.
|
||||
#ZED_NTFY_URL="https://ntfy.sh"
|
||||
|
|
|
@ -3132,7 +3132,8 @@ zfs_force_import_required(nvlist_t *config)
|
|||
* local hostid.
|
||||
*/
|
||||
if (nvlist_lookup_uint64(nvinfo, ZPOOL_CONFIG_HOSTID, &hostid) != 0)
|
||||
nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
|
||||
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
|
||||
&hostid);
|
||||
|
||||
if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
|
||||
return (B_TRUE);
|
||||
|
@ -5950,6 +5951,7 @@ zpool_do_iostat(int argc, char **argv)
|
|||
print_iostat_header(&cb);
|
||||
|
||||
if (skip) {
|
||||
(void) fflush(stdout);
|
||||
(void) fsleep(interval);
|
||||
continue;
|
||||
}
|
||||
|
@ -5980,18 +5982,13 @@ zpool_do_iostat(int argc, char **argv)
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the output so that redirection to a file isn't buffered
|
||||
* indefinitely.
|
||||
*/
|
||||
(void) fflush(stdout);
|
||||
|
||||
if (interval == 0)
|
||||
break;
|
||||
|
||||
if (count != 0 && --count == 0)
|
||||
break;
|
||||
|
||||
(void) fflush(stdout);
|
||||
(void) fsleep(interval);
|
||||
}
|
||||
|
||||
|
@ -6514,6 +6511,8 @@ zpool_do_list(int argc, char **argv)
|
|||
break;
|
||||
|
||||
pool_list_free(list);
|
||||
|
||||
(void) fflush(stdout);
|
||||
(void) fsleep(interval);
|
||||
}
|
||||
|
||||
|
@ -9094,6 +9093,7 @@ zpool_do_status(int argc, char **argv)
|
|||
if (count != 0 && --count == 0)
|
||||
break;
|
||||
|
||||
(void) fflush(stdout);
|
||||
(void) fsleep(interval);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
dnl #
|
||||
dnl # Starting from Linux 5.13, flush_dcache_page() becomes an inline
|
||||
dnl # function and may indirectly referencing GPL-only cpu_feature_keys on
|
||||
dnl # powerpc
|
||||
dnl # function and may indirectly referencing GPL-only symbols:
|
||||
dnl # on powerpc: cpu_feature_keys
|
||||
dnl # on riscv: PageHuge (added from 6.2)
|
||||
dnl #
|
||||
|
||||
dnl #
|
||||
|
|
|
@ -168,6 +168,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
|
|||
ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
|
||||
ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE
|
||||
;;
|
||||
riscv*)
|
||||
ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([for available kernel interfaces])
|
||||
|
@ -310,6 +313,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
|
|||
ZFS_AC_KERNEL_CPU_HAS_FEATURE
|
||||
ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE
|
||||
;;
|
||||
riscv*)
|
||||
ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
|
|||
ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV
|
||||
ZFS_AC_CONFIG_USER_ZFSEXEC
|
||||
|
||||
AC_CHECK_FUNCS([issetugid mlockall strlcat strlcpy])
|
||||
AC_CHECK_FUNCS([execvpe issetugid mlockall strlcat strlcpy])
|
||||
|
||||
AC_SUBST(RM)
|
||||
])
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _OPENSOLARIS_SYS_TIME_H_
|
||||
|
@ -91,6 +89,6 @@ gethrtime(void)
|
|||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_UPTIME, &ts);
|
||||
return (((u_int64_t)ts.tv_sec) * NANOSEC + ts.tv_nsec);
|
||||
return (((uint64_t)ts.tv_sec) * NANOSEC + ts.tv_nsec);
|
||||
}
|
||||
#endif /* !_OPENSOLARIS_SYS_TIME_H_ */
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
/*
|
||||
* Starting from Linux 5.13, flush_dcache_page() becomes an inline function
|
||||
* and under some configurations, may indirectly referencing GPL-only
|
||||
* cpu_feature_keys on powerpc. Override this function when it is detected
|
||||
* being GPL-only.
|
||||
* symbols, e.g., cpu_feature_keys on powerpc and PageHuge on riscv.
|
||||
* Override this function when it is detected being GPL-only.
|
||||
*/
|
||||
#if defined __powerpc__ && defined HAVE_FLUSH_DCACHE_PAGE_GPL_ONLY
|
||||
#include <linux/simd_powerpc.h>
|
||||
|
@ -53,6 +53,17 @@
|
|||
clear_bit(PG_dcache_clean, &(page)->flags); \
|
||||
} while (0)
|
||||
#endif
|
||||
/*
|
||||
* For riscv implementation, the use of PageHuge can be safely removed.
|
||||
* Because it handles pages allocated by HugeTLB, while flush_dcache_page
|
||||
* in zfs module is only called on kernel pages.
|
||||
*/
|
||||
#if defined __riscv && defined HAVE_FLUSH_DCACHE_PAGE_GPL_ONLY
|
||||
#define flush_dcache_page(page) do { \
|
||||
if (test_bit(PG_dcache_clean, &(page)->flags)) \
|
||||
clear_bit(PG_dcache_clean, &(page)->flags); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2.6.30 API change,
|
||||
|
|
|
@ -206,6 +206,7 @@ void dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin,
|
|||
dmu_tx_t *tx);
|
||||
int dmu_objset_create_crypt_check(dsl_dir_t *parentdd,
|
||||
dsl_crypto_params_t *dcp, boolean_t *will_encrypt);
|
||||
boolean_t dmu_objset_crypto_key_equal(objset_t *osa, objset_t *osb);
|
||||
void dsl_dataset_create_crypt_sync(uint64_t dsobj, dsl_dir_t *dd,
|
||||
struct dsl_dataset *origin, dsl_crypto_params_t *dcp, dmu_tx_t *tx);
|
||||
uint64_t dsl_crypto_key_create_sync(uint64_t crypt, dsl_wrapping_key_t *wkey,
|
||||
|
|
|
@ -971,6 +971,10 @@ extern int spa_import_progress_set_max_txg(uint64_t pool_guid,
|
|||
uint64_t max_txg);
|
||||
extern int spa_import_progress_set_state(uint64_t pool_guid,
|
||||
spa_load_state_t spa_load_state);
|
||||
extern void spa_import_progress_set_notes(spa_t *spa,
|
||||
const char *fmt, ...) __printflike(2, 3);
|
||||
extern void spa_import_progress_set_notes_nolog(spa_t *spa,
|
||||
const char *fmt, ...) __printflike(2, 3);
|
||||
|
||||
/* Pool configuration locks */
|
||||
extern int spa_config_tryenter(spa_t *spa, int locks, const void *tag,
|
||||
|
|
|
@ -64,6 +64,9 @@ libspl_assert(const char *buf, const char *file, const char *func, int line)
|
|||
#undef verify
|
||||
#endif
|
||||
|
||||
#define PANIC(fmt, a...) \
|
||||
libspl_assertf(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
|
||||
|
||||
#define VERIFY(cond) \
|
||||
(void) ((!(cond)) && \
|
||||
libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
extern size_t spl_pagesize(void);
|
||||
#define PAGESIZE (spl_pagesize())
|
||||
|
||||
#ifndef HAVE_EXECVPE
|
||||
extern int execvpe(const char *name, char * const argv[], char * const envp[]);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -101,7 +101,7 @@ gethrtime(void)
|
|||
{
|
||||
struct timespec ts;
|
||||
(void) clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
|
||||
return ((((uint64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
|
||||
}
|
||||
|
||||
#endif /* _LIBSPL_SYS_TIME_H */
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
#define ZFS_KMOD "openzfs"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_EXECVPE
|
||||
/* FreeBSD prior to 15 lacks execvpe */
|
||||
static int
|
||||
execvPe(const char *name, const char *path, char * const *argv,
|
||||
char * const *envp)
|
||||
|
@ -192,6 +193,7 @@ execvpe(const char *name, char * const argv[], char * const envp[])
|
|||
|
||||
return (execvPe(name, path, argv, envp));
|
||||
}
|
||||
#endif /* !HAVE_EXECVPE */
|
||||
|
||||
static __thread char errbuf[ERRBUFLEN];
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ spt_copyenv(int envc, char *envp[])
|
|||
char **envcopy;
|
||||
char *eq;
|
||||
int envsize;
|
||||
int i, error;
|
||||
int i, error = 0;
|
||||
|
||||
if (environ != envp)
|
||||
return (0);
|
||||
|
|
|
@ -364,9 +364,12 @@ When this feature is enabled ZFS will use block cloning for operations like
|
|||
Block cloning allows to create multiple references to a single block.
|
||||
It is much faster than copying the data (as the actual data is neither read nor
|
||||
written) and takes no additional space.
|
||||
Blocks can be cloned across datasets under some conditions (like disabled
|
||||
encryption and equal
|
||||
.Nm recordsize ) .
|
||||
Blocks can be cloned across datasets under some conditions (like equal
|
||||
.Nm recordsize ,
|
||||
the same master encryption key, etc.).
|
||||
ZFS tries its best to clone across datasets including encrypted ones.
|
||||
This is limited for various (nontrivial) reasons depending on the OS
|
||||
and/or ZFS internals.
|
||||
.Pp
|
||||
This feature becomes
|
||||
.Sy active
|
||||
|
|
|
@ -118,7 +118,15 @@ const sha256_ops_t sha256_shani_impl = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#elif defined(__aarch64__) || (defined(__arm__) && __ARM_ARCH > 6)
|
||||
#elif defined(__aarch64__) || defined(__arm__)
|
||||
extern void zfs_sha256_block_armv7(uint32_t s[8], const void *, size_t);
|
||||
const sha256_ops_t sha256_armv7_impl = {
|
||||
.is_supported = sha2_is_supported,
|
||||
.transform = zfs_sha256_block_armv7,
|
||||
.name = "armv7"
|
||||
};
|
||||
|
||||
#if __ARM_ARCH > 6
|
||||
static boolean_t sha256_have_neon(void)
|
||||
{
|
||||
return (kfpu_allowed() && zfs_neon_available());
|
||||
|
@ -129,13 +137,6 @@ static boolean_t sha256_have_armv8ce(void)
|
|||
return (kfpu_allowed() && zfs_sha256_available());
|
||||
}
|
||||
|
||||
extern void zfs_sha256_block_armv7(uint32_t s[8], const void *, size_t);
|
||||
const sha256_ops_t sha256_armv7_impl = {
|
||||
.is_supported = sha2_is_supported,
|
||||
.transform = zfs_sha256_block_armv7,
|
||||
.name = "armv7"
|
||||
};
|
||||
|
||||
TF(zfs_sha256_block_neon, tf_sha256_neon);
|
||||
const sha256_ops_t sha256_neon_impl = {
|
||||
.is_supported = sha256_have_neon,
|
||||
|
@ -149,6 +150,7 @@ const sha256_ops_t sha256_armv8_impl = {
|
|||
.transform = tf_sha256_armv8ce,
|
||||
.name = "armv8-ce"
|
||||
};
|
||||
#endif
|
||||
|
||||
#elif defined(__PPC64__)
|
||||
static boolean_t sha256_have_isa207(void)
|
||||
|
@ -192,11 +194,13 @@ static const sha256_ops_t *const sha256_impls[] = {
|
|||
#if defined(__x86_64) && defined(HAVE_SSE4_1)
|
||||
&sha256_shani_impl,
|
||||
#endif
|
||||
#if defined(__aarch64__) || (defined(__arm__) && __ARM_ARCH > 6)
|
||||
#if defined(__aarch64__) || defined(__arm__)
|
||||
&sha256_armv7_impl,
|
||||
#if __ARM_ARCH > 6
|
||||
&sha256_neon_impl,
|
||||
&sha256_armv8_impl,
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PPC64__)
|
||||
&sha256_ppc_impl,
|
||||
&sha256_power8_impl,
|
||||
|
|
|
@ -88,7 +88,7 @@ const sha512_ops_t sha512_avx2_impl = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
#elif defined(__aarch64__) || defined(__arm__)
|
||||
extern void zfs_sha512_block_armv7(uint64_t s[8], const void *, size_t);
|
||||
const sha512_ops_t sha512_armv7_impl = {
|
||||
.is_supported = sha2_is_supported,
|
||||
|
@ -96,6 +96,7 @@ const sha512_ops_t sha512_armv7_impl = {
|
|||
.name = "armv7"
|
||||
};
|
||||
|
||||
#if defined(__aarch64__)
|
||||
static boolean_t sha512_have_armv8ce(void)
|
||||
{
|
||||
return (kfpu_allowed() && zfs_sha512_available());
|
||||
|
@ -107,15 +108,9 @@ const sha512_ops_t sha512_armv8_impl = {
|
|||
.transform = tf_sha512_armv8ce,
|
||||
.name = "armv8-ce"
|
||||
};
|
||||
#endif
|
||||
|
||||
#elif defined(__arm__) && __ARM_ARCH > 6
|
||||
extern void zfs_sha512_block_armv7(uint64_t s[8], const void *, size_t);
|
||||
const sha512_ops_t sha512_armv7_impl = {
|
||||
.is_supported = sha2_is_supported,
|
||||
.transform = zfs_sha512_block_armv7,
|
||||
.name = "armv7"
|
||||
};
|
||||
|
||||
#if defined(__arm__) && __ARM_ARCH > 6
|
||||
static boolean_t sha512_have_neon(void)
|
||||
{
|
||||
return (kfpu_allowed() && zfs_neon_available());
|
||||
|
@ -127,6 +122,7 @@ const sha512_ops_t sha512_neon_impl = {
|
|||
.transform = tf_sha512_neon,
|
||||
.name = "neon"
|
||||
};
|
||||
#endif
|
||||
|
||||
#elif defined(__PPC64__)
|
||||
TF(zfs_sha512_ppc, tf_sha512_ppc);
|
||||
|
@ -164,14 +160,15 @@ static const sha512_ops_t *const sha512_impls[] = {
|
|||
#if defined(__x86_64) && defined(HAVE_AVX2)
|
||||
&sha512_avx2_impl,
|
||||
#endif
|
||||
#if defined(__aarch64__)
|
||||
#if defined(__aarch64__) || defined(__arm__)
|
||||
&sha512_armv7_impl,
|
||||
#if defined(__aarch64__)
|
||||
&sha512_armv8_impl,
|
||||
#endif
|
||||
#if defined(__arm__) && __ARM_ARCH > 6
|
||||
&sha512_armv7_impl,
|
||||
&sha512_neon_impl,
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PPC64__)
|
||||
&sha512_ppc_impl,
|
||||
&sha512_power8_impl,
|
||||
|
|
|
@ -1837,6 +1837,7 @@ zfs_sha256_block_armv7:
|
|||
#endif
|
||||
.size zfs_sha256_block_armv7,.-zfs_sha256_block_armv7
|
||||
|
||||
#if __ARM_ARCH__ >= 7
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
|
@ -1849,11 +1850,7 @@ zfs_sha256_block_neon:
|
|||
stmdb sp!,{r4-r12,lr}
|
||||
|
||||
sub r11,sp,#16*4+16
|
||||
#if __ARM_ARCH__ >=7
|
||||
adr r14,K256
|
||||
#else
|
||||
ldr r14,=K256
|
||||
#endif
|
||||
bic r11,r11,#15 @ align for 128-bit stores
|
||||
mov r12,sp
|
||||
mov sp,r11 @ alloca
|
||||
|
@ -2773,4 +2770,5 @@ zfs_sha256_block_armv8:
|
|||
bx lr @ bx lr
|
||||
.size zfs_sha256_block_armv8,.-zfs_sha256_block_armv8
|
||||
|
||||
#endif
|
||||
#endif // #if __ARM_ARCH__ >= 7
|
||||
#endif // #if defined(__arm__)
|
||||
|
|
|
@ -493,6 +493,7 @@ zfs_sha512_block_armv7:
|
|||
#endif
|
||||
.size zfs_sha512_block_armv7,.-zfs_sha512_block_armv7
|
||||
|
||||
#if __ARM_ARCH__ >= 7
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
|
@ -1822,4 +1823,5 @@ zfs_sha512_block_neon:
|
|||
VFP_ABI_POP
|
||||
bx lr @ .word 0xe12fff1e
|
||||
.size zfs_sha512_block_neon,.-zfs_sha512_block_neon
|
||||
#endif
|
||||
#endif // #if __ARM_ARCH__ >= 7
|
||||
#endif // #if defined(__arm__)
|
||||
|
|
|
@ -2011,6 +2011,8 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
|
|||
vap->va_size = zp->z_size;
|
||||
if (vp->v_type == VBLK || vp->v_type == VCHR)
|
||||
vap->va_rdev = zfs_cmpldev(rdev);
|
||||
else
|
||||
vap->va_rdev = 0;
|
||||
vap->va_gen = zp->z_gen;
|
||||
vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */
|
||||
vap->va_filerev = zp->z_seq;
|
||||
|
|
|
@ -6069,7 +6069,7 @@ arc_prune_task(void *ptr)
|
|||
if (func != NULL)
|
||||
func(ap->p_adjust, ap->p_private);
|
||||
|
||||
zfs_refcount_remove(&ap->p_refcnt, func);
|
||||
(void) zfs_refcount_remove(&ap->p_refcnt, func);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6098,7 +6098,7 @@ arc_prune_async(uint64_t adjust)
|
|||
ap->p_adjust = adjust;
|
||||
if (taskq_dispatch(arc_prune_taskq, arc_prune_task,
|
||||
ap, TQ_SLEEP) == TASKQID_INVALID) {
|
||||
zfs_refcount_remove(&ap->p_refcnt, ap->p_pfunc);
|
||||
(void) zfs_refcount_remove(&ap->p_refcnt, ap->p_pfunc);
|
||||
continue;
|
||||
}
|
||||
ARCSTAT_BUMP(arcstat_prune);
|
||||
|
@ -7720,7 +7720,7 @@ arc_fini(void)
|
|||
|
||||
mutex_enter(&arc_prune_mtx);
|
||||
while ((p = list_remove_head(&arc_prune_list)) != NULL) {
|
||||
zfs_refcount_remove(&p->p_refcnt, &arc_prune_list);
|
||||
(void) zfs_refcount_remove(&p->p_refcnt, &arc_prune_list);
|
||||
zfs_refcount_destroy(&p->p_refcnt);
|
||||
kmem_free(p, sizeof (*p));
|
||||
}
|
||||
|
@ -8301,7 +8301,8 @@ l2arc_write_done(zio_t *zio)
|
|||
ARCSTAT_BUMPDOWN(arcstat_l2_log_blk_count);
|
||||
zfs_refcount_remove_many(&dev->l2ad_lb_asize, asize,
|
||||
lb_ptr_buf);
|
||||
zfs_refcount_remove(&dev->l2ad_lb_count, lb_ptr_buf);
|
||||
(void) zfs_refcount_remove(&dev->l2ad_lb_count,
|
||||
lb_ptr_buf);
|
||||
kmem_free(lb_ptr_buf->lb_ptr,
|
||||
sizeof (l2arc_log_blkptr_t));
|
||||
kmem_free(lb_ptr_buf, sizeof (l2arc_lb_ptr_buf_t));
|
||||
|
@ -8772,7 +8773,8 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all)
|
|||
ARCSTAT_BUMPDOWN(arcstat_l2_log_blk_count);
|
||||
zfs_refcount_remove_many(&dev->l2ad_lb_asize, asize,
|
||||
lb_ptr_buf);
|
||||
zfs_refcount_remove(&dev->l2ad_lb_count, lb_ptr_buf);
|
||||
(void) zfs_refcount_remove(&dev->l2ad_lb_count,
|
||||
lb_ptr_buf);
|
||||
list_remove(&dev->l2ad_lbptr_list, lb_ptr_buf);
|
||||
kmem_free(lb_ptr_buf->lb_ptr,
|
||||
sizeof (l2arc_log_blkptr_t));
|
||||
|
|
|
@ -157,10 +157,8 @@
|
|||
* (copying the file content to the new dataset and removing the source file).
|
||||
* In that case Block Cloning will only be used briefly, because the BRT entries
|
||||
* will be removed when the source is removed.
|
||||
* Note: currently it is not possible to clone blocks between encrypted
|
||||
* datasets, even if those datasets use the same encryption key (this includes
|
||||
* snapshots of encrypted datasets). Cloning blocks between datasets that use
|
||||
* the same keys should be possible and should be implemented in the future.
|
||||
* Block Cloning across encrypted datasets is supported as long as both
|
||||
* datasets share the same master key (e.g. snapshots and clones)
|
||||
*
|
||||
* Block Cloning flow through ZFS layers.
|
||||
*
|
||||
|
@ -344,7 +342,7 @@ brt_vdev_entcount_get(const brt_vdev_t *brtvd, uint64_t idx)
|
|||
|
||||
ASSERT3U(idx, <, brtvd->bv_size);
|
||||
|
||||
if (brtvd->bv_need_byteswap) {
|
||||
if (unlikely(brtvd->bv_need_byteswap)) {
|
||||
return (BSWAP_16(brtvd->bv_entcount[idx]));
|
||||
} else {
|
||||
return (brtvd->bv_entcount[idx]);
|
||||
|
@ -357,7 +355,7 @@ brt_vdev_entcount_set(brt_vdev_t *brtvd, uint64_t idx, uint16_t entcnt)
|
|||
|
||||
ASSERT3U(idx, <, brtvd->bv_size);
|
||||
|
||||
if (brtvd->bv_need_byteswap) {
|
||||
if (unlikely(brtvd->bv_need_byteswap)) {
|
||||
brtvd->bv_entcount[idx] = BSWAP_16(entcnt);
|
||||
} else {
|
||||
brtvd->bv_entcount[idx] = entcnt;
|
||||
|
@ -392,28 +390,13 @@ brt_vdev_entcount_dec(brt_vdev_t *brtvd, uint64_t idx)
|
|||
|
||||
#ifdef ZFS_DEBUG
|
||||
static void
|
||||
brt_vdev_dump(brt_t *brt)
|
||||
brt_vdev_dump(brt_vdev_t *brtvd)
|
||||
{
|
||||
brt_vdev_t *brtvd;
|
||||
uint64_t vdevid;
|
||||
|
||||
if ((zfs_flags & ZFS_DEBUG_BRT) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (brt->brt_nvdevs == 0) {
|
||||
zfs_dbgmsg("BRT empty");
|
||||
return;
|
||||
}
|
||||
|
||||
zfs_dbgmsg("BRT vdev dump:");
|
||||
for (vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
|
||||
uint64_t idx;
|
||||
|
||||
brtvd = &brt->brt_vdevs[vdevid];
|
||||
zfs_dbgmsg(" vdevid=%llu/%llu meta_dirty=%d entcount_dirty=%d "
|
||||
zfs_dbgmsg(" BRT vdevid=%llu meta_dirty=%d entcount_dirty=%d "
|
||||
"size=%llu totalcount=%llu nblocks=%llu bitmapsize=%zu\n",
|
||||
(u_longlong_t)vdevid, (u_longlong_t)brtvd->bv_vdevid,
|
||||
(u_longlong_t)brtvd->bv_vdevid,
|
||||
brtvd->bv_meta_dirty, brtvd->bv_entcount_dirty,
|
||||
(u_longlong_t)brtvd->bv_size,
|
||||
(u_longlong_t)brtvd->bv_totalcount,
|
||||
|
@ -422,10 +405,10 @@ brt_vdev_dump(brt_t *brt)
|
|||
if (brtvd->bv_totalcount > 0) {
|
||||
zfs_dbgmsg(" entcounts:");
|
||||
for (idx = 0; idx < brtvd->bv_size; idx++) {
|
||||
if (brt_vdev_entcount_get(brtvd, idx) > 0) {
|
||||
uint16_t entcnt = brt_vdev_entcount_get(brtvd, idx);
|
||||
if (entcnt > 0) {
|
||||
zfs_dbgmsg(" [%04llu] %hu",
|
||||
(u_longlong_t)idx,
|
||||
brt_vdev_entcount_get(brtvd, idx));
|
||||
(u_longlong_t)idx, entcnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -438,10 +421,9 @@ brt_vdev_dump(brt_t *brt)
|
|||
BT_TEST(brtvd->bv_bitmap, idx) ? 'x' : '.';
|
||||
}
|
||||
bitmap[idx] = '\0';
|
||||
zfs_dbgmsg(" bitmap: %s", bitmap);
|
||||
zfs_dbgmsg(" dirty: %s", bitmap);
|
||||
kmem_free(bitmap, brtvd->bv_nblocks + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -769,7 +751,8 @@ brt_vdev_addref(brt_t *brt, brt_vdev_t *brtvd, const brt_entry_t *bre,
|
|||
BT_SET(brtvd->bv_bitmap, idx);
|
||||
|
||||
#ifdef ZFS_DEBUG
|
||||
brt_vdev_dump(brt);
|
||||
if (zfs_flags & ZFS_DEBUG_BRT)
|
||||
brt_vdev_dump(brtvd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -805,7 +788,8 @@ brt_vdev_decref(brt_t *brt, brt_vdev_t *brtvd, const brt_entry_t *bre,
|
|||
BT_SET(brtvd->bv_bitmap, idx);
|
||||
|
||||
#ifdef ZFS_DEBUG
|
||||
brt_vdev_dump(brt);
|
||||
if (zfs_flags & ZFS_DEBUG_BRT)
|
||||
brt_vdev_dump(brtvd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -2274,6 +2274,21 @@ dmu_read_l0_bps(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the block was allocated in transaction group that is not
|
||||
* yet synced, we could clone it, but we couldn't write this
|
||||
* operation into ZIL, or it may be impossible to replay, since
|
||||
* the block may appear not yet allocated at that point.
|
||||
*/
|
||||
if (BP_PHYSICAL_BIRTH(bp) > spa_freeze_txg(os->os_spa)) {
|
||||
error = SET_ERROR(EINVAL);
|
||||
goto out;
|
||||
}
|
||||
if (BP_PHYSICAL_BIRTH(bp) > spa_last_synced_txg(os->os_spa)) {
|
||||
error = SET_ERROR(EAGAIN);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bps[i] = *bp;
|
||||
}
|
||||
|
||||
|
|
|
@ -266,6 +266,40 @@ spa_crypto_key_compare(const void *a, const void *b)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* this compares a crypto key based on zk_guid. See comment on
|
||||
* spa_crypto_key_compare for more information.
|
||||
*/
|
||||
boolean_t
|
||||
dmu_objset_crypto_key_equal(objset_t *osa, objset_t *osb)
|
||||
{
|
||||
dsl_crypto_key_t *dcka = NULL;
|
||||
dsl_crypto_key_t *dckb = NULL;
|
||||
uint64_t obja, objb;
|
||||
boolean_t equal;
|
||||
spa_t *spa;
|
||||
|
||||
spa = dmu_objset_spa(osa);
|
||||
if (spa != dmu_objset_spa(osb))
|
||||
return (B_FALSE);
|
||||
obja = dmu_objset_ds(osa)->ds_object;
|
||||
objb = dmu_objset_ds(osb)->ds_object;
|
||||
|
||||
if (spa_keystore_lookup_key(spa, obja, FTAG, &dcka) != 0)
|
||||
return (B_FALSE);
|
||||
if (spa_keystore_lookup_key(spa, objb, FTAG, &dckb) != 0) {
|
||||
spa_keystore_dsl_key_rele(spa, dcka, FTAG);
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
equal = (dcka->dck_key.zk_guid == dckb->dck_key.zk_guid);
|
||||
|
||||
spa_keystore_dsl_key_rele(spa, dcka, FTAG);
|
||||
spa_keystore_dsl_key_rele(spa, dckb, FTAG);
|
||||
|
||||
return (equal);
|
||||
}
|
||||
|
||||
static int
|
||||
spa_key_mapping_compare(const void *a, const void *b)
|
||||
{
|
||||
|
|
|
@ -3109,6 +3109,7 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type)
|
|||
spa->spa_load_state = state;
|
||||
(void) spa_import_progress_set_state(spa_guid(spa),
|
||||
spa_load_state(spa));
|
||||
spa_import_progress_set_notes(spa, "spa_load()");
|
||||
|
||||
gethrestime(&spa->spa_loaded_ts);
|
||||
error = spa_load_impl(spa, type, &ereport);
|
||||
|
@ -3337,7 +3338,7 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
|
|||
uint64_t mmp_config = ub->ub_mmp_config;
|
||||
uint16_t mmp_seq = MMP_SEQ_VALID(ub) ? MMP_SEQ(ub) : 0;
|
||||
uint64_t import_delay;
|
||||
hrtime_t import_expire;
|
||||
hrtime_t import_expire, now;
|
||||
nvlist_t *mmp_label = NULL;
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
kcondvar_t cv;
|
||||
|
@ -3375,7 +3376,17 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
|
|||
|
||||
import_expire = gethrtime() + import_delay;
|
||||
|
||||
while (gethrtime() < import_expire) {
|
||||
spa_import_progress_set_notes(spa, "Checking MMP activity, waiting "
|
||||
"%llu ms", (u_longlong_t)NSEC2MSEC(import_delay));
|
||||
|
||||
int interations = 0;
|
||||
while ((now = gethrtime()) < import_expire) {
|
||||
if (interations++ % 30 == 0) {
|
||||
spa_import_progress_set_notes(spa, "Checking MMP "
|
||||
"activity, %llu ms remaining",
|
||||
(u_longlong_t)NSEC2MSEC(import_expire - now));
|
||||
}
|
||||
|
||||
(void) spa_import_progress_set_mmp_check(spa_guid(spa),
|
||||
NSEC2SEC(import_expire - gethrtime()));
|
||||
|
||||
|
@ -4995,6 +5006,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
/*
|
||||
* Retrieve the checkpoint txg if the pool has a checkpoint.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Loading checkpoint txg");
|
||||
error = spa_ld_read_checkpoint_txg(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5007,6 +5019,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* initiated. Otherwise we could be reading from indirect vdevs before
|
||||
* we have loaded their mappings.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Loading indirect vdev metadata");
|
||||
error = spa_ld_open_indirect_vdev_metadata(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5015,6 +5028,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* Retrieve the full list of active features from the MOS and check if
|
||||
* they are all supported.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Checking feature flags");
|
||||
error = spa_ld_check_features(spa, &missing_feat_write);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5023,6 +5037,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* Load several special directories from the MOS needed by the dsl_pool
|
||||
* layer.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Loading special MOS directories");
|
||||
error = spa_ld_load_special_directories(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5030,6 +5045,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
/*
|
||||
* Retrieve pool properties from the MOS.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Loading properties");
|
||||
error = spa_ld_get_props(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5038,6 +5054,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* Retrieve the list of auxiliary devices - cache devices and spares -
|
||||
* and open them.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Loading AUX vdevs");
|
||||
error = spa_ld_open_aux_vdevs(spa, type);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5046,14 +5063,17 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* Load the metadata for all vdevs. Also check if unopenable devices
|
||||
* should be autoreplaced.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Loading vdev metadata");
|
||||
error = spa_ld_load_vdev_metadata(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
spa_import_progress_set_notes(spa, "Loading dedup tables");
|
||||
error = spa_ld_load_dedup_tables(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
spa_import_progress_set_notes(spa, "Loading BRT");
|
||||
error = spa_ld_load_brt(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5062,6 +5082,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* Verify the logs now to make sure we don't have any unexpected errors
|
||||
* when we claim log blocks later.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Verifying Log Devices");
|
||||
error = spa_ld_verify_logs(spa, type, ereport);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5083,6 +5104,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* state. When performing an extreme rewind, we verify the whole pool,
|
||||
* which can take a very long time.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Verifying pool data");
|
||||
error = spa_ld_verify_pool_data(spa);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -5092,6 +5114,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* we write anything to the pool because we'd need to update the space
|
||||
* accounting using the deflated sizes.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Calculating deflated space");
|
||||
spa_update_dspace(spa);
|
||||
|
||||
/*
|
||||
|
@ -5099,6 +5122,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* pool. If we are importing the pool in read-write mode, a few
|
||||
* additional steps must be performed to finish the import.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Starting import");
|
||||
if (spa_writeable(spa) && (spa->spa_load_state == SPA_LOAD_RECOVER ||
|
||||
spa->spa_load_max_txg == UINT64_MAX)) {
|
||||
uint64_t config_cache_txg = spa->spa_config_txg;
|
||||
|
@ -5122,6 +5146,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
(u_longlong_t)spa->spa_uberblock.ub_checkpoint_txg);
|
||||
}
|
||||
|
||||
spa_import_progress_set_notes(spa, "Claiming ZIL blocks");
|
||||
/*
|
||||
* Traverse the ZIL and claim all blocks.
|
||||
*/
|
||||
|
@ -5141,6 +5166,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* will have been set for us by ZIL traversal operations
|
||||
* performed above.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Syncing ZIL claims");
|
||||
txg_wait_synced(spa->spa_dsl_pool, spa->spa_claim_max_txg);
|
||||
|
||||
/*
|
||||
|
@ -5148,6 +5174,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* next sync, we would update the config stored in vdev labels
|
||||
* and the cachefile (by default /etc/zfs/zpool.cache).
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Updating configs");
|
||||
spa_ld_check_for_config_update(spa, config_cache_txg,
|
||||
update_config_cache);
|
||||
|
||||
|
@ -5156,6 +5183,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* Then check all DTLs to see if anything needs resilvering.
|
||||
* The resilver will be deferred if a rebuild was started.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa, "Starting resilvers");
|
||||
if (vdev_rebuild_active(spa->spa_root_vdev)) {
|
||||
vdev_rebuild_restart(spa);
|
||||
} else if (!dsl_scan_resilvering(spa->spa_dsl_pool) &&
|
||||
|
@ -5169,6 +5197,8 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
*/
|
||||
spa_history_log_version(spa, "open", NULL);
|
||||
|
||||
spa_import_progress_set_notes(spa,
|
||||
"Restarting device removals");
|
||||
spa_restart_removal(spa);
|
||||
spa_spawn_aux_threads(spa);
|
||||
|
||||
|
@ -5181,19 +5211,26 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
|
|||
* auxiliary threads above (from which the livelist
|
||||
* deletion zthr is part of).
|
||||
*/
|
||||
spa_import_progress_set_notes(spa,
|
||||
"Cleaning up inconsistent objsets");
|
||||
(void) dmu_objset_find(spa_name(spa),
|
||||
dsl_destroy_inconsistent, NULL, DS_FIND_CHILDREN);
|
||||
|
||||
/*
|
||||
* Clean up any stale temporary dataset userrefs.
|
||||
*/
|
||||
spa_import_progress_set_notes(spa,
|
||||
"Cleaning up temporary userrefs");
|
||||
dsl_pool_clean_tmp_userrefs(spa->spa_dsl_pool);
|
||||
|
||||
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
|
||||
spa_import_progress_set_notes(spa, "Restarting initialize");
|
||||
vdev_initialize_restart(spa->spa_root_vdev);
|
||||
spa_import_progress_set_notes(spa, "Restarting TRIM");
|
||||
vdev_trim_restart(spa->spa_root_vdev);
|
||||
vdev_autotrim_restart(spa);
|
||||
spa_config_exit(spa, SCL_CONFIG, FTAG);
|
||||
spa_import_progress_set_notes(spa, "Finished importing");
|
||||
}
|
||||
|
||||
spa_import_progress_remove(spa_guid(spa));
|
||||
|
|
|
@ -1153,6 +1153,7 @@ spa_ld_log_sm_data(spa_t *spa)
|
|||
|
||||
uint_t pn = 0;
|
||||
uint64_t ps = 0;
|
||||
uint64_t nsm = 0;
|
||||
psls = sls = avl_first(&spa->spa_sm_logs_by_txg);
|
||||
while (sls != NULL) {
|
||||
/* Prefetch log spacemaps up to 16 TXGs or MBs ahead. */
|
||||
|
@ -1185,6 +1186,10 @@ spa_ld_log_sm_data(spa_t *spa)
|
|||
summary_add_data(spa, sls->sls_txg,
|
||||
sls->sls_mscount, 0, sls->sls_nblocks);
|
||||
|
||||
spa_import_progress_set_notes_nolog(spa,
|
||||
"Read %llu of %lu log space maps", (u_longlong_t)nsm,
|
||||
avl_numnodes(&spa->spa_sm_logs_by_txg));
|
||||
|
||||
struct spa_ld_log_sm_arg vla = {
|
||||
.slls_spa = spa,
|
||||
.slls_txg = sls->sls_txg
|
||||
|
@ -1200,6 +1205,7 @@ spa_ld_log_sm_data(spa_t *spa)
|
|||
|
||||
pn--;
|
||||
ps -= space_map_length(sls->sls_sm);
|
||||
nsm++;
|
||||
space_map_close(sls->sls_sm);
|
||||
sls->sls_sm = NULL;
|
||||
sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls);
|
||||
|
@ -1210,11 +1216,11 @@ spa_ld_log_sm_data(spa_t *spa)
|
|||
|
||||
hrtime_t read_logs_endtime = gethrtime();
|
||||
spa_load_note(spa,
|
||||
"read %llu log space maps (%llu total blocks - blksz = %llu bytes) "
|
||||
"in %lld ms", (u_longlong_t)avl_numnodes(&spa->spa_sm_logs_by_txg),
|
||||
"Read %lu log space maps (%llu total blocks - blksz = %llu bytes) "
|
||||
"in %lld ms", avl_numnodes(&spa->spa_sm_logs_by_txg),
|
||||
(u_longlong_t)spa_log_sm_nblocks(spa),
|
||||
(u_longlong_t)zfs_log_sm_blksz,
|
||||
(longlong_t)((read_logs_endtime - read_logs_starttime) / 1000000));
|
||||
(longlong_t)NSEC2MSEC(read_logs_endtime - read_logs_starttime));
|
||||
|
||||
out:
|
||||
if (error != 0) {
|
||||
|
|
|
@ -426,6 +426,8 @@ spa_load_note(spa_t *spa, const char *fmt, ...)
|
|||
|
||||
zfs_dbgmsg("spa_load(%s, config %s): %s", spa->spa_name,
|
||||
spa->spa_trust_config ? "trusted" : "untrusted", buf);
|
||||
|
||||
spa_import_progress_set_notes_nolog(spa, "%s", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2184,6 +2186,7 @@ typedef struct spa_import_progress {
|
|||
uint64_t pool_guid; /* unique id for updates */
|
||||
char *pool_name;
|
||||
spa_load_state_t spa_load_state;
|
||||
char *spa_load_notes;
|
||||
uint64_t mmp_sec_remaining; /* MMP activity check */
|
||||
uint64_t spa_load_max_txg; /* rewind txg */
|
||||
procfs_list_node_t smh_node;
|
||||
|
@ -2194,9 +2197,9 @@ spa_history_list_t *spa_import_progress_list = NULL;
|
|||
static int
|
||||
spa_import_progress_show_header(struct seq_file *f)
|
||||
{
|
||||
seq_printf(f, "%-20s %-14s %-14s %-12s %s\n", "pool_guid",
|
||||
seq_printf(f, "%-20s %-14s %-14s %-12s %-16s %s\n", "pool_guid",
|
||||
"load_state", "multihost_secs", "max_txg",
|
||||
"pool_name");
|
||||
"pool_name", "notes");
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -2205,11 +2208,12 @@ spa_import_progress_show(struct seq_file *f, void *data)
|
|||
{
|
||||
spa_import_progress_t *sip = (spa_import_progress_t *)data;
|
||||
|
||||
seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %s\n",
|
||||
seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %-16s %s\n",
|
||||
(u_longlong_t)sip->pool_guid, (u_longlong_t)sip->spa_load_state,
|
||||
(u_longlong_t)sip->mmp_sec_remaining,
|
||||
(u_longlong_t)sip->spa_load_max_txg,
|
||||
(sip->pool_name ? sip->pool_name : "-"));
|
||||
(sip->pool_name ? sip->pool_name : "-"),
|
||||
(sip->spa_load_notes ? sip->spa_load_notes : "-"));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -2223,6 +2227,8 @@ spa_import_progress_truncate(spa_history_list_t *shl, unsigned int size)
|
|||
sip = list_remove_head(&shl->procfs_list.pl_list);
|
||||
if (sip->pool_name)
|
||||
spa_strfree(sip->pool_name);
|
||||
if (sip->spa_load_notes)
|
||||
kmem_strfree(sip->spa_load_notes);
|
||||
kmem_free(sip, sizeof (spa_import_progress_t));
|
||||
shl->size--;
|
||||
}
|
||||
|
@ -2278,6 +2284,10 @@ spa_import_progress_set_state(uint64_t pool_guid,
|
|||
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
|
||||
if (sip->pool_guid == pool_guid) {
|
||||
sip->spa_load_state = load_state;
|
||||
if (sip->spa_load_notes != NULL) {
|
||||
kmem_strfree(sip->spa_load_notes);
|
||||
sip->spa_load_notes = NULL;
|
||||
}
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -2287,6 +2297,59 @@ spa_import_progress_set_state(uint64_t pool_guid,
|
|||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
spa_import_progress_set_notes_impl(spa_t *spa, boolean_t log_dbgmsg,
|
||||
const char *fmt, va_list adx)
|
||||
{
|
||||
spa_history_list_t *shl = spa_import_progress_list;
|
||||
spa_import_progress_t *sip;
|
||||
uint64_t pool_guid = spa_guid(spa);
|
||||
|
||||
if (shl->size == 0)
|
||||
return;
|
||||
|
||||
char *notes = kmem_vasprintf(fmt, adx);
|
||||
|
||||
mutex_enter(&shl->procfs_list.pl_lock);
|
||||
for (sip = list_tail(&shl->procfs_list.pl_list); sip != NULL;
|
||||
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
|
||||
if (sip->pool_guid == pool_guid) {
|
||||
if (sip->spa_load_notes != NULL) {
|
||||
kmem_strfree(sip->spa_load_notes);
|
||||
sip->spa_load_notes = NULL;
|
||||
}
|
||||
sip->spa_load_notes = notes;
|
||||
if (log_dbgmsg)
|
||||
zfs_dbgmsg("'%s' %s", sip->pool_name, notes);
|
||||
notes = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_exit(&shl->procfs_list.pl_lock);
|
||||
if (notes != NULL)
|
||||
kmem_strfree(notes);
|
||||
}
|
||||
|
||||
void
|
||||
spa_import_progress_set_notes(spa_t *spa, const char *fmt, ...)
|
||||
{
|
||||
va_list adx;
|
||||
|
||||
va_start(adx, fmt);
|
||||
spa_import_progress_set_notes_impl(spa, B_TRUE, fmt, adx);
|
||||
va_end(adx);
|
||||
}
|
||||
|
||||
void
|
||||
spa_import_progress_set_notes_nolog(spa_t *spa, const char *fmt, ...)
|
||||
{
|
||||
va_list adx;
|
||||
|
||||
va_start(adx, fmt);
|
||||
spa_import_progress_set_notes_impl(spa, B_FALSE, fmt, adx);
|
||||
va_end(adx);
|
||||
}
|
||||
|
||||
int
|
||||
spa_import_progress_set_max_txg(uint64_t pool_guid, uint64_t load_max_txg)
|
||||
{
|
||||
|
@ -2355,6 +2418,7 @@ spa_import_progress_add(spa_t *spa)
|
|||
poolname = spa_name(spa);
|
||||
sip->pool_name = spa_strdup(poolname);
|
||||
sip->spa_load_state = spa_load_state(spa);
|
||||
sip->spa_load_notes = NULL;
|
||||
|
||||
mutex_enter(&shl->procfs_list.pl_lock);
|
||||
procfs_list_add(&shl->procfs_list, sip);
|
||||
|
@ -2374,6 +2438,8 @@ spa_import_progress_remove(uint64_t pool_guid)
|
|||
if (sip->pool_guid == pool_guid) {
|
||||
if (sip->pool_name)
|
||||
spa_strfree(sip->pool_name);
|
||||
if (sip->spa_load_notes)
|
||||
spa_strfree(sip->spa_load_notes);
|
||||
list_remove(&shl->procfs_list.pl_list, sip);
|
||||
shl->size--;
|
||||
kmem_free(sip, sizeof (spa_import_progress_t));
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <sys/fs/zfs.h>
|
||||
#include <sys/dmu.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dsl_crypt.h>
|
||||
#include <sys/spa.h>
|
||||
#include <sys/txg.h>
|
||||
#include <sys/dbuf.h>
|
||||
|
@ -1097,6 +1098,16 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
|
|||
return (SET_ERROR(EXDEV));
|
||||
}
|
||||
|
||||
/*
|
||||
* Cloning across encrypted datasets is possible only if they
|
||||
* share the same master key.
|
||||
*/
|
||||
if (inos != outos && inos->os_encrypted &&
|
||||
!dmu_objset_crypto_key_equal(inos, outos)) {
|
||||
zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
|
||||
return (SET_ERROR(EXDEV));
|
||||
}
|
||||
|
||||
error = zfs_verify_zp(inzp);
|
||||
if (error == 0)
|
||||
error = zfs_verify_zp(outzp);
|
||||
|
@ -1280,20 +1291,6 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
|
|||
*/
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Encrypted data is fine as long as it comes from the same
|
||||
* dataset.
|
||||
* TODO: We want to extend it in the future to allow cloning to
|
||||
* datasets with the same keys, like clones or to be able to
|
||||
* clone a file from a snapshot of an encrypted dataset into the
|
||||
* dataset itself.
|
||||
*/
|
||||
if (BP_IS_PROTECTED(&bps[0])) {
|
||||
if (inzfsvfs != outzfsvfs) {
|
||||
error = SET_ERROR(EXDEV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a transaction.
|
||||
|
|
|
@ -617,11 +617,12 @@ zil_claim_write(zilog_t *zilog, const lr_t *lrc, void *tx, uint64_t first_txg)
|
|||
}
|
||||
|
||||
static int
|
||||
zil_claim_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx)
|
||||
zil_claim_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx,
|
||||
uint64_t first_txg)
|
||||
{
|
||||
const lr_clone_range_t *lr = (const lr_clone_range_t *)lrc;
|
||||
const blkptr_t *bp;
|
||||
spa_t *spa;
|
||||
spa_t *spa = zilog->zl_spa;
|
||||
uint_t ii;
|
||||
|
||||
ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
|
||||
|
@ -636,19 +637,36 @@ zil_claim_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx)
|
|||
* XXX: Do we need to byteswap lr?
|
||||
*/
|
||||
|
||||
spa = zilog->zl_spa;
|
||||
|
||||
for (ii = 0; ii < lr->lr_nbps; ii++) {
|
||||
bp = &lr->lr_bps[ii];
|
||||
|
||||
/*
|
||||
* When data in embedded into BP there is no need to create
|
||||
* BRT entry as there is no data block. Just copy the BP as
|
||||
* it contains the data.
|
||||
* When data is embedded into the BP there is no need to create
|
||||
* BRT entry as there is no data block. Just copy the BP as it
|
||||
* contains the data.
|
||||
*/
|
||||
if (!BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp)) {
|
||||
brt_pending_add(spa, bp, tx);
|
||||
if (BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We can not handle block pointers from the future, since they
|
||||
* are not yet allocated. It should not normally happen, but
|
||||
* just in case lets be safe and just stop here now instead of
|
||||
* corrupting the pool.
|
||||
*/
|
||||
if (BP_PHYSICAL_BIRTH(bp) >= first_txg)
|
||||
return (SET_ERROR(ENOENT));
|
||||
|
||||
/*
|
||||
* Assert the block is really allocated before we reference it.
|
||||
*/
|
||||
metaslab_check_free(spa, bp);
|
||||
}
|
||||
|
||||
for (ii = 0; ii < lr->lr_nbps; ii++) {
|
||||
bp = &lr->lr_bps[ii];
|
||||
if (!BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp))
|
||||
brt_pending_add(spa, bp, tx);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
@ -663,7 +681,7 @@ zil_claim_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
|
|||
case TX_WRITE:
|
||||
return (zil_claim_write(zilog, lrc, tx, first_txg));
|
||||
case TX_CLONE_RANGE:
|
||||
return (zil_claim_clone_range(zilog, lrc, tx));
|
||||
return (zil_claim_clone_range(zilog, lrc, tx, first_txg));
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
@ -1707,8 +1725,6 @@ static const struct {
|
|||
{ 8192 + 4096, 8192 + 4096 }, /* database */
|
||||
{ 32768 + 4096, 32768 + 4096 }, /* NFS writes */
|
||||
{ 65536 + 4096, 65536 + 4096 }, /* 64KB writes */
|
||||
{ 131072, 131072 }, /* < 128KB writes */
|
||||
{ 131072 +4096, 65536 + 4096 }, /* 128KB writes */
|
||||
{ UINT64_MAX, SPA_OLD_MAXBLOCKSIZE}, /* > 128KB writes */
|
||||
};
|
||||
|
||||
|
|
|
@ -295,6 +295,53 @@ zio_fini(void)
|
|||
* ==========================================================================
|
||||
*/
|
||||
|
||||
#ifdef ZFS_DEBUG
|
||||
static const ulong_t zio_buf_canary = (ulong_t)0xdeadc0dedead210b;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use empty space after the buffer to detect overflows.
|
||||
*
|
||||
* Since zio_init() creates kmem caches only for certain set of buffer sizes,
|
||||
* allocations of different sizes may have some unused space after the data.
|
||||
* Filling part of that space with a known pattern on allocation and checking
|
||||
* it on free should allow us to detect some buffer overflows.
|
||||
*/
|
||||
static void
|
||||
zio_buf_put_canary(ulong_t *p, size_t size, kmem_cache_t **cache, size_t c)
|
||||
{
|
||||
#ifdef ZFS_DEBUG
|
||||
size_t off = P2ROUNDUP(size, sizeof (ulong_t));
|
||||
ulong_t *canary = p + off / sizeof (ulong_t);
|
||||
size_t asize = (c + 1) << SPA_MINBLOCKSHIFT;
|
||||
if (c + 1 < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT &&
|
||||
cache[c] == cache[c + 1])
|
||||
asize = (c + 2) << SPA_MINBLOCKSHIFT;
|
||||
for (; off < asize; canary++, off += sizeof (ulong_t))
|
||||
*canary = zio_buf_canary;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
zio_buf_check_canary(ulong_t *p, size_t size, kmem_cache_t **cache, size_t c)
|
||||
{
|
||||
#ifdef ZFS_DEBUG
|
||||
size_t off = P2ROUNDUP(size, sizeof (ulong_t));
|
||||
ulong_t *canary = p + off / sizeof (ulong_t);
|
||||
size_t asize = (c + 1) << SPA_MINBLOCKSHIFT;
|
||||
if (c + 1 < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT &&
|
||||
cache[c] == cache[c + 1])
|
||||
asize = (c + 2) << SPA_MINBLOCKSHIFT;
|
||||
for (; off < asize; canary++, off += sizeof (ulong_t)) {
|
||||
if (unlikely(*canary != zio_buf_canary)) {
|
||||
PANIC("ZIO buffer overflow %p (%zu) + %zu %#lx != %#lx",
|
||||
p, size, (canary - p) * sizeof (ulong_t),
|
||||
*canary, zio_buf_canary);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Use zio_buf_alloc to allocate ZFS metadata. This data will appear in a
|
||||
* crashdump if the kernel panics, so use it judiciously. Obviously, it's
|
||||
|
@ -311,7 +358,9 @@ zio_buf_alloc(size_t size)
|
|||
atomic_add_64(&zio_buf_cache_allocs[c], 1);
|
||||
#endif
|
||||
|
||||
return (kmem_cache_alloc(zio_buf_cache[c], KM_PUSHPAGE));
|
||||
void *p = kmem_cache_alloc(zio_buf_cache[c], KM_PUSHPAGE);
|
||||
zio_buf_put_canary(p, size, zio_buf_cache, c);
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -327,7 +376,9 @@ zio_data_buf_alloc(size_t size)
|
|||
|
||||
VERIFY3U(c, <, SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
|
||||
|
||||
return (kmem_cache_alloc(zio_data_buf_cache[c], KM_PUSHPAGE));
|
||||
void *p = kmem_cache_alloc(zio_data_buf_cache[c], KM_PUSHPAGE);
|
||||
zio_buf_put_canary(p, size, zio_data_buf_cache, c);
|
||||
return (p);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -340,6 +391,7 @@ zio_buf_free(void *buf, size_t size)
|
|||
atomic_add_64(&zio_buf_cache_frees[c], 1);
|
||||
#endif
|
||||
|
||||
zio_buf_check_canary(buf, size, zio_buf_cache, c);
|
||||
kmem_cache_free(zio_buf_cache[c], buf);
|
||||
}
|
||||
|
||||
|
@ -350,6 +402,7 @@ zio_data_buf_free(void *buf, size_t size)
|
|||
|
||||
VERIFY3U(c, <, SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
|
||||
|
||||
zio_buf_check_canary(buf, size, zio_data_buf_cache, c);
|
||||
kmem_cache_free(zio_data_buf_cache[c], buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -515,64 +515,6 @@ zvol_replay_write(void *arg1, void *arg2, boolean_t byteswap)
|
|||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Replay a TX_CLONE_RANGE ZIL transaction that didn't get committed
|
||||
* after a system failure.
|
||||
*
|
||||
* TODO: For now we drop block cloning transations for ZVOLs as they are
|
||||
* unsupported, but we still need to inform BRT about that as we
|
||||
* claimed them during pool import.
|
||||
* This situation can occur when we try to import a pool from a ZFS
|
||||
* version supporting block cloning for ZVOLs into a system that
|
||||
* has this ZFS version, that doesn't support block cloning for ZVOLs.
|
||||
*/
|
||||
static int
|
||||
zvol_replay_clone_range(void *arg1, void *arg2, boolean_t byteswap)
|
||||
{
|
||||
char name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
zvol_state_t *zv = arg1;
|
||||
objset_t *os = zv->zv_objset;
|
||||
lr_clone_range_t *lr = arg2;
|
||||
blkptr_t *bp;
|
||||
dmu_tx_t *tx;
|
||||
spa_t *spa;
|
||||
uint_t ii;
|
||||
int error;
|
||||
|
||||
ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
|
||||
ASSERT3U(lr->lr_common.lrc_reclen, >=, offsetof(lr_clone_range_t,
|
||||
lr_bps[lr->lr_nbps]));
|
||||
|
||||
dmu_objset_name(os, name);
|
||||
cmn_err(CE_WARN, "ZFS dropping block cloning transaction for %s.",
|
||||
name);
|
||||
|
||||
if (byteswap)
|
||||
byteswap_uint64_array(lr, sizeof (*lr));
|
||||
|
||||
tx = dmu_tx_create(os);
|
||||
error = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (error) {
|
||||
dmu_tx_abort(tx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
spa = os->os_spa;
|
||||
|
||||
for (ii = 0; ii < lr->lr_nbps; ii++) {
|
||||
bp = &lr->lr_bps[ii];
|
||||
|
||||
if (!BP_IS_HOLE(bp)) {
|
||||
zio_free(spa, dmu_tx_get_txg(tx), bp);
|
||||
}
|
||||
}
|
||||
|
||||
(void) zil_replaying(zv->zv_zilog, tx);
|
||||
dmu_tx_commit(tx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zvol_replay_err(void *arg1, void *arg2, boolean_t byteswap)
|
||||
{
|
||||
|
@ -607,7 +549,7 @@ zil_replay_func_t *const zvol_replay_vector[TX_MAX_TYPE] = {
|
|||
zvol_replay_err, /* TX_SETSAXATTR */
|
||||
zvol_replay_err, /* TX_RENAME_EXCHANGE */
|
||||
zvol_replay_err, /* TX_RENAME_WHITEOUT */
|
||||
zvol_replay_clone_range /* TX_CLONE_RANGE */
|
||||
zvol_replay_err, /* TX_CLONE_RANGE */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -425,7 +425,8 @@ tests = ['zpool_import_001_pos', 'zpool_import_002_pos',
|
|||
'import_devices_missing', 'import_log_missing',
|
||||
'import_paths_changed',
|
||||
'import_rewind_config_changed',
|
||||
'import_rewind_device_replaced']
|
||||
'import_rewind_device_replaced',
|
||||
'zpool_import_status']
|
||||
tags = ['functional', 'cli_root', 'zpool_import']
|
||||
timeout = 1200
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ tests = ['block_cloning_copyfilerange', 'block_cloning_copyfilerange_partial',
|
|||
'block_cloning_disabled_copyfilerange', 'block_cloning_disabled_ficlone',
|
||||
'block_cloning_disabled_ficlonerange',
|
||||
'block_cloning_copyfilerange_cross_dataset',
|
||||
'block_cloning_cross_enc_dataset',
|
||||
'block_cloning_copyfilerange_fallback_same_txg']
|
||||
tags = ['functional', 'block_cloning']
|
||||
|
||||
|
|
|
@ -305,6 +305,8 @@ elif sys.platform.startswith('linux'):
|
|||
['SKIP', cfr_cross_reason],
|
||||
'block_cloning/block_cloning_copyfilerange_fallback_same_txg':
|
||||
['SKIP', cfr_cross_reason],
|
||||
'block_cloning/block_cloning_cross_enc_dataset':
|
||||
['SKIP', cfr_cross_reason],
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -451,6 +451,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
|||
functional/block_cloning/block_cloning_ficlone.ksh \
|
||||
functional/block_cloning/block_cloning_ficlonerange.ksh \
|
||||
functional/block_cloning/block_cloning_ficlonerange_partial.ksh \
|
||||
functional/block_cloning/block_cloning_cross_enc_dataset.ksh \
|
||||
functional/bootfs/bootfs_001_pos.ksh \
|
||||
functional/bootfs/bootfs_002_neg.ksh \
|
||||
functional/bootfs/bootfs_003_pos.ksh \
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
function have_same_content
|
||||
{
|
||||
typeset hash1=$(cat $1 | md5sum)
|
||||
typeset hash2=$(cat $2 | md5sum)
|
||||
typeset hash1=$(md5digest $1)
|
||||
typeset hash2=$(md5digest $2)
|
||||
|
||||
log_must [ "$hash1" = "$hash2" ]
|
||||
}
|
||||
|
@ -44,10 +44,14 @@ function have_same_content
|
|||
#
|
||||
function get_same_blocks
|
||||
{
|
||||
KEY=$5
|
||||
if [ ${#KEY} -gt 0 ]; then
|
||||
KEY="--key=$KEY"
|
||||
fi
|
||||
typeset zdbout=${TMPDIR:-$TEST_BASE_DIR}/zdbout.$$
|
||||
zdb -vvvvv $1 -O $2 | \
|
||||
zdb $KEY -vvvvv $1 -O $2 | \
|
||||
awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.a
|
||||
zdb -vvvvv $3 -O $4 | \
|
||||
zdb $KEY -vvvvv $3 -O $4 | \
|
||||
awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.b
|
||||
echo $(sort $zdbout.a $zdbout.b | uniq -d | cut -f1 -d' ')
|
||||
}
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023, Kay Pedersen <mail@mkwg.de>
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
|
||||
log_unsupported "copy_file_range can't copy cross-filesystem before Linux 5.3"
|
||||
fi
|
||||
|
||||
claim="Block cloning across encrypted datasets."
|
||||
|
||||
log_assert $claim
|
||||
|
||||
DS1="$TESTPOOL/encrypted1"
|
||||
DS2="$TESTPOOL/encrypted2"
|
||||
DS1_NC="$TESTPOOL/notcrypted1"
|
||||
PASSPHRASE="top_secret"
|
||||
|
||||
function prepare_enc
|
||||
{
|
||||
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
|
||||
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
|
||||
"-o keyformat=passphrase -o keylocation=prompt $DS1"
|
||||
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
|
||||
"-o keyformat=passphrase -o keylocation=prompt $DS2"
|
||||
log_must zfs create $DS1/child1
|
||||
log_must zfs create $DS1/child2
|
||||
log_must zfs create $DS1_NC
|
||||
|
||||
log_note "Create test file"
|
||||
# we must wait until the src file txg is written to the disk otherwise we
|
||||
# will fallback to normal copy. See "dmu_read_l0_bps" in
|
||||
# "zfs/module/zfs/dmu.c" and "zfs_clone_range" in
|
||||
# "zfs/module/zfs/zfs_vnops.c"
|
||||
log_must dd if=/dev/urandom of=/$DS1/file bs=128K count=4
|
||||
log_must dd if=/dev/urandom of=/$DS1/child1/file bs=128K count=4
|
||||
log_must dd if=/dev/urandom of=/$DS1_NC/file bs=128K count=4
|
||||
log_must sync_pool $TESTPOOL
|
||||
}
|
||||
|
||||
function cleanup_enc
|
||||
{
|
||||
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||
}
|
||||
|
||||
function clone_and_check
|
||||
{
|
||||
I_FILE="$1"
|
||||
O_FILE=$2
|
||||
I_DS=$3
|
||||
O_DS=$4
|
||||
SAME_BLOCKS=$5
|
||||
# the CLONE option provides a choice between copy_file_range
|
||||
# which should clone and a dd which is a copy no matter what
|
||||
CLONE=$6
|
||||
SNAPSHOT=$7
|
||||
if [ ${#SNAPSHOT} -gt 0 ]; then
|
||||
I_FILE=".zfs/snapshot/$SNAPSHOT/$1"
|
||||
fi
|
||||
if [ $CLONE ]; then
|
||||
log_must clonefile -f "/$I_DS/$I_FILE" "/$O_DS/$O_FILE" 0 0 524288
|
||||
else
|
||||
log_must dd if="/$I_DS/$I_FILE" of="/$O_DS/$O_FILE" bs=128K
|
||||
fi
|
||||
log_must sync_pool $TESTPOOL
|
||||
|
||||
log_must have_same_content "/$I_DS/$I_FILE" "/$O_DS/$O_FILE"
|
||||
|
||||
if [ ${#SNAPSHOT} -gt 0 ]; then
|
||||
I_DS="$I_DS@$SNAPSHOT"
|
||||
I_FILE="$1"
|
||||
fi
|
||||
typeset blocks=$(get_same_blocks \
|
||||
$I_DS $I_FILE $O_DS $O_FILE $PASSPHRASE)
|
||||
log_must [ "$blocks" = "$SAME_BLOCKS" ]
|
||||
}
|
||||
|
||||
log_onexit cleanup_enc
|
||||
|
||||
prepare_enc
|
||||
|
||||
log_note "Cloning entire file with copy_file_range across different enc" \
|
||||
"roots, should fallback"
|
||||
# we are expecting no same block map.
|
||||
clone_and_check "file" "clone" $DS1 $DS2 "" true
|
||||
log_note "check if the file is still readable and the same after" \
|
||||
"unmount and key unload, shouldn't fail"
|
||||
typeset hash1=$(md5digest "/$DS1/file")
|
||||
log_must zfs umount $DS1 && zfs unload-key $DS1
|
||||
typeset hash2=$(md5digest "/$DS2/clone")
|
||||
log_must [ "$hash1" = "$hash2" ]
|
||||
|
||||
cleanup_enc
|
||||
prepare_enc
|
||||
|
||||
log_note "Cloning entire file with copy_file_range across different child datasets"
|
||||
# clone shouldn't work because of deriving a new master key for the child
|
||||
# we are expecting no same block map.
|
||||
clone_and_check "file" "clone" $DS1 "$DS1/child1" "" true
|
||||
clone_and_check "file" "clone" "$DS1/child1" "$DS1/child2" "" true
|
||||
|
||||
cleanup_enc
|
||||
prepare_enc
|
||||
|
||||
log_note "Copying entire file with copy_file_range across same snapshot"
|
||||
log_must zfs snapshot -r $DS1@s1
|
||||
log_must sync_pool $TESTPOOL
|
||||
log_must rm -f "/$DS1/file"
|
||||
log_must sync_pool $TESTPOOL
|
||||
clone_and_check "file" "clone" "$DS1" "$DS1" "0 1 2 3" true "s1"
|
||||
|
||||
cleanup_enc
|
||||
prepare_enc
|
||||
|
||||
log_note "Copying entire file with copy_file_range across different snapshot"
|
||||
clone_and_check "file" "file" $DS1 $DS2 "" true
|
||||
log_must zfs snapshot -r $DS2@s1
|
||||
log_must sync_pool $TESTPOOL
|
||||
log_must rm -f "/$DS1/file" "/$DS2/file"
|
||||
log_must sync_pool $TESTPOOL
|
||||
clone_and_check "file" "clone" "$DS2" "$DS1" "" true "s1"
|
||||
typeset hash1=$(md5digest "/$DS1/.zfs/snapshot/s1/file")
|
||||
log_note "destroy the snapshot and check if the file is still readable and" \
|
||||
"has the same content"
|
||||
log_must zfs destroy -r $DS2@s1
|
||||
log_must sync_pool $TESTPOOL
|
||||
typeset hash2=$(md5digest "/$DS1/file")
|
||||
log_must [ "$hash1" = "$hash2" ]
|
||||
|
||||
cleanup_enc
|
||||
prepare_enc
|
||||
|
||||
log_note "Copying with copy_file_range from non encrypted to encrypted"
|
||||
clone_and_check "file" "copy" $DS1_NC $DS1 "" true
|
||||
|
||||
cleanup_enc
|
||||
prepare_enc
|
||||
|
||||
log_note "Copying with copy_file_range from encrypted to non encrypted"
|
||||
clone_and_check "file" "copy" $DS1 $DS1_NC "" true
|
||||
|
||||
log_must sync_pool $TESTPOOL
|
||||
|
||||
log_pass $claim
|
|
@ -0,0 +1,132 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 Klara, Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# During a pool import, the 'import_progress' kstat contains details
|
||||
# on the import progress.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create test pool with several devices
|
||||
# 2. Generate some ZIL records and spacemap logs
|
||||
# 3. Export the pool
|
||||
# 4. Import the pool in the background and monitor the kstat content
|
||||
# 5. Check the zfs debug messages for import progress
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 0
|
||||
log_must set_tunable64 METASLAB_DEBUG_LOAD 0
|
||||
|
||||
destroy_pool $TESTPOOL1
|
||||
}
|
||||
|
||||
log_assert "During a pool import, the 'import_progress' kstat contains " \
|
||||
"notes on the progress"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2
|
||||
typeset guid=$(zpool get -H -o value guid $TESTPOOL1)
|
||||
|
||||
log_must zfs create -o recordsize=8k $TESTPOOL1/fs
|
||||
#
|
||||
# This dd command works around an issue where ZIL records aren't created
|
||||
# after freezing the pool unless a ZIL header already exists. Create a file
|
||||
# synchronously to force ZFS to write one out.
|
||||
#
|
||||
log_must dd if=/dev/zero of=/$TESTPOOL1/fs/sync conv=fsync bs=1 count=1
|
||||
|
||||
#
|
||||
# Overwrite some blocks to populate spacemap logs
|
||||
#
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL1/fs/00 bs=1M count=200
|
||||
sync_all_pools
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL1/fs/00 bs=1M count=200
|
||||
sync_all_pools
|
||||
|
||||
#
|
||||
# Freeze the pool to retain intent log records
|
||||
#
|
||||
log_must zpool freeze $TESTPOOL1
|
||||
|
||||
# fill_fs [destdir] [dirnum] [filenum] [bytes] [num_writes] [data]
|
||||
log_must fill_fs /$TESTPOOL1/fs 1 2000 100 1024 R
|
||||
|
||||
log_must zpool list -v $TESTPOOL1
|
||||
|
||||
#
|
||||
# Unmount filesystem and export the pool
|
||||
#
|
||||
# At this stage the zfs intent log contains
|
||||
# a set of records to replay.
|
||||
#
|
||||
log_must zfs unmount /$TESTPOOL1/fs
|
||||
|
||||
log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 1
|
||||
log_must zpool export $TESTPOOL1
|
||||
|
||||
log_must set_tunable64 METASLAB_DEBUG_LOAD 1
|
||||
log_note "Starting zpool import in background at" $(date +'%H:%M:%S')
|
||||
zpool import -d $DEVICE_DIR -f $guid &
|
||||
pid=$!
|
||||
|
||||
#
|
||||
# capture progress until import is finished
|
||||
#
|
||||
log_note waiting for pid $pid to exit
|
||||
kstat import_progress
|
||||
while [[ -d /proc/"$pid" ]]; do
|
||||
line=$(kstat import_progress | grep -v pool_guid)
|
||||
if [[ -n $line ]]; then
|
||||
echo $line
|
||||
fi
|
||||
if [[ -f /$TESTPOOL1/fs/00 ]]; then
|
||||
break;
|
||||
fi
|
||||
sleep 0.0001
|
||||
done
|
||||
log_note "zpool import completed at" $(date +'%H:%M:%S')
|
||||
|
||||
entries=$(kstat dbgmsg | grep "spa_import_progress_set_notes_impl(): 'testpool1'" | wc -l)
|
||||
log_note "found $entries progress notes in dbgmsg"
|
||||
log_must test $entries -gt 20
|
||||
|
||||
log_must zpool status $TESTPOOL1
|
||||
|
||||
log_pass "During a pool import, the 'import_progress' kstat contains " \
|
||||
"notes on the progress"
|
|
@ -316,6 +316,9 @@
|
|||
/* sops->evict_inode() exists */
|
||||
/* #undef HAVE_EVICT_INODE */
|
||||
|
||||
/* Define to 1 if you have the `execvpe' function. */
|
||||
/* #undef HAVE_EXECVPE */
|
||||
|
||||
/* FALLOC_FL_ZERO_RANGE is defined */
|
||||
/* #undef HAVE_FALLOC_FL_ZERO_RANGE */
|
||||
|
||||
|
@ -1110,7 +1113,7 @@
|
|||
/* #undef ZFS_IS_GPL_COMPATIBLE */
|
||||
|
||||
/* Define the project alias string. */
|
||||
#define ZFS_META_ALIAS "zfs-2.2.99-239-FreeBSD_ga03ebd9be"
|
||||
#define ZFS_META_ALIAS "zfs-2.2.99-257-FreeBSD_g450f2d0b0"
|
||||
|
||||
/* Define the project author. */
|
||||
#define ZFS_META_AUTHOR "OpenZFS"
|
||||
|
@ -1140,7 +1143,7 @@
|
|||
#define ZFS_META_NAME "zfs"
|
||||
|
||||
/* Define the project release. */
|
||||
#define ZFS_META_RELEASE "239-FreeBSD_ga03ebd9be"
|
||||
#define ZFS_META_RELEASE "257-FreeBSD_g450f2d0b0"
|
||||
|
||||
/* Define the project version. */
|
||||
#define ZFS_META_VERSION "2.2.99"
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define ZFS_META_GITREV "zfs-2.2.99-239-ga03ebd9be"
|
||||
#define ZFS_META_GITREV "zfs-2.2.99-257-g450f2d0b0"
|
||||
|
|
Loading…
Reference in a new issue