Skip to content

Commit

Permalink
Merge pull request #152 from truenas/truenas/zfs-2.1-release
Browse files Browse the repository at this point in the history
Sync stable/bluefin with truenas/zfs-2.1-release
  • Loading branch information
amotin committed Jul 25, 2023
2 parents 4b88096 + 62ffa8d commit 41aa15f
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 110 deletions.
36 changes: 31 additions & 5 deletions config/kernel-inode-permission.m4
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [
dnl #
dnl # 6.3 API change
dnl # iops->permission() now takes struct mnt_idmap*
dnl # as its first arg
dnl #
ZFS_LINUX_TEST_SRC([permission_mnt_idmap], [
#include <linux/fs.h>
#include <linux/sched.h>
int inode_permission(struct mnt_idmap *idmap,
struct inode *inode, int mask) { return 0; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.permission = inode_permission,
};
],[])
dnl #
dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list.
Expand All @@ -18,12 +36,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [
])

AC_DEFUN([ZFS_AC_KERNEL_PERMISSION], [
AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*])
ZFS_LINUX_TEST_RESULT([permission_userns], [
AC_MSG_CHECKING([whether iops->permission() takes struct mnt_idmap*])
ZFS_LINUX_TEST_RESULT([permission_mnt_idmap], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1,
[iops->permission() takes struct user_namespace*])
AC_DEFINE(HAVE_IOPS_PERMISSION_IDMAP, 1,
[iops->permission() takes struct mnt_idmap*])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*])
ZFS_LINUX_TEST_RESULT([permission_userns], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1,
[iops->permission() takes struct user_namespace*])
],[
AC_MSG_RESULT(no)
])
])
])

2 changes: 2 additions & 0 deletions include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ zpl_chmod_acl(struct inode *ip)
#if defined(HAVE_IOPS_PERMISSION_USERNS)
extern int zpl_permission(struct user_namespace *userns, struct inode *ip,
int mask);
#elif defined(HAVE_IOPS_PERMISSION_IDMAP)
extern int zpl_permission(struct mnt_idmap *idmap, struct inode *ip, int mask);
#else
extern int zpl_permission(struct inode *ip, int mask);
#endif
Expand Down
1 change: 1 addition & 0 deletions include/sys/spa_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ struct spa {
uint64_t spa_min_ashift; /* of vdevs in normal class */
uint64_t spa_max_ashift; /* of vdevs in normal class */
uint64_t spa_min_alloc; /* of vdevs in normal class */
uint64_t spa_gcd_alloc; /* of vdevs in normal class */
uint64_t spa_config_guid; /* config pool guid */
uint64_t spa_load_guid; /* spa_load initialized guid */
uint64_t spa_last_synced_guid; /* last synced guid */
Expand Down
1 change: 1 addition & 0 deletions include/sys/vdev_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ struct vdev {
boolean_t vdev_copy_uberblocks; /* post expand copy uberblocks */
boolean_t vdev_resilver_deferred; /* resilver deferred */
boolean_t vdev_kobj_flag; /* kobj event record */
boolean_t vdev_attaching; /* vdev attach ashift handling */
vdev_queue_t vdev_queue; /* I/O deadline schedule queue */
vdev_cache_t vdev_cache; /* physical block cache */
spa_aux_vdev_t *vdev_aux; /* for l2cache and spares vdevs */
Expand Down
2 changes: 1 addition & 1 deletion module/os/linux/zfs/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner,
if ((fsuid == owner) || (fsuid == 0))
return (0);

if (zpl_inode_owner_or_capable(kcred->user_ns, ip))
if (zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (0);

#if defined(CONFIG_USER_NS)
Expand Down
5 changes: 3 additions & 2 deletions module/os/linux/zfs/zfs_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2543,8 +2543,9 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr)
return (unmapped ? SET_ERROR(EPERM) : 0);
}

#if defined(HAVE_IOPS_PERMISSION_USERNS)
err = generic_permission(cr->user_ns, ZTOI(zp), mask);
#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \
defined(HAVE_IOPS_PERMISSION_IDMAP))
err = generic_permission(zfs_init_idmap, ZTOI(zp), mask);
#else
err = generic_permission(ZTOI(zp), mask);
#endif
Expand Down
2 changes: 1 addition & 1 deletion module/os/linux/zfs/zpl_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ __zpl_ioctl_setdosflags(struct inode *ip, uint64_t ioctl_flags, xvattr_t *xva)
!capable(CAP_LINUX_IMMUTABLE))
return (-EPERM);

if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (-EACCES);

