Merge 4e2f8ba14a
into 1713aa7b4d
This commit is contained in:
commit
f5025cb1a8
|
@ -158,6 +158,8 @@ extern "C" {
|
||||||
#define ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
|
#define ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
|
||||||
|
|
||||||
extern int zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len);
|
extern int zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len);
|
||||||
|
extern int zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl,
|
||||||
|
sa_attr_type_t *sa_table, uint64_t *pobjp, int *is_xattrdir);
|
||||||
extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
|
extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
|
|
|
@ -12,9 +12,13 @@ CPPCHECKTARGETS += libzpool.la
|
||||||
|
|
||||||
dist_libzpool_la_SOURCES = \
|
dist_libzpool_la_SOURCES = \
|
||||||
%D%/abd_os.c \
|
%D%/abd_os.c \
|
||||||
|
%D%/arc_os.c \
|
||||||
%D%/kernel.c \
|
%D%/kernel.c \
|
||||||
%D%/taskq.c \
|
%D%/taskq.c \
|
||||||
%D%/util.c
|
%D%/util.c \
|
||||||
|
%D%/vdev_label_os.c \
|
||||||
|
%D%/zfs_racct.c \
|
||||||
|
%D%/zfs_debug.c
|
||||||
|
|
||||||
nodist_libzpool_la_SOURCES = \
|
nodist_libzpool_la_SOURCES = \
|
||||||
module/lua/lapi.c \
|
module/lua/lapi.c \
|
||||||
|
@ -42,13 +46,7 @@ nodist_libzpool_la_SOURCES = \
|
||||||
module/lua/lvm.c \
|
module/lua/lvm.c \
|
||||||
module/lua/lzio.c \
|
module/lua/lzio.c \
|
||||||
\
|
\
|
||||||
module/os/linux/zfs/arc_os.c \
|
|
||||||
module/os/linux/zfs/trace.c \
|
|
||||||
module/os/linux/zfs/vdev_file.c \
|
module/os/linux/zfs/vdev_file.c \
|
||||||
module/os/linux/zfs/vdev_label_os.c \
|
|
||||||
module/os/linux/zfs/zfs_debug.c \
|
|
||||||
module/os/linux/zfs/zfs_racct.c \
|
|
||||||
module/os/linux/zfs/zfs_znode.c \
|
|
||||||
module/os/linux/zfs/zio_crypt.c \
|
module/os/linux/zfs/zio_crypt.c \
|
||||||
\
|
\
|
||||||
module/zcommon/cityhash.c \
|
module/zcommon/cityhash.c \
|
||||||
|
@ -183,6 +181,7 @@ nodist_libzpool_la_SOURCES = \
|
||||||
module/zfs/zfs_ratelimit.c \
|
module/zfs/zfs_ratelimit.c \
|
||||||
module/zfs/zfs_rlock.c \
|
module/zfs/zfs_rlock.c \
|
||||||
module/zfs/zfs_sa.c \
|
module/zfs/zfs_sa.c \
|
||||||
|
module/zfs/zfs_znode.c \
|
||||||
module/zfs/zil.c \
|
module/zfs/zil.c \
|
||||||
module/zfs/zio.c \
|
module/zfs/zio.c \
|
||||||
module/zfs/zio_checksum.c \
|
module/zfs/zio_checksum.c \
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2018, Joyent, Inc.
|
||||||
|
* Copyright (c) 2011, 2019 by Delphix. All rights reserved.
|
||||||
|
* Copyright (c) 2014 by Saso Kiselkov. All rights reserved.
|
||||||
|
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/zfs_context.h>
|
||||||
|
#include <sys/arc_impl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a default max arc size based on the amount of physical memory.
|
||||||
|
* This may be overridden by tuning the zfs_arc_max module parameter.
|
||||||
|
*/
|
||||||
|
uint64_t
|
||||||
|
arc_default_max(uint64_t min, uint64_t allmem)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
|
||||||
|
if (allmem >= 1 << 30)
|
||||||
|
size = allmem - (1 << 30);
|
||||||
|
else
|
||||||
|
size = min;
|
||||||
|
return (MAX(allmem * 5 / 8, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
arc_available_memory(void)
|
||||||
|
{
|
||||||
|
int64_t lowest = INT64_MAX;
|
||||||
|
|
||||||
|
/* Every 100 calls, free a small amount */
|
||||||
|
if (random_in_range(100) == 0)
|
||||||
|
lowest = -1024;
|
||||||
|
|
||||||
|
return (lowest);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg)
|
||||||
|
{
|
||||||
|
(void) spa, (void) reserve, (void) txg;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
arc_all_memory(void)
|
||||||
|
{
|
||||||
|
return (ptob(physmem) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
arc_free_memory(void)
|
||||||
|
{
|
||||||
|
return (random_in_range(arc_all_memory() * 20 / 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
arc_register_hotplug(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
arc_unregister_hotplug(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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 by iXsystems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/zfs_context.h>
|
||||||
|
#include <sys/spa.h>
|
||||||
|
#include <sys/spa_impl.h>
|
||||||
|
#include <sys/vdev.h>
|
||||||
|
#include <sys/vdev_impl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the reserved boot area is in-use. This is called from
|
||||||
|
* spa_vdev_attach() when adding a device to a raidz vdev, to ensure that the
|
||||||
|
* reserved area is available as scratch space for raidz expansion.
|
||||||
|
*
|
||||||
|
* This function currently always returns 0. On Linux, there are no known
|
||||||
|
* external uses of the reserved area. On FreeBSD, the reserved boot area is
|
||||||
|
* used when booting to a ZFS root from an MBR partition.
|
||||||
|
*
|
||||||
|
* Currently nothing using libzpool can add a disk to a pool, so this does
|
||||||
|
* nothing.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vdev_check_boot_reserve(spa_t *spa, vdev_t *childvd)
|
||||||
|
{
|
||||||
|
(void) spa;
|
||||||
|
(void) childvd;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
|
* Copyright (c) 2024, Rob Norris <robn@despairlabs.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/zfs_context.h>
|
||||||
|
|
||||||
|
typedef struct zfs_dbgmsg {
|
||||||
|
list_node_t zdm_node;
|
||||||
|
uint64_t zdm_timestamp;
|
||||||
|
uint_t zdm_size;
|
||||||
|
char zdm_msg[]; /* variable length allocation */
|
||||||
|
} zfs_dbgmsg_t;
|
||||||
|
|
||||||
|
static list_t zfs_dbgmsgs;
|
||||||
|
static kmutex_t zfs_dbgmsgs_lock;
|
||||||
|
|
||||||
|
int zfs_dbgmsg_enable = B_TRUE;
|
||||||
|
|
||||||
|
void
|
||||||
|
zfs_dbgmsg_init(void)
|
||||||
|
{
|
||||||
|
list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t),
|
||||||
|
offsetof(zfs_dbgmsg_t, zdm_node));
|
||||||
|
mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zfs_dbgmsg_fini(void)
|
||||||
|
{
|
||||||
|
zfs_dbgmsg_t *zdm;
|
||||||
|
while ((zdm = list_remove_head(&zfs_dbgmsgs)))
|
||||||
|
umem_free(zdm, zdm->zdm_size);
|
||||||
|
mutex_destroy(&zfs_dbgmsgs_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__set_error(const char *file, const char *func, int line, int err)
|
||||||
|
{
|
||||||
|
if (zfs_flags & ZFS_DEBUG_SET_ERROR)
|
||||||
|
__dprintf(B_FALSE, file, func, line, "error %lu",
|
||||||
|
(ulong_t)err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__zfs_dbgmsg(char *buf)
|
||||||
|
{
|
||||||
|
uint_t size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
|
||||||
|
zfs_dbgmsg_t *zdm = umem_zalloc(size, KM_SLEEP);
|
||||||
|
zdm->zdm_size = size;
|
||||||
|
zdm->zdm_timestamp = gethrestime_sec();
|
||||||
|
strcpy(zdm->zdm_msg, buf);
|
||||||
|
|
||||||
|
mutex_enter(&zfs_dbgmsgs_lock);
|
||||||
|
list_insert_tail(&zfs_dbgmsgs, zdm);
|
||||||
|
mutex_exit(&zfs_dbgmsgs_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zfs_dbgmsg_print(int fd, const char *tag)
|
||||||
|
{
|
||||||
|
ssize_t ret __attribute__((unused));
|
||||||
|
|
||||||
|
mutex_enter(&zfs_dbgmsgs_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use write() in this function instead of printf()
|
||||||
|
* so it is safe to call from a signal handler.
|
||||||
|
*/
|
||||||
|
ret = write(fd, "ZFS_DBGMSG(", 11);
|
||||||
|
ret = write(fd, tag, strlen(tag));
|
||||||
|
ret = write(fd, ") START:\n", 9);
|
||||||
|
|
||||||
|
for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs); zdm != NULL;
|
||||||
|
zdm = list_next(&zfs_dbgmsgs, zdm)) {
|
||||||
|
ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg));
|
||||||
|
ret = write(fd, "\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = write(fd, "ZFS_DBGMSG(", 11);
|
||||||
|
ret = write(fd, tag, strlen(tag));
|
||||||
|
ret = write(fd, ") END\n", 6);
|
||||||
|
|
||||||
|
mutex_exit(&zfs_dbgmsgs_lock);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 iXsystems, Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/zfs_racct.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
zfs_racct_read(uint64_t size, uint64_t iops)
|
||||||
|
{
|
||||||
|
(void) size, (void) iops;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zfs_racct_write(uint64_t size, uint64_t iops)
|
||||||
|
{
|
||||||
|
(void) size, (void) iops;
|
||||||
|
}
|
|
@ -423,6 +423,7 @@ ZFS_OBJS := \
|
||||||
zfs_rlock.o \
|
zfs_rlock.o \
|
||||||
zfs_sa.o \
|
zfs_sa.o \
|
||||||
zfs_vnops.o \
|
zfs_vnops.o \
|
||||||
|
zfs_znode.o \
|
||||||
zil.o \
|
zil.o \
|
||||||
zio.o \
|
zio.o \
|
||||||
zio_checksum.o \
|
zio_checksum.o \
|
||||||
|
@ -457,7 +458,7 @@ ZFS_OBJS_OS := \
|
||||||
zfs_uio.o \
|
zfs_uio.o \
|
||||||
zfs_vfsops.o \
|
zfs_vfsops.o \
|
||||||
zfs_vnops_os.o \
|
zfs_vnops_os.o \
|
||||||
zfs_znode.o \
|
zfs_znode_os.o \
|
||||||
zio_crypt.o \
|
zio_crypt.o \
|
||||||
zpl_ctldir.o \
|
zpl_ctldir.o \
|
||||||
zpl_export.o \
|
zpl_export.o \
|
||||||
|
|
|
@ -212,7 +212,7 @@ SRCS+= abd_os.c \
|
||||||
zfs_racct.c \
|
zfs_racct.c \
|
||||||
zfs_vfsops.c \
|
zfs_vfsops.c \
|
||||||
zfs_vnops_os.c \
|
zfs_vnops_os.c \
|
||||||
zfs_znode.c \
|
zfs_znode_os.c \
|
||||||
zio_crypt.c \
|
zio_crypt.c \
|
||||||
zvol_os.c
|
zvol_os.c
|
||||||
|
|
||||||
|
@ -357,6 +357,7 @@ SRCS+= abd.c \
|
||||||
zfs_rlock.c \
|
zfs_rlock.c \
|
||||||
zfs_sa.c \
|
zfs_sa.c \
|
||||||
zfs_vnops.c \
|
zfs_vnops.c \
|
||||||
|
zfs_znode.c \
|
||||||
zil.c \
|
zil.c \
|
||||||
zio.c \
|
zio.c \
|
||||||
zio_checksum.c \
|
zio_checksum.c \
|
||||||
|
|
|
@ -140,15 +140,11 @@ zfs_dbgmsg_fini(void)
|
||||||
{
|
{
|
||||||
if (zfs_dbgmsg_kstat)
|
if (zfs_dbgmsg_kstat)
|
||||||
kstat_delete(zfs_dbgmsg_kstat);
|
kstat_delete(zfs_dbgmsg_kstat);
|
||||||
/*
|
|
||||||
* TODO - decide how to make this permanent
|
|
||||||
*/
|
|
||||||
#ifdef _KERNEL
|
|
||||||
mutex_enter(&zfs_dbgmsgs_lock);
|
mutex_enter(&zfs_dbgmsgs_lock);
|
||||||
zfs_dbgmsg_purge(0);
|
zfs_dbgmsg_purge(0);
|
||||||
mutex_exit(&zfs_dbgmsgs_lock);
|
mutex_exit(&zfs_dbgmsgs_lock);
|
||||||
mutex_destroy(&zfs_dbgmsgs_lock);
|
mutex_destroy(&zfs_dbgmsgs_lock);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -184,7 +180,6 @@ __set_error(const char *file, const char *func, int line, int err)
|
||||||
__dprintf(B_FALSE, file, func, line, "error %lu", (ulong_t)err);
|
__dprintf(B_FALSE, file, func, line, "error %lu", (ulong_t)err);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
void
|
void
|
||||||
__dprintf(boolean_t dprint, const char *file, const char *func,
|
__dprintf(boolean_t dprint, const char *file, const char *func,
|
||||||
int line, const char *fmt, ...)
|
int line, const char *fmt, ...)
|
||||||
|
@ -229,37 +224,6 @@ __dprintf(boolean_t dprint, const char *file, const char *func,
|
||||||
kmem_free(buf, size);
|
kmem_free(buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void
|
|
||||||
zfs_dbgmsg_print(int fd, const char *tag)
|
|
||||||
{
|
|
||||||
ssize_t ret __attribute__((unused));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We use write() in this function instead of printf()
|
|
||||||
* so it is safe to call from a signal handler.
|
|
||||||
*/
|
|
||||||
ret = write(fd, "ZFS_DBGMSG(", 11);
|
|
||||||
ret = write(fd, tag, strlen(tag));
|
|
||||||
ret = write(fd, ") START:\n", 9);
|
|
||||||
|
|
||||||
mutex_enter(&zfs_dbgmsgs_lock);
|
|
||||||
|
|
||||||
for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs); zdm != NULL;
|
|
||||||
zdm = list_next(&zfs_dbgmsgs, zdm))
|
|
||||||
ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg));
|
|
||||||
ret = write(fd, "\n", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = write(fd, "ZFS_DBGMSG(", 11);
|
|
||||||
ret = write(fd, tag, strlen(tag));
|
|
||||||
ret = write(fd, ") END\n", 6);
|
|
||||||
|
|
||||||
mutex_exit(&zfs_dbgmsgs_lock);
|
|
||||||
}
|
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_enable, INT, ZMOD_RW,
|
ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_enable, INT, ZMOD_RW,
|
||||||
"Enable ZFS debug message log");
|
"Enable ZFS debug message log");
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
/* Portions Copyright 2007 Jeremy Teo */
|
/* Portions Copyright 2007 Jeremy Teo */
|
||||||
/* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
|
/* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
@ -52,8 +51,6 @@
|
||||||
#include <sys/zfs_fuid.h>
|
#include <sys/zfs_fuid.h>
|
||||||
#include <sys/dnode.h>
|
#include <sys/dnode.h>
|
||||||
#include <sys/fs/zfs.h>
|
#include <sys/fs/zfs.h>
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
#include <sys/dmu.h>
|
#include <sys/dmu.h>
|
||||||
#include <sys/dmu_objset.h>
|
#include <sys/dmu_objset.h>
|
||||||
#include <sys/dmu_tx.h>
|
#include <sys/dmu_tx.h>
|
||||||
|
@ -86,12 +83,6 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, znode, CTLFLAG_RD,
|
||||||
#define ZNODE_STAT_ADD(stat) /* nothing */
|
#define ZNODE_STAT_ADD(stat) /* nothing */
|
||||||
#endif /* ZNODE_STATS */
|
#endif /* ZNODE_STATS */
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions needed for userland (ie: libzpool) are not put under
|
|
||||||
* #ifdef_KERNEL; the rest of the functions have dependencies
|
|
||||||
* (such as VFS logic) that will not compile easily in userland.
|
|
||||||
*/
|
|
||||||
#ifdef _KERNEL
|
|
||||||
#if !defined(KMEM_DEBUG)
|
#if !defined(KMEM_DEBUG)
|
||||||
#define _ZFS_USE_SMR
|
#define _ZFS_USE_SMR
|
||||||
static uma_zone_t znode_uma_zone;
|
static uma_zone_t znode_uma_zone;
|
||||||
|
@ -1787,376 +1778,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
|
||||||
mutex_destroy(&zfsvfs->z_hold_mtx[i]);
|
mutex_destroy(&zfsvfs->z_hold_mtx[i]);
|
||||||
kmem_free(zfsvfs, sizeof (zfsvfs_t));
|
kmem_free(zfsvfs, sizeof (zfsvfs_t));
|
||||||
}
|
}
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
|
|
||||||
{
|
|
||||||
uint64_t sa_obj = 0;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
|
|
||||||
if (error != 0 && error != ENOENT)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
|
|
||||||
dmu_buf_t **db, const void *tag)
|
|
||||||
{
|
|
||||||
dmu_object_info_t doi;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
dmu_object_info_from_db(*db, &doi);
|
|
||||||
if ((doi.doi_bonus_type != DMU_OT_SA &&
|
|
||||||
doi.doi_bonus_type != DMU_OT_ZNODE) ||
|
|
||||||
(doi.doi_bonus_type == DMU_OT_ZNODE &&
|
|
||||||
doi.doi_bonus_size < sizeof (znode_phys_t))) {
|
|
||||||
sa_buf_rele(*db, tag);
|
|
||||||
return (SET_ERROR(ENOTSUP));
|
|
||||||
}
|
|
||||||
|
|
||||||
error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
|
|
||||||
if (error != 0) {
|
|
||||||
sa_buf_rele(*db, tag);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
|
|
||||||
{
|
|
||||||
sa_handle_destroy(hdl);
|
|
||||||
sa_buf_rele(db, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given an object number, return its parent object number and whether
|
|
||||||
* or not the object is an extended attribute directory.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
|
|
||||||
uint64_t *pobjp, int *is_xattrdir)
|
|
||||||
{
|
|
||||||
uint64_t parent;
|
|
||||||
uint64_t pflags;
|
|
||||||
uint64_t mode;
|
|
||||||
uint64_t parent_mode;
|
|
||||||
sa_bulk_attr_t bulk[3];
|
|
||||||
sa_handle_t *sa_hdl;
|
|
||||||
dmu_buf_t *sa_db;
|
|
||||||
int count = 0;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
|
|
||||||
&parent, sizeof (parent));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
|
|
||||||
&pflags, sizeof (pflags));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
|
|
||||||
&mode, sizeof (mode));
|
|
||||||
|
|
||||||
if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When a link is removed its parent pointer is not changed and will
|
|
||||||
* be invalid. There are two cases where a link is removed but the
|
|
||||||
* file stays around, when it goes to the delete queue and when there
|
|
||||||
* are additional links.
|
|
||||||
*/
|
|
||||||
error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
|
|
||||||
zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extended attributes can be applied to files, directories, etc.
|
|
||||||
* Otherwise the parent must be a directory.
|
|
||||||
*/
|
|
||||||
if (!*is_xattrdir && !S_ISDIR(parent_mode))
|
|
||||||
return (SET_ERROR(EINVAL));
|
|
||||||
|
|
||||||
*pobjp = parent;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given an object number, return some zpl level statistics
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
|
|
||||||
zfs_stat_t *sb)
|
|
||||||
{
|
|
||||||
sa_bulk_attr_t bulk[4];
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
|
|
||||||
&sb->zs_mode, sizeof (sb->zs_mode));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
|
|
||||||
&sb->zs_gen, sizeof (sb->zs_gen));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
|
|
||||||
&sb->zs_links, sizeof (sb->zs_links));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
|
|
||||||
&sb->zs_ctime, sizeof (sb->zs_ctime));
|
|
||||||
|
|
||||||
return (sa_bulk_lookup(hdl, bulk, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
|
|
||||||
sa_attr_type_t *sa_table, char *buf, int len)
|
|
||||||
{
|
|
||||||
sa_handle_t *sa_hdl;
|
|
||||||
sa_handle_t *prevhdl = NULL;
|
|
||||||
dmu_buf_t *prevdb = NULL;
|
|
||||||
dmu_buf_t *sa_db = NULL;
|
|
||||||
char *path = buf + len - 1;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
*path = '\0';
|
|
||||||
sa_hdl = hdl;
|
|
||||||
|
|
||||||
uint64_t deleteq_obj;
|
|
||||||
VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
|
|
||||||
ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
|
|
||||||
error = zap_lookup_int(osp, deleteq_obj, obj);
|
|
||||||
if (error == 0) {
|
|
||||||
return (ESTALE);
|
|
||||||
} else if (error != ENOENT) {
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint64_t pobj;
|
|
||||||
char component[MAXNAMELEN + 2];
|
|
||||||
size_t complen;
|
|
||||||
int is_xattrdir;
|
|
||||||
|
|
||||||
if (prevdb) {
|
|
||||||
ASSERT3P(prevhdl, !=, NULL);
|
|
||||||
zfs_release_sa_handle(prevhdl, prevdb, FTAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
|
|
||||||
&is_xattrdir)) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (pobj == obj) {
|
|
||||||
if (path[0] != '/')
|
|
||||||
*--path = '/';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
component[0] = '/';
|
|
||||||
if (is_xattrdir) {
|
|
||||||
(void) sprintf(component + 1, "<xattrdir>");
|
|
||||||
} else {
|
|
||||||
error = zap_value_search(osp, pobj, obj,
|
|
||||||
ZFS_DIRENT_OBJ(-1ULL), component + 1);
|
|
||||||
if (error != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
complen = strlen(component);
|
|
||||||
path -= complen;
|
|
||||||
ASSERT3P(path, >=, buf);
|
|
||||||
memcpy(path, component, complen);
|
|
||||||
obj = pobj;
|
|
||||||
|
|
||||||
if (sa_hdl != hdl) {
|
|
||||||
prevhdl = sa_hdl;
|
|
||||||
prevdb = sa_db;
|
|
||||||
}
|
|
||||||
error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
|
|
||||||
if (error != 0) {
|
|
||||||
sa_hdl = prevhdl;
|
|
||||||
sa_db = prevdb;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa_hdl != NULL && sa_hdl != hdl) {
|
|
||||||
ASSERT3P(sa_db, !=, NULL);
|
|
||||||
zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == 0)
|
|
||||||
(void) memmove(buf, path, buf + len - path);
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
|
|
||||||
{
|
|
||||||
sa_attr_type_t *sa_table;
|
|
||||||
sa_handle_t *hdl;
|
|
||||||
dmu_buf_t *db;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
error = zfs_sa_setup(osp, &sa_table);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
|
|
||||||
|
|
||||||
zfs_release_sa_handle(hdl, db, FTAG);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
|
|
||||||
char *buf, int len)
|
|
||||||
{
|
|
||||||
char *path = buf + len - 1;
|
|
||||||
sa_attr_type_t *sa_table;
|
|
||||||
sa_handle_t *hdl;
|
|
||||||
dmu_buf_t *db;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
*path = '\0';
|
|
||||||
|
|
||||||
error = zfs_sa_setup(osp, &sa_table);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
|
|
||||||
if (error != 0) {
|
|
||||||
zfs_release_sa_handle(hdl, db, FTAG);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
|
|
||||||
|
|
||||||
zfs_release_sa_handle(hdl, db, FTAG);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a property stored within the master node.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
|
|
||||||
{
|
|
||||||
uint64_t *cached_copy = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Figure out where in the objset_t the cached copy would live, if it
|
|
||||||
* is available for the requested property.
|
|
||||||
*/
|
|
||||||
if (os != NULL) {
|
|
||||||
switch (prop) {
|
|
||||||
case ZFS_PROP_VERSION:
|
|
||||||
cached_copy = &os->os_version;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_NORMALIZE:
|
|
||||||
cached_copy = &os->os_normalization;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_UTF8ONLY:
|
|
||||||
cached_copy = &os->os_utf8only;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_CASE:
|
|
||||||
cached_copy = &os->os_casesensitivity;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
|
|
||||||
*value = *cached_copy;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the property wasn't cached, look up the file system's value for
|
|
||||||
* the property. For the version property, we look up a slightly
|
|
||||||
* different string.
|
|
||||||
*/
|
|
||||||
const char *pname;
|
|
||||||
int error = ENOENT;
|
|
||||||
if (prop == ZFS_PROP_VERSION) {
|
|
||||||
pname = ZPL_VERSION_STR;
|
|
||||||
} else {
|
|
||||||
pname = zfs_prop_to_name(prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (os != NULL) {
|
|
||||||
ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
|
|
||||||
error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == ENOENT) {
|
|
||||||
/* No value set, use the default value */
|
|
||||||
switch (prop) {
|
|
||||||
case ZFS_PROP_VERSION:
|
|
||||||
*value = ZPL_VERSION;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_NORMALIZE:
|
|
||||||
case ZFS_PROP_UTF8ONLY:
|
|
||||||
*value = 0;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_CASE:
|
|
||||||
*value = ZFS_CASE_SENSITIVE;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_ACLTYPE:
|
|
||||||
*value = ZFS_ACLTYPE_NFSV4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If one of the methods for getting the property value above worked,
|
|
||||||
* copy it into the objset_t's cache.
|
|
||||||
*/
|
|
||||||
if (error == 0 && cached_copy != NULL) {
|
|
||||||
*cached_copy = *value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
zfs_znode_update_vfs(znode_t *zp)
|
|
||||||
{
|
|
||||||
vm_object_t object;
|
|
||||||
|
|
||||||
if ((object = ZTOV(zp)->v_object) == NULL ||
|
|
||||||
zp->z_size == object->un_pager.vnp.vnp_size)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vnode_pager_setsize(ZTOV(zp), zp->z_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
int
|
int
|
||||||
zfs_znode_parent_and_name(znode_t *zp, znode_t **dzpp, char *buf)
|
zfs_znode_parent_and_name(znode_t *zp, znode_t **dzpp, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -2186,9 +1808,7 @@ zfs_znode_parent_and_name(znode_t *zp, znode_t **dzpp, char *buf)
|
||||||
err = zfs_zget(zfsvfs, parent, dzpp);
|
err = zfs_zget(zfsvfs, parent, dzpp);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
int
|
int
|
||||||
zfs_rlimit_fsize(off_t fsize)
|
zfs_rlimit_fsize(off_t fsize)
|
||||||
{
|
{
|
||||||
|
@ -2211,4 +1831,3 @@ zfs_rlimit_fsize(off_t fsize)
|
||||||
|
|
||||||
return (EFBIG);
|
return (EFBIG);
|
||||||
}
|
}
|
||||||
#endif /* _KERNEL */
|
|
|
@ -42,7 +42,6 @@
|
||||||
#include <sys/abd.h>
|
#include <sys/abd.h>
|
||||||
#include <sys/zil.h>
|
#include <sys/zil.h>
|
||||||
#include <sys/fm/fs/zfs.h>
|
#include <sys/fm/fs/zfs.h>
|
||||||
#ifdef _KERNEL
|
|
||||||
#include <sys/shrinker.h>
|
#include <sys/shrinker.h>
|
||||||
#include <sys/vmsystm.h>
|
#include <sys/vmsystm.h>
|
||||||
#include <sys/zpl.h>
|
#include <sys/zpl.h>
|
||||||
|
@ -50,7 +49,6 @@
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/memory.h>
|
#include <linux/memory.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#endif
|
|
||||||
#include <sys/callb.h>
|
#include <sys/callb.h>
|
||||||
#include <sys/kstat.h>
|
#include <sys/kstat.h>
|
||||||
#include <sys/zthr.h>
|
#include <sys/zthr.h>
|
||||||
|
@ -59,7 +57,6 @@
|
||||||
#include <sys/trace_zfs.h>
|
#include <sys/trace_zfs.h>
|
||||||
#include <sys/aggsum.h>
|
#include <sys/aggsum.h>
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
/*
|
/*
|
||||||
* This is a limit on how many pages the ARC shrinker makes available for
|
* This is a limit on how many pages the ARC shrinker makes available for
|
||||||
* eviction in response to one page allocation attempt. Note that in
|
* eviction in response to one page allocation attempt. Note that in
|
||||||
|
@ -87,7 +84,6 @@ static int zfs_arc_shrinker_seeks = DEFAULT_SEEKS;
|
||||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||||
static struct notifier_block arc_hotplug_callback_mem_nb;
|
static struct notifier_block arc_hotplug_callback_mem_nb;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a default max arc size based on the amount of physical memory.
|
* Return a default max arc size based on the amount of physical memory.
|
||||||
|
@ -105,7 +101,6 @@ arc_default_max(uint64_t min, uint64_t allmem)
|
||||||
return (MAX(allmem * 5 / 8, size));
|
return (MAX(allmem * 5 / 8, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
/*
|
/*
|
||||||
* Return maximum amount of memory that we could possibly use. Reduced
|
* Return maximum amount of memory that we could possibly use. Reduced
|
||||||
* to half of all memory in user space which is primarily used for testing.
|
* to half of all memory in user space which is primarily used for testing.
|
||||||
|
@ -459,48 +454,6 @@ arc_unregister_hotplug(void)
|
||||||
unregister_memory_notifier(&arc_hotplug_callback_mem_nb);
|
unregister_memory_notifier(&arc_hotplug_callback_mem_nb);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else /* _KERNEL */
|
|
||||||
int64_t
|
|
||||||
arc_available_memory(void)
|
|
||||||
{
|
|
||||||
int64_t lowest = INT64_MAX;
|
|
||||||
|
|
||||||
/* Every 100 calls, free a small amount */
|
|
||||||
if (random_in_range(100) == 0)
|
|
||||||
lowest = -1024;
|
|
||||||
|
|
||||||
return (lowest);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg)
|
|
||||||
{
|
|
||||||
(void) spa, (void) reserve, (void) txg;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t
|
|
||||||
arc_all_memory(void)
|
|
||||||
{
|
|
||||||
return (ptob(physmem) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t
|
|
||||||
arc_free_memory(void)
|
|
||||||
{
|
|
||||||
return (random_in_range(arc_all_memory() * 20 / 100));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
arc_register_hotplug(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
arc_unregister_hotplug(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, shrinker_limit, INT, ZMOD_RW,
|
ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, shrinker_limit, INT, ZMOD_RW,
|
||||||
"Limit on number of pages that ARC shrinker can reclaim at once");
|
"Limit on number of pages that ARC shrinker can reclaim at once");
|
||||||
|
|
|
@ -111,12 +111,7 @@ zfs_dbgmsg_fini(void)
|
||||||
procfs_list_uninstall(&zfs_dbgmsgs);
|
procfs_list_uninstall(&zfs_dbgmsgs);
|
||||||
zfs_dbgmsg_purge(0);
|
zfs_dbgmsg_purge(0);
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO - decide how to make this permanent
|
|
||||||
*/
|
|
||||||
#ifdef _KERNEL
|
|
||||||
procfs_list_destroy(&zfs_dbgmsgs);
|
procfs_list_destroy(&zfs_dbgmsgs);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -148,8 +143,6 @@ __zfs_dbgmsg(char *buf)
|
||||||
mutex_exit(&zfs_dbgmsgs.pl_lock);
|
mutex_exit(&zfs_dbgmsgs.pl_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
|
|
||||||
void
|
void
|
||||||
__dprintf(boolean_t dprint, const char *file, const char *func,
|
__dprintf(boolean_t dprint, const char *file, const char *func,
|
||||||
int line, const char *fmt, ...)
|
int line, const char *fmt, ...)
|
||||||
|
@ -218,38 +211,6 @@ __dprintf(boolean_t dprint, const char *file, const char *func,
|
||||||
kmem_free(buf, size);
|
kmem_free(buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void
|
|
||||||
zfs_dbgmsg_print(int fd, const char *tag)
|
|
||||||
{
|
|
||||||
ssize_t ret __attribute__((unused));
|
|
||||||
|
|
||||||
mutex_enter(&zfs_dbgmsgs.pl_lock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We use write() in this function instead of printf()
|
|
||||||
* so it is safe to call from a signal handler.
|
|
||||||
*/
|
|
||||||
ret = write(fd, "ZFS_DBGMSG(", 11);
|
|
||||||
ret = write(fd, tag, strlen(tag));
|
|
||||||
ret = write(fd, ") START:\n", 9);
|
|
||||||
|
|
||||||
for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs.pl_list); zdm != NULL;
|
|
||||||
zdm = list_next(&zfs_dbgmsgs.pl_list, zdm)) {
|
|
||||||
ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg));
|
|
||||||
ret = write(fd, "\n", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = write(fd, "ZFS_DBGMSG(", 11);
|
|
||||||
ret = write(fd, tag, strlen(tag));
|
|
||||||
ret = write(fd, ") END\n", 6);
|
|
||||||
|
|
||||||
mutex_exit(&zfs_dbgmsgs.pl_lock);
|
|
||||||
}
|
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
module_param(zfs_dbgmsg_enable, int, 0644);
|
module_param(zfs_dbgmsg_enable, int, 0644);
|
||||||
MODULE_PARM_DESC(zfs_dbgmsg_enable, "Enable ZFS debug message log");
|
MODULE_PARM_DESC(zfs_dbgmsg_enable, "Enable ZFS debug message log");
|
||||||
|
|
||||||
|
@ -257,4 +218,3 @@ MODULE_PARM_DESC(zfs_dbgmsg_enable, "Enable ZFS debug message log");
|
||||||
module_param(zfs_dbgmsg_maxsize, uint, 0644);
|
module_param(zfs_dbgmsg_maxsize, uint, 0644);
|
||||||
/* END CSTYLED */
|
/* END CSTYLED */
|
||||||
MODULE_PARM_DESC(zfs_dbgmsg_maxsize, "Maximum ZFS debug log size");
|
MODULE_PARM_DESC(zfs_dbgmsg_maxsize, "Maximum ZFS debug log size");
|
||||||
#endif
|
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
/* Portions Copyright 2007 Jeremy Teo */
|
/* Portions Copyright 2007 Jeremy Teo */
|
||||||
|
|
||||||
#ifdef _KERNEL
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
@ -49,8 +48,6 @@
|
||||||
#include <sys/dnode.h>
|
#include <sys/dnode.h>
|
||||||
#include <sys/fs/zfs.h>
|
#include <sys/fs/zfs.h>
|
||||||
#include <sys/zpl.h>
|
#include <sys/zpl.h>
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
#include <sys/dmu.h>
|
#include <sys/dmu.h>
|
||||||
#include <sys/dmu_objset.h>
|
#include <sys/dmu_objset.h>
|
||||||
#include <sys/dmu_tx.h>
|
#include <sys/dmu_tx.h>
|
||||||
|
@ -65,13 +62,6 @@
|
||||||
#include "zfs_prop.h"
|
#include "zfs_prop.h"
|
||||||
#include "zfs_comutil.h"
|
#include "zfs_comutil.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions needed for userland (ie: libzpool) are not put under
|
|
||||||
* #ifdef_KERNEL; the rest of the functions have dependencies
|
|
||||||
* (such as VFS logic) that will not compile easily in userland.
|
|
||||||
*/
|
|
||||||
#ifdef _KERNEL
|
|
||||||
|
|
||||||
static kmem_cache_t *znode_cache = NULL;
|
static kmem_cache_t *znode_cache = NULL;
|
||||||
static kmem_cache_t *znode_hold_cache = NULL;
|
static kmem_cache_t *znode_hold_cache = NULL;
|
||||||
unsigned int zfs_object_mutex_size = ZFS_OBJ_MTX_SZ;
|
unsigned int zfs_object_mutex_size = ZFS_OBJ_MTX_SZ;
|
||||||
|
@ -2006,360 +1996,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
|
||||||
kmem_free(sb, sizeof (struct super_block));
|
kmem_free(sb, sizeof (struct super_block));
|
||||||
kmem_free(zfsvfs, sizeof (zfsvfs_t));
|
kmem_free(zfsvfs, sizeof (zfsvfs_t));
|
||||||
}
|
}
|
||||||
#endif /* _KERNEL */
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
|
|
||||||
{
|
|
||||||
uint64_t sa_obj = 0;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
|
|
||||||
if (error != 0 && error != ENOENT)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
|
|
||||||
dmu_buf_t **db, const void *tag)
|
|
||||||
{
|
|
||||||
dmu_object_info_t doi;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
dmu_object_info_from_db(*db, &doi);
|
|
||||||
if ((doi.doi_bonus_type != DMU_OT_SA &&
|
|
||||||
doi.doi_bonus_type != DMU_OT_ZNODE) ||
|
|
||||||
(doi.doi_bonus_type == DMU_OT_ZNODE &&
|
|
||||||
doi.doi_bonus_size < sizeof (znode_phys_t))) {
|
|
||||||
sa_buf_rele(*db, tag);
|
|
||||||
return (SET_ERROR(ENOTSUP));
|
|
||||||
}
|
|
||||||
|
|
||||||
error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
|
|
||||||
if (error != 0) {
|
|
||||||
sa_buf_rele(*db, tag);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
|
|
||||||
{
|
|
||||||
sa_handle_destroy(hdl);
|
|
||||||
sa_buf_rele(db, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given an object number, return its parent object number and whether
|
|
||||||
* or not the object is an extended attribute directory.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
|
|
||||||
uint64_t *pobjp, int *is_xattrdir)
|
|
||||||
{
|
|
||||||
uint64_t parent;
|
|
||||||
uint64_t pflags;
|
|
||||||
uint64_t mode;
|
|
||||||
uint64_t parent_mode;
|
|
||||||
sa_bulk_attr_t bulk[3];
|
|
||||||
sa_handle_t *sa_hdl;
|
|
||||||
dmu_buf_t *sa_db;
|
|
||||||
int count = 0;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
|
|
||||||
&parent, sizeof (parent));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
|
|
||||||
&pflags, sizeof (pflags));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
|
|
||||||
&mode, sizeof (mode));
|
|
||||||
|
|
||||||
if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When a link is removed its parent pointer is not changed and will
|
|
||||||
* be invalid. There are two cases where a link is removed but the
|
|
||||||
* file stays around, when it goes to the delete queue and when there
|
|
||||||
* are additional links.
|
|
||||||
*/
|
|
||||||
error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
|
|
||||||
zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extended attributes can be applied to files, directories, etc.
|
|
||||||
* Otherwise the parent must be a directory.
|
|
||||||
*/
|
|
||||||
if (!*is_xattrdir && !S_ISDIR(parent_mode))
|
|
||||||
return (SET_ERROR(EINVAL));
|
|
||||||
|
|
||||||
*pobjp = parent;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given an object number, return some zpl level statistics
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
|
|
||||||
zfs_stat_t *sb)
|
|
||||||
{
|
|
||||||
sa_bulk_attr_t bulk[4];
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
|
|
||||||
&sb->zs_mode, sizeof (sb->zs_mode));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
|
|
||||||
&sb->zs_gen, sizeof (sb->zs_gen));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
|
|
||||||
&sb->zs_links, sizeof (sb->zs_links));
|
|
||||||
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
|
|
||||||
&sb->zs_ctime, sizeof (sb->zs_ctime));
|
|
||||||
|
|
||||||
return (sa_bulk_lookup(hdl, bulk, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
|
|
||||||
sa_attr_type_t *sa_table, char *buf, int len)
|
|
||||||
{
|
|
||||||
sa_handle_t *sa_hdl;
|
|
||||||
sa_handle_t *prevhdl = NULL;
|
|
||||||
dmu_buf_t *prevdb = NULL;
|
|
||||||
dmu_buf_t *sa_db = NULL;
|
|
||||||
char *path = buf + len - 1;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
*path = '\0';
|
|
||||||
sa_hdl = hdl;
|
|
||||||
|
|
||||||
uint64_t deleteq_obj;
|
|
||||||
VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
|
|
||||||
ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
|
|
||||||
error = zap_lookup_int(osp, deleteq_obj, obj);
|
|
||||||
if (error == 0) {
|
|
||||||
return (ESTALE);
|
|
||||||
} else if (error != ENOENT) {
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint64_t pobj = 0;
|
|
||||||
char component[MAXNAMELEN + 2];
|
|
||||||
size_t complen;
|
|
||||||
int is_xattrdir = 0;
|
|
||||||
|
|
||||||
if (prevdb) {
|
|
||||||
ASSERT(prevhdl != NULL);
|
|
||||||
zfs_release_sa_handle(prevhdl, prevdb, FTAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
|
|
||||||
&is_xattrdir)) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (pobj == obj) {
|
|
||||||
if (path[0] != '/')
|
|
||||||
*--path = '/';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
component[0] = '/';
|
|
||||||
if (is_xattrdir) {
|
|
||||||
strcpy(component + 1, "<xattrdir>");
|
|
||||||
} else {
|
|
||||||
error = zap_value_search(osp, pobj, obj,
|
|
||||||
ZFS_DIRENT_OBJ(-1ULL), component + 1);
|
|
||||||
if (error != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
complen = strlen(component);
|
|
||||||
path -= complen;
|
|
||||||
ASSERT(path >= buf);
|
|
||||||
memcpy(path, component, complen);
|
|
||||||
obj = pobj;
|
|
||||||
|
|
||||||
if (sa_hdl != hdl) {
|
|
||||||
prevhdl = sa_hdl;
|
|
||||||
prevdb = sa_db;
|
|
||||||
}
|
|
||||||
error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
|
|
||||||
if (error != 0) {
|
|
||||||
sa_hdl = prevhdl;
|
|
||||||
sa_db = prevdb;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa_hdl != NULL && sa_hdl != hdl) {
|
|
||||||
ASSERT(sa_db != NULL);
|
|
||||||
zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == 0)
|
|
||||||
(void) memmove(buf, path, buf + len - path);
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
|
|
||||||
{
|
|
||||||
sa_attr_type_t *sa_table;
|
|
||||||
sa_handle_t *hdl;
|
|
||||||
dmu_buf_t *db;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
error = zfs_sa_setup(osp, &sa_table);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
|
|
||||||
|
|
||||||
zfs_release_sa_handle(hdl, db, FTAG);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
|
|
||||||
char *buf, int len)
|
|
||||||
{
|
|
||||||
char *path = buf + len - 1;
|
|
||||||
sa_attr_type_t *sa_table;
|
|
||||||
sa_handle_t *hdl;
|
|
||||||
dmu_buf_t *db;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
*path = '\0';
|
|
||||||
|
|
||||||
error = zfs_sa_setup(osp, &sa_table);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
|
|
||||||
if (error != 0) {
|
|
||||||
zfs_release_sa_handle(hdl, db, FTAG);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
|
|
||||||
|
|
||||||
zfs_release_sa_handle(hdl, db, FTAG);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a property stored within the master node.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
|
|
||||||
{
|
|
||||||
uint64_t *cached_copy = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Figure out where in the objset_t the cached copy would live, if it
|
|
||||||
* is available for the requested property.
|
|
||||||
*/
|
|
||||||
if (os != NULL) {
|
|
||||||
switch (prop) {
|
|
||||||
case ZFS_PROP_VERSION:
|
|
||||||
cached_copy = &os->os_version;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_NORMALIZE:
|
|
||||||
cached_copy = &os->os_normalization;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_UTF8ONLY:
|
|
||||||
cached_copy = &os->os_utf8only;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_CASE:
|
|
||||||
cached_copy = &os->os_casesensitivity;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
|
|
||||||
*value = *cached_copy;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the property wasn't cached, look up the file system's value for
|
|
||||||
* the property. For the version property, we look up a slightly
|
|
||||||
* different string.
|
|
||||||
*/
|
|
||||||
const char *pname;
|
|
||||||
int error = ENOENT;
|
|
||||||
if (prop == ZFS_PROP_VERSION)
|
|
||||||
pname = ZPL_VERSION_STR;
|
|
||||||
else
|
|
||||||
pname = zfs_prop_to_name(prop);
|
|
||||||
|
|
||||||
if (os != NULL) {
|
|
||||||
ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
|
|
||||||
error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == ENOENT) {
|
|
||||||
/* No value set, use the default value */
|
|
||||||
switch (prop) {
|
|
||||||
case ZFS_PROP_VERSION:
|
|
||||||
*value = ZPL_VERSION;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_NORMALIZE:
|
|
||||||
case ZFS_PROP_UTF8ONLY:
|
|
||||||
*value = 0;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_CASE:
|
|
||||||
*value = ZFS_CASE_SENSITIVE;
|
|
||||||
break;
|
|
||||||
case ZFS_PROP_ACLTYPE:
|
|
||||||
*value = ZFS_ACLTYPE_OFF;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If one of the methods for getting the property value above worked,
|
|
||||||
* copy it into the objset_t's cache.
|
|
||||||
*/
|
|
||||||
if (error == 0 && cached_copy != NULL) {
|
|
||||||
*cached_copy = *value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_KERNEL)
|
|
||||||
EXPORT_SYMBOL(zfs_create_fs);
|
EXPORT_SYMBOL(zfs_create_fs);
|
||||||
EXPORT_SYMBOL(zfs_obj_to_path);
|
EXPORT_SYMBOL(zfs_obj_to_path);
|
||||||
|
|
||||||
|
@ -2369,4 +2006,3 @@ MODULE_PARM_DESC(zfs_object_mutex_size, "Size of znode hold array");
|
||||||
module_param(zfs_unlink_suspend_progress, int, 0644);
|
module_param(zfs_unlink_suspend_progress, int, 0644);
|
||||||
MODULE_PARM_DESC(zfs_unlink_suspend_progress, "Set to prevent async unlinks "
|
MODULE_PARM_DESC(zfs_unlink_suspend_progress, "Set to prevent async unlinks "
|
||||||
"(debug - leaks space into the unlinked set)");
|
"(debug - leaks space into the unlinked set)");
|
||||||
#endif
|
|
|
@ -0,0 +1,397 @@
|
||||||
|
/*
|
||||||
|
* 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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||||
|
* Copyright (c) 2014 Integros [integros.com]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Portions Copyright 2007 Jeremy Teo */
|
||||||
|
/* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
|
||||||
|
|
||||||
|
#include <sys/dmu.h>
|
||||||
|
#include <sys/dmu_objset.h>
|
||||||
|
#include <sys/dmu_tx.h>
|
||||||
|
#include <sys/zfs_refcount.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/zap.h>
|
||||||
|
#include <sys/zfs_znode.h>
|
||||||
|
#include <sys/sa.h>
|
||||||
|
#include <sys/zfs_sa.h>
|
||||||
|
#include <sys/zfs_stat.h>
|
||||||
|
|
||||||
|
#include "zfs_prop.h"
|
||||||
|
#include "zfs_comutil.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
|
||||||
|
{
|
||||||
|
uint64_t sa_obj = 0;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
|
||||||
|
if (error != 0 && error != ENOENT)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
|
||||||
|
dmu_buf_t **db, const void *tag)
|
||||||
|
{
|
||||||
|
dmu_object_info_t doi;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
dmu_object_info_from_db(*db, &doi);
|
||||||
|
if ((doi.doi_bonus_type != DMU_OT_SA &&
|
||||||
|
doi.doi_bonus_type != DMU_OT_ZNODE) ||
|
||||||
|
(doi.doi_bonus_type == DMU_OT_ZNODE &&
|
||||||
|
doi.doi_bonus_size < sizeof (znode_phys_t))) {
|
||||||
|
sa_buf_rele(*db, tag);
|
||||||
|
return (SET_ERROR(ENOTSUP));
|
||||||
|
}
|
||||||
|
|
||||||
|
error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
|
||||||
|
if (error != 0) {
|
||||||
|
sa_buf_rele(*db, tag);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
|
||||||
|
{
|
||||||
|
sa_handle_destroy(hdl);
|
||||||
|
sa_buf_rele(db, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given an object number, return its parent object number and whether
|
||||||
|
* or not the object is an extended attribute directory.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
|
||||||
|
uint64_t *pobjp, int *is_xattrdir)
|
||||||
|
{
|
||||||
|
uint64_t parent;
|
||||||
|
uint64_t pflags;
|
||||||
|
uint64_t mode;
|
||||||
|
uint64_t parent_mode;
|
||||||
|
sa_bulk_attr_t bulk[3];
|
||||||
|
sa_handle_t *sa_hdl;
|
||||||
|
dmu_buf_t *sa_db;
|
||||||
|
int count = 0;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
|
||||||
|
&parent, sizeof (parent));
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
|
||||||
|
&pflags, sizeof (pflags));
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
|
||||||
|
&mode, sizeof (mode));
|
||||||
|
|
||||||
|
if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When a link is removed its parent pointer is not changed and will
|
||||||
|
* be invalid. There are two cases where a link is removed but the
|
||||||
|
* file stays around, when it goes to the delete queue and when there
|
||||||
|
* are additional links.
|
||||||
|
*/
|
||||||
|
error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
|
||||||
|
zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extended attributes can be applied to files, directories, etc.
|
||||||
|
* Otherwise the parent must be a directory.
|
||||||
|
*/
|
||||||
|
if (!*is_xattrdir && !S_ISDIR(parent_mode))
|
||||||
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
|
*pobjp = parent;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given an object number, return some zpl level statistics
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
|
||||||
|
zfs_stat_t *sb)
|
||||||
|
{
|
||||||
|
sa_bulk_attr_t bulk[4];
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
|
||||||
|
&sb->zs_mode, sizeof (sb->zs_mode));
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
|
||||||
|
&sb->zs_gen, sizeof (sb->zs_gen));
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
|
||||||
|
&sb->zs_links, sizeof (sb->zs_links));
|
||||||
|
SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
|
||||||
|
&sb->zs_ctime, sizeof (sb->zs_ctime));
|
||||||
|
|
||||||
|
return (sa_bulk_lookup(hdl, bulk, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
|
||||||
|
sa_attr_type_t *sa_table, char *buf, int len)
|
||||||
|
{
|
||||||
|
sa_handle_t *sa_hdl;
|
||||||
|
sa_handle_t *prevhdl = NULL;
|
||||||
|
dmu_buf_t *prevdb = NULL;
|
||||||
|
dmu_buf_t *sa_db = NULL;
|
||||||
|
char *path = buf + len - 1;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
*path = '\0';
|
||||||
|
sa_hdl = hdl;
|
||||||
|
|
||||||
|
uint64_t deleteq_obj;
|
||||||
|
VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
|
||||||
|
ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
|
||||||
|
error = zap_lookup_int(osp, deleteq_obj, obj);
|
||||||
|
if (error == 0) {
|
||||||
|
return (ESTALE);
|
||||||
|
} else if (error != ENOENT) {
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uint64_t pobj = 0;
|
||||||
|
char component[MAXNAMELEN + 2];
|
||||||
|
size_t complen;
|
||||||
|
int is_xattrdir = 0;
|
||||||
|
|
||||||
|
if (prevdb) {
|
||||||
|
ASSERT3P(prevhdl, !=, NULL);
|
||||||
|
zfs_release_sa_handle(prevhdl, prevdb, FTAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
|
||||||
|
&is_xattrdir)) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (pobj == obj) {
|
||||||
|
if (path[0] != '/')
|
||||||
|
*--path = '/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
component[0] = '/';
|
||||||
|
if (is_xattrdir) {
|
||||||
|
strcpy(component + 1, "<xattrdir>");
|
||||||
|
} else {
|
||||||
|
error = zap_value_search(osp, pobj, obj,
|
||||||
|
ZFS_DIRENT_OBJ(-1ULL), component + 1);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
complen = strlen(component);
|
||||||
|
path -= complen;
|
||||||
|
ASSERT3P(path, >=, buf);
|
||||||
|
memcpy(path, component, complen);
|
||||||
|
obj = pobj;
|
||||||
|
|
||||||
|
if (sa_hdl != hdl) {
|
||||||
|
prevhdl = sa_hdl;
|
||||||
|
prevdb = sa_db;
|
||||||
|
}
|
||||||
|
error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
|
||||||
|
if (error != 0) {
|
||||||
|
sa_hdl = prevhdl;
|
||||||
|
sa_db = prevdb;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa_hdl != NULL && sa_hdl != hdl) {
|
||||||
|
ASSERT3P(sa_db, !=, NULL);
|
||||||
|
zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error == 0)
|
||||||
|
(void) memmove(buf, path, buf + len - path);
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
|
||||||
|
{
|
||||||
|
sa_attr_type_t *sa_table;
|
||||||
|
sa_handle_t *hdl;
|
||||||
|
dmu_buf_t *db;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = zfs_sa_setup(osp, &sa_table);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
|
||||||
|
|
||||||
|
zfs_release_sa_handle(hdl, db, FTAG);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
|
||||||
|
char *buf, int len)
|
||||||
|
{
|
||||||
|
char *path = buf + len - 1;
|
||||||
|
sa_attr_type_t *sa_table;
|
||||||
|
sa_handle_t *hdl;
|
||||||
|
dmu_buf_t *db;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
*path = '\0';
|
||||||
|
|
||||||
|
error = zfs_sa_setup(osp, &sa_table);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
|
||||||
|
if (error != 0) {
|
||||||
|
zfs_release_sa_handle(hdl, db, FTAG);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
|
||||||
|
|
||||||
|
zfs_release_sa_handle(hdl, db, FTAG);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a property stored within the master node.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
|
||||||
|
{
|
||||||
|
uint64_t *cached_copy = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure out where in the objset_t the cached copy would live, if it
|
||||||
|
* is available for the requested property.
|
||||||
|
*/
|
||||||
|
if (os != NULL) {
|
||||||
|
switch (prop) {
|
||||||
|
case ZFS_PROP_VERSION:
|
||||||
|
cached_copy = &os->os_version;
|
||||||
|
break;
|
||||||
|
case ZFS_PROP_NORMALIZE:
|
||||||
|
cached_copy = &os->os_normalization;
|
||||||
|
break;
|
||||||
|
case ZFS_PROP_UTF8ONLY:
|
||||||
|
cached_copy = &os->os_utf8only;
|
||||||
|
break;
|
||||||
|
case ZFS_PROP_CASE:
|
||||||
|
cached_copy = &os->os_casesensitivity;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
|
||||||
|
*value = *cached_copy;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the property wasn't cached, look up the file system's value for
|
||||||
|
* the property. For the version property, we look up a slightly
|
||||||
|
* different string.
|
||||||
|
*/
|
||||||
|
const char *pname;
|
||||||
|
int error = ENOENT;
|
||||||
|
if (prop == ZFS_PROP_VERSION)
|
||||||
|
pname = ZPL_VERSION_STR;
|
||||||
|
else
|
||||||
|
pname = zfs_prop_to_name(prop);
|
||||||
|
|
||||||
|
if (os != NULL) {
|
||||||
|
ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
|
||||||
|
error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error == ENOENT) {
|
||||||
|
/* No value set, use the default value */
|
||||||
|
switch (prop) {
|
||||||
|
case ZFS_PROP_VERSION:
|
||||||
|
*value = ZPL_VERSION;
|
||||||
|
break;
|
||||||
|
case ZFS_PROP_NORMALIZE:
|
||||||
|
case ZFS_PROP_UTF8ONLY:
|
||||||
|
*value = 0;
|
||||||
|
break;
|
||||||
|
case ZFS_PROP_CASE:
|
||||||
|
*value = ZFS_CASE_SENSITIVE;
|
||||||
|
break;
|
||||||
|
case ZFS_PROP_ACLTYPE:
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
*value = ZFS_ACLTYPE_NFSV4;
|
||||||
|
#else
|
||||||
|
*value = ZFS_ACLTYPE_OFF;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If one of the methods for getting the property value above worked,
|
||||||
|
* copy it into the objset_t's cache.
|
||||||
|
*/
|
||||||
|
if (error == 0 && cached_copy != NULL) {
|
||||||
|
*cached_copy = *value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
Loading…
Reference in New Issue