From nobody Wed Dec 28 22:43:54 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Nj6566cXYz2cDNH; Wed, 28 Dec 2022 22:43:54 +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 4Nj65660nCz3Jyx; Wed, 28 Dec 2022 22:43:54 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1672267434; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=k3Yj3OGwjnOkbojGLBB+zPTbxeldbazEM/IoQYOUSHw=; b=AsUlltExeV2HzkJrI7y9h4BVoUytgnNPvIkbevoa++X4ffMypFU7LfJ02c9bvqs9KW4jrd OGBof8ugObfa4J/oak8Jzrpn+9yUu9zrcyrLW/uxrnKD0HalP0JmJP9GXEUGfKNBKUgSS5 Cf8rfnTtxqY4WioVN+mXyUcObwUqTp+KdaoRe3qp3kI27Uj6IMfF995G+L4uraSyrdHrye J6Ni8IZRLABqbZsCAb6NzYXKN1NGCHyYQjPwxuBoNsL0vZhXStfgnRfKaDz6NYSGYnubXz eu1IMOGE1OwTLoRc6zXeTq+o3J0WbmDxAhtmyKXEoR0g9ZPblOXyJ85PZpvhMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1672267434; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=k3Yj3OGwjnOkbojGLBB+zPTbxeldbazEM/IoQYOUSHw=; b=ijYbXS7nAPvExUD4qGhlcRbSbNeJhzUZQ1Y4n5SGduht1rLqiPuDSDkGsvFmMcjh/yiy5D bLRkwwkqKn2TkN2x27DmC4QMvgeVjgs/Hg0oBg6uFQbuY0hvGT+aI+ChM8/uTG/IZxrSza qUaMtDPiZiEkh7MY2Y6HqaO1f1tNvW35WoiqRn3B5HemOBhjHTNpM+oIfu70Jov1k5cCY5 OiI3r3Et9jW8ryJ2KyG1+smzPEzCuqsSQ1cl6OoJ9b5YsyEcUvNouxlG13jB3+MH9S2bKQ zWfBY9YasNYjzCO9G2q3Tq17+1HzseFScXetjRG3pZCMZAjoziv8WqcJJa0PfA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1672267434; a=rsa-sha256; cv=none; b=dDJ9pU7yLoi0f6T2P0hJDJEE1ukSDIEzhn8Hg57jYb1JlLvRQND5/jRvjQ7dNYeKHdjODR ZDl0V9P93FtCxHHdMjrrJJPEse0behK0a8qrnFPh+i2dqcVQe9b6XF3dsXRxYptMukpR0a 7u1f7nGANVeQ8tTLYeTLwv65aVAG5dMYPgcAUABqpL1Ut5y0uqS/BoteKFEGGQeIYnd1/T HILnUUopZdTPyDGZQU4PHa5f8vYjqJGruf+0s9E9Gn2LQ3oGXLFnhyqiH0vKZ57AuqeBto hGHQRS2hC7gCUXmOofmYtSRM7dZ0LaJqSaTK26rmlXtH82c3FtD8+ekUOFDGHw== 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 4Nj65653yFz160H; Wed, 28 Dec 2022 22:43:54 +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 2BSMhsmL040686; Wed, 28 Dec 2022 22:43:54 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2BSMhsbr040685; Wed, 28 Dec 2022 22:43:54 GMT (envelope-from git) Date: Wed, 28 Dec 2022 22:43:54 GMT Message-Id: <202212282243.2BSMhsbr040685@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: f45feecfb27c - main - vfs: add vn_getsize List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org 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: f45feecfb27ca51067d6789eaa43547cadc4990b Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=f45feecfb27ca51067d6789eaa43547cadc4990b commit f45feecfb27ca51067d6789eaa43547cadc4990b Author: Mateusz Guzik AuthorDate: 2022-09-22 13:55:49 +0000 Commit: Mateusz Guzik CommitDate: 2022-12-28 22:43:49 +0000 vfs: add vn_getsize getattr is very expensive and in important cases only gets called to get the size. This can be optimized with a dedicated routine which obtains that statistic. As a step towards that goal make size-only consumers use a dedicated routine. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D37885 --- sys/kern/kern_sendfile.c | 4 +-- sys/kern/vfs_subr.c | 30 +++++++++++++++++++--- sys/kern/vfs_vnops.c | 66 ++++++++++++++++++++++-------------------------- sys/sys/vnode.h | 2 ++ sys/vm/vnode_pager.c | 4 +-- 5 files changed, 61 insertions(+), 45 deletions(-) diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c index 96f95e4c841f..12842e3476e1 100644 --- a/sys/kern/kern_sendfile.c +++ b/sys/kern/kern_sendfile.c @@ -563,7 +563,6 @@ sendfile_getobj(struct thread *td, struct file *fp, vm_object_t *obj_res, struct vnode **vp_res, struct shmfd **shmfd_res, off_t *obj_size, int *bsize) { - struct vattr va; vm_object_t obj; struct vnode *vp; struct shmfd *shmfd; @@ -602,10 +601,9 @@ sendfile_getobj(struct thread *td, struct file *fp, vm_object_t *obj_res, VM_OBJECT_RLOCK(obj); *obj_size = obj->un_pager.vnp.vnp_size; } else { - error = VOP_GETATTR(vp, &va, td->td_ucred); + error = vn_getsize_locked(vp, obj_size, td->td_ucred); if (error != 0) goto out; - *obj_size = va.va_size; VM_OBJECT_RLOCK(obj); } } else if (fp->f_type == DTYPE_SHM) { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index b3f12bb52928..d49f97a7060e 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -6377,7 +6377,7 @@ static int filt_vfsread(struct knote *kn, long hint) { struct vnode *vp = (struct vnode *)kn->kn_hook; - struct vattr va; + off_t size; int res; /* @@ -6391,11 +6391,11 @@ filt_vfsread(struct knote *kn, long hint) return (1); } - if (VOP_GETATTR(vp, &va, curthread->td_ucred)) + if (vn_getsize_locked(vp, &size, curthread->td_ucred) != 0) return (0); VI_LOCK(vp); - kn->kn_data = va.va_size - kn->kn_fp->f_offset; + kn->kn_data = size - kn->kn_fp->f_offset; res = (kn->kn_sfflags & NOTE_FILE_POLL) != 0 || kn->kn_data != 0; VI_UNLOCK(vp); return (res); @@ -7116,6 +7116,30 @@ vn_irflag_unset(struct vnode *vp, short tounset) VI_UNLOCK(vp); } +int +vn_getsize_locked(struct vnode *vp, off_t *size, struct ucred *cred) +{ + struct vattr vattr; + int error; + + ASSERT_VOP_LOCKED(vp, __func__); + error = VOP_GETATTR(vp, &vattr, cred); + if (__predict_true(error == 0)) + *size = vattr.va_size; + return (error); +} + +int +vn_getsize(struct vnode *vp, off_t *size, struct ucred *cred) +{ + int error; + + VOP_LOCK(vp, LK_SHARED); + error = vn_getsize_locked(vp, size, cred); + VOP_UNLOCK(vp); + return (error); +} + #ifdef INVARIANTS void vn_set_state_validate(struct vnode *vp, enum vstate state) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 4d8963100a43..f3a6360eb250 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1690,9 +1690,9 @@ static int vn_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, struct thread *td) { - struct vattr vattr; struct vnode *vp; struct fiobmap2_arg *bmarg; + off_t size; int error; vp = fp->f_vnode; @@ -1701,11 +1701,9 @@ vn_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, case VREG: switch (com) { case FIONREAD: - vn_lock(vp, LK_SHARED | LK_RETRY); - error = VOP_GETATTR(vp, &vattr, active_cred); - VOP_UNLOCK(vp); + error = vn_getsize(vp, &size, active_cred); if (error == 0) - *(int *)data = vattr.va_size - fp->f_offset; + *(int *)data = size - fp->f_offset; return (error); case FIOBMAP2: bmarg = (struct fiobmap2_arg *)data; @@ -2558,7 +2556,7 @@ int vn_bmap_seekhole_locked(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred) { - struct vattr va; + off_t size; daddr_t bn, bnp; uint64_t bsize; off_t noff; @@ -2572,16 +2570,16 @@ vn_bmap_seekhole_locked(struct vnode *vp, u_long cmd, off_t *off, error = ENOTTY; goto out; } - error = VOP_GETATTR(vp, &va, cred); + error = vn_getsize_locked(vp, &size, cred); if (error != 0) goto out; noff = *off; - if (noff < 0 || noff >= va.va_size) { + if (noff < 0 || noff >= size) { error = ENXIO; goto out; } bsize = vp->v_mount->mnt_stat.f_iosize; - for (bn = noff / bsize; noff < va.va_size; bn++, noff += bsize - + for (bn = noff / bsize; noff < size; bn++, noff += bsize - noff % bsize) { error = VOP_BMAP(vp, bn, NULL, &bnp, NULL, NULL); if (error == EOPNOTSUPP) { @@ -2596,9 +2594,9 @@ vn_bmap_seekhole_locked(struct vnode *vp, u_long cmd, off_t *off, goto out; } } - if (noff > va.va_size) - noff = va.va_size; - /* noff == va.va_size. There is an implicit hole at the end of file. */ + if (noff > size) + noff = size; + /* noff == size. There is an implicit hole at the end of file. */ if (cmd == FIOSEEKDATA) error = ENXIO; out: @@ -2627,8 +2625,7 @@ vn_seek(struct file *fp, off_t offset, int whence, struct thread *td) { struct ucred *cred; struct vnode *vp; - struct vattr vattr; - off_t foffset, size; + off_t foffset, fsize, size; int error, noneg; cred = td->td_ucred; @@ -2647,10 +2644,8 @@ vn_seek(struct file *fp, off_t offset, int whence, struct thread *td) offset += foffset; break; case L_XTND: - vn_lock(vp, LK_SHARED | LK_RETRY); - error = VOP_GETATTR(vp, &vattr, cred); - VOP_UNLOCK(vp); - if (error) + error = vn_getsize(vp, &fsize, cred); + if (error != 0) break; /* @@ -2658,16 +2653,16 @@ vn_seek(struct file *fp, off_t offset, int whence, struct thread *td) * the media size and use that to determine the ending * offset. */ - if (vattr.va_size == 0 && vp->v_type == VCHR && + if (fsize == 0 && vp->v_type == VCHR && fo_ioctl(fp, DIOCGMEDIASIZE, &size, cred, td) == 0) - vattr.va_size = size; + fsize = size; if (noneg && - (vattr.va_size > OFF_MAX || - (offset > 0 && vattr.va_size > OFF_MAX - offset))) { + (fsize > OFF_MAX || + (offset > 0 && fsize > OFF_MAX - offset))) { error = EOVERFLOW; break; } - offset += vattr.va_size; + offset += fsize; break; case L_SET: break; @@ -3259,7 +3254,6 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp, off_t *outoffp, size_t *lenp, unsigned int flags, struct ucred *incred, struct ucred *outcred, struct thread *fsize_td) { - struct vattr va, inva; struct mount *mp; off_t startoff, endoff, xfer, xfer2; u_long blksize; @@ -3267,6 +3261,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, bool cantseek, readzeros, eof, lastblock, holetoeof; ssize_t aresid, r = 0; size_t copylen, len, savlen; + off_t insize, outsize; char *dat; long holein, holeout; struct timespec curts, endts; @@ -3283,7 +3278,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, if (VOP_PATHCONF(invp, _PC_MIN_HOLE_SIZE, &holein) != 0) holein = 0; if (holein > 0) - error = VOP_GETATTR(invp, &inva, incred); + error = vn_getsize_locked(invp, &insize, incred); VOP_UNLOCK(invp); if (error != 0) goto out; @@ -3314,13 +3309,12 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, /* * Holes that are past EOF do not need to be written as a block * of zero bytes. So, truncate the output file as far as - * possible and then use va.va_size to decide if writing 0 + * possible and then use size to decide if writing 0 * bytes is necessary in the loop below. */ if (error == 0) - error = VOP_GETATTR(outvp, &va, outcred); - if (error == 0 && va.va_size > *outoffp && va.va_size <= - *outoffp + len) { + error = vn_getsize_locked(outvp, &outsize, outcred); + if (error == 0 && outsize > *outoffp && outsize <= *outoffp + len) { #ifdef MAC error = mac_vnode_check_write(curthread->td_ucred, outcred, outvp); @@ -3329,7 +3323,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, error = vn_truncate_locked(outvp, *outoffp, false, outcred); if (error == 0) - va.va_size = *outoffp; + outsize = *outoffp; } VOP_UNLOCK(outvp); } @@ -3409,7 +3403,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, error = VOP_IOCTL(invp, FIOSEEKDATA, &startoff, 0, incred, curthread); if (error == ENXIO) { - startoff = endoff = inva.va_size; + startoff = endoff = insize; eof = holetoeof = true; error = 0; } @@ -3434,9 +3428,9 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, if (startoff > *inoffp) { /* Found hole before data block. */ xfer = MIN(startoff - *inoffp, len); - if (*outoffp < va.va_size) { + if (*outoffp < outsize) { /* Must write 0s to punch hole. */ - xfer2 = MIN(va.va_size - *outoffp, + xfer2 = MIN(outsize - *outoffp, xfer); memset(dat, 0, MIN(xfer2, blksize)); error = vn_write_outvp(outvp, dat, @@ -3445,7 +3439,7 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, } if (error == 0 && *outoffp + xfer > - va.va_size && (xfer == len || holetoeof)) { + outsize && (xfer == len || holetoeof)) { /* Grow output file (hole at end). */ error = vn_write_outvp(outvp, dat, *outoffp, xfer, blksize, true, @@ -3515,12 +3509,12 @@ vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, false; if (xfer == len) lastblock = true; - if (!cantseek || *outoffp < va.va_size || + if (!cantseek || *outoffp < outsize || lastblock || !readzeros) error = vn_write_outvp(outvp, dat, *outoffp, xfer, blksize, readzeros && lastblock && - *outoffp >= va.va_size, false, + *outoffp >= outsize, false, outcred); if (error == 0) { *inoffp += xfer; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index b3e67f6dcf31..04596a7184ee 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1135,6 +1135,8 @@ int vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred, struct thread *td); int vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred, struct thread *td); +int vn_getsize_locked(struct vnode *vp, off_t *size, struct ucred *active_cred); +int vn_getsize(struct vnode *vp, off_t *size, struct ucred *active_cred); void vn_fsid(struct vnode *vp, struct vattr *va); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index c9917ecc2589..56caf75d7f90 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -155,7 +155,6 @@ vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td) { vm_object_t object; vm_ooffset_t size = isize; - struct vattr va; bool last; if (!vn_isdisk(vp) && vn_canvmio(vp) == FALSE) @@ -169,9 +168,8 @@ vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td) if (vn_isdisk(vp)) { size = IDX_TO_OFF(INT_MAX); } else { - if (VOP_GETATTR(vp, &va, td->td_ucred)) + if (vn_getsize_locked(vp, &size, td->td_ucred) != 0) return (0); - size = va.va_size; } }