From owner-dev-commits-src-main@freebsd.org Sat Jan 23 15:05:00 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id D0AAB4F58A3; Sat, 23 Jan 2021 15:05:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DNKDX48FDz4Z2d; Sat, 23 Jan 2021 15:05:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 18865133E4; Sat, 23 Jan 2021 15:05:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 10NF5000076451; Sat, 23 Jan 2021 15:05:00 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 10NF50Ko076450; Sat, 23 Jan 2021 15:05:00 GMT (envelope-from git) Date: Sat, 23 Jan 2021 15:05:00 GMT Message-Id: <202101231505.10NF50Ko076450@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mateusz Guzik Subject: git: 3110d4ebd6c0 - main - zfs: add support for lockless symlink lookup MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mjg X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 3110d4ebd6c0848cf5e25890d01791bb407e2a9b Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Jan 2021 15:05:01 -0000 The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=3110d4ebd6c0848cf5e25890d01791bb407e2a9b commit 3110d4ebd6c0848cf5e25890d01791bb407e2a9b Author: Mateusz Guzik AuthorDate: 2021-01-23 13:46:32 +0000 Commit: Mateusz Guzik CommitDate: 2021-01-23 15:04:43 +0000 zfs: add support for lockless symlink lookup Reviewed by: kib (previous version) Tested by: pho (previous version) Differential Revision: https://reviews.freebsd.org/D27488 --- .../include/os/freebsd/zfs/sys/zfs_znode_impl.h | 1 + .../openzfs/module/os/freebsd/zfs/zfs_vnops_os.c | 81 +++++++++++++++++++++- .../openzfs/module/os/freebsd/zfs/zfs_znode.c | 7 ++ 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h index ac2625d9a8ab..091186f23174 100644 --- a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h +++ b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h @@ -53,6 +53,7 @@ extern "C" { #define ZNODE_OS_FIELDS \ struct zfsvfs *z_zfsvfs; \ vnode_t *z_vnode; \ + char *z_cached_symlink; \ uint64_t z_uid; \ uint64_t z_gid; \ uint64_t z_gen; \ diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c index 2e8eadb5e16e..365c64a9479c 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c @@ -4463,6 +4463,31 @@ zfs_freebsd_fplookup_vexec(struct vop_fplookup_vexec_args *v) } #endif +#if __FreeBSD_version >= 1400001 +static int +zfs_freebsd_fplookup_symlink(struct vop_fplookup_symlink_args *v) +{ + vnode_t *vp; + znode_t *zp; + char *target; + + vp = v->a_vp; + zp = VTOZ_SMR(vp); + if (__predict_false(zp == NULL)) { + return (EAGAIN); + } + + /* + * FIXME: Load consume would be sufficient but there is no primitive to do it. + */ + target = (char *)atomic_load_acq_ptr((uintptr_t *)&zp->z_cached_symlink); + if (target == NULL) { + return (EAGAIN); + } + return (cache_symlink_resolve(v->a_fpl, target, strlen(target))); +} +#endif + #ifndef _SYS_SYSPROTO_H_ struct vop_access_args { struct vnode *a_vp; @@ -4949,6 +4974,8 @@ zfs_freebsd_symlink(struct vop_symlink_args *ap) struct componentname *cnp = ap->a_cnp; vattr_t *vap = ap->a_vap; znode_t *zp = NULL; + char *symlink; + size_t symlink_len; int rc; ASSERT(cnp->cn_flags & SAVENAME); @@ -4959,8 +4986,19 @@ zfs_freebsd_symlink(struct vop_symlink_args *ap) rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, ap->a_target, &zp, cnp->cn_cred, 0 /* flags */); - if (rc == 0) + if (rc == 0) { *ap->a_vpp = ZTOV(zp); + ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); + MPASS(zp->z_cached_symlink == NULL); + symlink_len = strlen(ap->a_target); + symlink = cache_symlink_alloc(symlink_len + 1, M_WAITOK); + if (symlink != NULL) { + memcpy(symlink, ap->a_target, symlink_len); + symlink[symlink_len] = '\0'; + atomic_store_rel_ptr((uintptr_t *)&zp->z_cached_symlink, + (uintptr_t)symlink); + } + } return (rc); } @@ -4975,8 +5013,36 @@ struct vop_readlink_args { static int zfs_freebsd_readlink(struct vop_readlink_args *ap) { - - return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred, NULL)); + znode_t *zp = VTOZ(ap->a_vp); + struct uio *auio; + char *symlink, *base; + size_t symlink_len; + int error; + bool trycache; + + auio = ap->a_uio; + trycache = false; + if (auio->uio_segflg == UIO_SYSSPACE && auio->uio_iovcnt == 1) { + base = auio->uio_iov->iov_base; + symlink_len = auio->uio_iov->iov_len; + trycache = true; + } + error = zfs_readlink(ap->a_vp, auio, ap->a_cred, NULL); + if (atomic_load_ptr(&zp->z_cached_symlink) != NULL || + error != 0 || !trycache) { + return (error); + } + symlink_len -= auio->uio_resid; + symlink = cache_symlink_alloc(symlink_len + 1, M_WAITOK); + if (symlink != NULL) { + memcpy(symlink, base, symlink_len); + symlink[symlink_len] = '\0'; + if (!atomic_cmpset_rel_ptr((uintptr_t *)&zp->z_cached_symlink, + (uintptr_t)NULL, (uintptr_t)symlink)) { + cache_symlink_free(symlink, symlink_len + 1); + } + } + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -5733,6 +5799,9 @@ struct vop_vector zfs_vnodeops = { .vop_reclaim = zfs_freebsd_reclaim, #if __FreeBSD_version >= 1300102 .vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, +#endif +#if __FreeBSD_version >= 1400001 + .vop_fplookup_symlink = zfs_freebsd_fplookup_symlink, #endif .vop_access = zfs_freebsd_access, .vop_allocate = VOP_EINVAL, @@ -5782,6 +5851,9 @@ struct vop_vector zfs_fifoops = { .vop_fsync = zfs_freebsd_fsync, #if __FreeBSD_version >= 1300102 .vop_fplookup_vexec = zfs_freebsd_fplookup_vexec, +#endif +#if __FreeBSD_version >= 1400001 + .vop_fplookup_symlink = zfs_freebsd_fplookup_symlink, #endif .vop_access = zfs_freebsd_access, .vop_getattr = zfs_freebsd_getattr, @@ -5805,6 +5877,9 @@ struct vop_vector zfs_shareops = { .vop_default = &default_vnodeops, #if __FreeBSD_version >= 1300121 .vop_fplookup_vexec = VOP_EAGAIN, +#endif +#if __FreeBSD_version >= 1400001 + .vop_fplookup_symlink = VOP_EAGAIN, #endif .vop_access = zfs_freebsd_access, .vop_inactive = zfs_freebsd_inactive, diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c index 6a21623c5f67..f9a0820eda2d 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c @@ -444,6 +444,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, zp->z_blksz = blksz; zp->z_seq = 0x7A4653; zp->z_sync_cnt = 0; + atomic_store_ptr((uintptr_t *)&zp->z_cached_symlink, (uintptr_t)NULL); vp = ZTOV(zp); @@ -1237,6 +1238,7 @@ void zfs_znode_free(znode_t *zp) { zfsvfs_t *zfsvfs = zp->z_zfsvfs; + char *symlink; ASSERT(zp->z_sa_hdl == NULL); zp->z_vnode = NULL; @@ -1245,6 +1247,11 @@ zfs_znode_free(znode_t *zp) list_remove(&zfsvfs->z_all_znodes, zp); zfsvfs->z_nr_znodes--; mutex_exit(&zfsvfs->z_znodes_lock); + symlink = atomic_load_ptr(&zp->z_cached_symlink); + if (symlink != NULL) { + atomic_store_rel_ptr((uintptr_t *)&zp->z_cached_symlink, (uintptr_t)NULL); + cache_symlink_free(symlink, strlen(symlink) + 1); + } if (zp->z_acl_cached) { zfs_acl_free(zp->z_acl_cached);