xva_init(xva);
Expand Down
12 changes: 8 additions & 4 deletions module/os/linux/zfs/zpl_xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,8 @@ xattr_handler_t zpl_xattr_acl_default_handler =
int
#if defined(HAVE_IOPS_PERMISSION_USERNS)
zpl_permission(struct user_namespace *userns, struct inode *ip, int mask)
#elif defined(HAVE_IOPS_PERMISSION_IDMAP)
zpl_permission(struct mnt_idmap *idmap, struct inode *ip, int mask)
#else
zpl_permission(struct inode *ip, int mask)
#endif
Expand All @@ -1513,8 +1515,9 @@ zpl_permission(struct inode *ip, int mask)
*/
if ((ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_NFSV4) ||
((ITOZ(ip)->z_pflags & ZFS_ACL_TRIVIAL && GENERIC_MASK(mask)))) {
#if defined(HAVE_IOPS_PERMISSION_USERNS)
return (generic_permission(userns, ip, mask));
#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \
defined(HAVE_IOPS_PERMISSION_IDMAP))
return (generic_permission(zfs_init_idmap, ip, mask));
#else
return (generic_permission(ip, mask));
#endif
Expand All @@ -1531,8 +1534,9 @@ zpl_permission(struct inode *ip, int mask)
* NFSv4 ACE. Pass back to default kernel permissions check.
*/
if (to_check == 0) {
#if defined(HAVE_IOPS_PERMISSION_USERNS)
return (generic_permission(userns, ip, mask));
#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \
defined(HAVE_IOPS_PERMISSION_IDMAP))
return (generic_permission(zfs_init_idmap, ip, mask));
#else
return (generic_permission(ip, mask));
#endif
Expand Down
1 change: 1 addition & 0 deletions module/zfs/spa_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
spa->spa_min_ashift = INT_MAX;
spa->spa_max_ashift = 0;
spa->spa_min_alloc = INT_MAX;
spa->spa_gcd_alloc = INT_MAX;

/* Reset cached value */
spa->spa_dedup_dspace = ~0ULL;
Expand Down
50 changes: 42 additions & 8 deletions module/zfs/vdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,9 +854,15 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
&vd->vdev_not_present);

/*
* Get the alignment requirement.
* Get the alignment requirement. Ignore pool ashift for vdev
* attach case.
*/
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT, &vd->vdev_ashift);
if (alloctype != VDEV_ALLOC_ATTACH) {
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT,
&vd->vdev_ashift);
} else {
vd->vdev_attaching = B_TRUE;
}

/*
* Retrieve the vdev creation time.
Expand Down Expand Up @@ -1345,6 +1351,36 @@ vdev_remove_parent(vdev_t *cvd)
vdev_free(mvd);
}

/*
* Choose GCD for spa_gcd_alloc.
*/
static uint64_t
vdev_gcd(uint64_t a, uint64_t b)
{
while (b != 0) {
uint64_t t = b;
b = a % b;
a = t;
}
return (a);
}

/*
* Set spa_min_alloc and spa_gcd_alloc.
*/
static void
vdev_spa_set_alloc(spa_t *spa, uint64_t min_alloc)
{
if (min_alloc < spa->spa_min_alloc)
spa->spa_min_alloc = min_alloc;
if (spa->spa_gcd_alloc == INT_MAX) {
spa->spa_gcd_alloc = min_alloc;
} else {
spa->spa_gcd_alloc = vdev_gcd(min_alloc,
spa->spa_gcd_alloc);
}
}

void
vdev_metaslab_group_create(vdev_t *vd)
{
Expand Down Expand Up @@ -1397,8 +1433,7 @@ vdev_metaslab_group_create(vdev_t *vd)
spa->spa_min_ashift = vd->vdev_ashift;

uint64_t min_alloc = vdev_get_min_alloc(vd);
if (min_alloc < spa->spa_min_alloc)
spa->spa_min_alloc = min_alloc;
vdev_spa_set_alloc(spa, min_alloc);
}
}
}
Expand Down Expand Up @@ -2093,9 +2128,9 @@ vdev_open(vdev_t *vd)
return (SET_ERROR(EDOM));
}

if (vd->vdev_top == vd) {
if (vd->vdev_top == vd && vd->vdev_attaching == B_FALSE)
vdev_ashift_optimize(vd);
}
vd->vdev_attaching = B_FALSE;
}
if (vd->vdev_ashift != 0 && (vd->vdev_ashift < ASHIFT_MIN ||
vd->vdev_ashift > ASHIFT_MAX)) {
Expand Down Expand Up @@ -2156,8 +2191,7 @@ vdev_open(vdev_t *vd)
if (vd->vdev_top == vd && vd->vdev_ashift != 0 &&
vd->vdev_islog == 0 && vd->vdev_aux == NULL) {
uint64_t min_alloc = vdev_get_min_alloc(vd);
if (min_alloc < spa->spa_min_alloc)
spa->spa_min_alloc = min_alloc;
vdev_spa_set_alloc(spa, min_alloc);
}

/*
Expand Down
22 changes: 17 additions & 5 deletions module/zfs/zio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,19 @@ zio_shrink(zio_t *zio, uint64_t size)
}
}

/*
* Round provided allocation size up to a value that can be allocated
* by at least some vdev(s) in the pool with minimum or no additional
* padding and without extra space usage on others
*/
static uint64_t
zio_roundup_alloc_size(spa_t *spa, uint64_t size)
{
if (size > spa->spa_min_alloc)
return (roundup(size, spa->spa_gcd_alloc));
return (spa->spa_min_alloc);
}

/*
* ==========================================================================
* Prepare to read and write logical blocks
Expand Down Expand Up @@ -1735,9 +1748,8 @@ zio_write_compress(zio_t *zio)
* in that we charge for the padding used to fill out
* the last sector.
*/
ASSERT3U(spa->spa_min_alloc, >=, SPA_MINBLOCKSHIFT);
size_t rounded = (size_t)roundup(psize,
spa->spa_min_alloc);
size_t rounded = (size_t)zio_roundup_alloc_size(spa,
psize);
if (rounded >= lsize) {
compress = ZIO_COMPRESS_OFF;
zio_buf_free(cbuf, lsize);
Expand Down Expand Up @@ -1780,8 +1792,8 @@ zio_write_compress(zio_t *zio)
* take this codepath because it will change the on-disk block
* and decryption will fail.
*/
size_t rounded = MIN((size_t)roundup(psize,
spa->spa_min_alloc), lsize);
size_t rounded = MIN((size_t)zio_roundup_alloc_size(spa, psize),
lsize);

if (rounded != psize) {
abd_t *cdata = abd_alloc_linear(rounded, B_TRUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,35 +66,14 @@ log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
do
for cmdval in ${ashifts[@]}
do
log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
verify_ashift $disk1 $ashift
if [[ $? -ne 0 ]]
then
log_fail "Pool was created without setting ashift " \
"value to $ashift"
fi
# ashift_of(attached_disk) <= ashift_of(existing_vdev)
if [[ $cmdval -le $ashift ]]
then
log_must zpool attach -o ashift=$cmdval $TESTPOOL1 \
$disk1 $disk2
verify_ashift $disk2 $ashift
if [[ $? -ne 0 ]]
then
log_fail "Device was attached without " \
"setting ashift value to $ashift"
fi
else
log_mustnot zpool attach -o ashift=$cmdval $TESTPOOL1 \
$disk1 $disk2
fi
# clean things for the next run
log_must zpool destroy $TESTPOOL1
log_must zpool labelclear $disk1
log_must zpool labelclear $disk2
done
log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
log_must verify_ashift $disk1 $ashift
log_must zpool attach $TESTPOOL1 $disk1 $disk2
log_must verify_ashift $disk2 $ashift
# clean things for the next run
log_must zpool destroy $TESTPOOL1
log_must zpool labelclear $disk1
log_must zpool labelclear $disk2
done

typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,36 +66,16 @@ log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
do
for cmdval in ${ashifts[@]}
do
log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
verify_ashift $disk1 $ashift
if [[ $? -ne 0 ]]
then
log_fail "Pool was created without setting ashift " \
"value to $ashift"
fi
# ashift_of(replacing_disk) <= ashift_of(existing_vdev)
if [[ $cmdval -le $ashift ]]
then
log_must zpool replace -o ashift=$cmdval $TESTPOOL1 \
$disk1 $disk2
verify_ashift $disk2 $ashift
if [[ $? -ne 0 ]]
then
log_fail "Device was replaced without " \
"setting ashift value to $ashift"
fi
wait_replacing $TESTPOOL1
else
log_mustnot zpool replace -o ashift=$cmdval $TESTPOOL1 \
$disk1 $disk2
fi
# clean things for the next run
log_must zpool destroy $TESTPOOL1
log_must zpool labelclear $disk1
log_must zpool labelclear $disk2
done
log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
log_must verify_ashift $disk1 $ashift
# ashift_of(replacing_disk) <= ashift_of(existing_vdev)
log_must zpool replace $TESTPOOL1 $disk1 $disk2
log_must verify_ashift $disk2 $ashift
wait_replacing $TESTPOOL1
# clean things for the next run
log_must zpool destroy $TESTPOOL1
log_must zpool labelclear $disk1
log_must zpool labelclear $disk2
done

typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
Expand Down
Loading

0 comments on commit 41aa15f

Please sign in to comment.