From nobody Fri Sep 19 14:19:53 2025 X-Original-To: dev-commits-src-all@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 4cSvls2B92z684pL; Fri, 19 Sep 2025 14:19:53 +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 "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cSvls1gzCz3q8V; Fri, 19 Sep 2025 14:19:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1758291593; 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=09vurr1oVbYViJ7bPh2QrocXGF5nVuH8aSeU2reWgFk=; b=O1D76D47lkBs1/vGHb6TFQn9DfC2nIjxS0dEcpKhpLyAWIshUslbm3EfClqT2/HdbQVcaR /JkkUp6aVWpk+XKYqmX68zKqUPB9329eyHXK2CjE4AwN50afO72hcq8Pio+nYxr/nCHL5p Fl3Sdrj+GFT+sttSUSTKBSDHfoL8kPOZYAitLdVUjcqgc7tt/PS4KgWgKG27ffMkFHglPX hF5B8orqNM7ksdhwxYSQ3gJU6sNNz6KT8XopPtKf+5bORfs4ZSWSxREOrCx+T7392OCpxr 5lfDG/96KpXedQen6ZC7wOsVx51vhzc+8PQphoqbj3OUWau+DjUCzqBXllVnBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1758291593; 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=09vurr1oVbYViJ7bPh2QrocXGF5nVuH8aSeU2reWgFk=; b=uF2rJNtTdpasNws4U1q6aRBOm3f5DVdS7HivOxaIpli9XyAxKCQ18eigbr9hT5fqjfztO5 bguZe1MhqYsUVgORKgiwPYmdOJoFkmOlzFMrkpWwzscIXKVaq55pWqZ7V6nU1agNU28Xpu QxyPQwqB02o0BE1JuU0GPLrw6SCStkB6JKKN27Uzu9PqOj6PEJ0s1Qi1okL3JVy+mLzr9Y HWoHCOCGuSP9Ig+T59USadT82a0OEfSILt0DVGV9BONPIs4vGL62OZc9fKzzMMxAdZmto1 OGta+Gyz7P9TDNCUT4KDbodPCN0w7IvGWmBXDjde6mmwP32VNOVAr4kjMtstew== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1758291593; a=rsa-sha256; cv=none; b=sbaA3W0CNQpfRRtltFrdfgRM3OOQvMqKrgjqCqhPldgQbJhG23Rcau09nC468rPhHr1RIL QEP18FLlLL+boSEZWdua1IniHovXdkhR5pFlPhGpcJooRfIUn3KeT5Xs/HWx1ldL9Be7xp os7Pk24NmMQOyGODm9ZoNkhYah+Dhfqdh49PXV9zFC1Y7adUXeEx3YPBuNTaCEOCFugb/Q jZIZ71D4tGCSXKO7Uv0/k2wND92uLwW7hIDS8ow7dJqKO/bgEUzBqf+7HysnjvK63o7Tjd PIddtAOVezISvD/liozrZ9T5PhbzttzAK1wU8iYxeUUad3jQgInJR7iaosVlAA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none 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 4cSvls19hFz11Hm; Fri, 19 Sep 2025 14:19:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 58JEJr33031835; Fri, 19 Sep 2025 14:19:53 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 58JEJrSZ031832; Fri, 19 Sep 2025 14:19:53 GMT (envelope-from git) Date: Fri, 19 Sep 2025 14:19:53 GMT Message-Id: <202509191419.58JEJrSZ031832@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 94a0f9f63e16 - main - kern/vfs_vnops.c: generalize the lock primitive for file foffset List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 94a0f9f63e164e4f3791bc7d105d6f267b4d47bc Auto-Submitted: auto-generated The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=94a0f9f63e164e4f3791bc7d105d6f267b4d47bc commit 94a0f9f63e164e4f3791bc7d105d6f267b4d47bc Author: Konstantin Belousov AuthorDate: 2025-09-10 16:35:01 +0000 Commit: Konstantin Belousov CommitDate: 2025-09-19 14:19:05 +0000 kern/vfs_vnops.c: generalize the lock primitive for file foffset Generalize foffset_lock/unlock() by splitting the locking info file_v_lock/unlock() (LP64 case) or file_v_lock/unlock_mtxp() for ILP32 (using mutex pool) and then taking the action to read the offset. sys/file.h: rename struct file f_vnread_flags member into generic f_vflags Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D52486 --- sys/kern/vfs_vnops.c | 148 +++++++++++++++++++++++++++++++-------------------- sys/sys/file.h | 6 +-- 2 files changed, 94 insertions(+), 60 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index a4f41192f684..f81c2033d95e 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -798,58 +798,82 @@ vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, size_t len, } #if OFF_MAX <= LONG_MAX -off_t -foffset_lock(struct file *fp, int flags) +static void +file_v_lock(struct file *fp, short lock_bit, short lock_wait_bit) { - volatile short *flagsp; - off_t res; + short *flagsp; short state; - KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); - - if ((flags & FOF_NOLOCK) != 0) - return (atomic_load_long(&fp->f_offset)); - - /* - * According to McKusick the vn lock was protecting f_offset here. - * It is now protected by the FOFFSET_LOCKED flag. - */ - flagsp = &fp->f_vnread_flags; - if (atomic_cmpset_acq_16(flagsp, 0, FOFFSET_LOCKED)) - return (atomic_load_long(&fp->f_offset)); + flagsp = &fp->f_vflags; + state = atomic_load_16(flagsp); + if ((state & lock_bit) == 0 && + atomic_cmpset_acq_16(flagsp, state, state | lock_bit)) + return; - sleepq_lock(&fp->f_vnread_flags); + sleepq_lock(flagsp); state = atomic_load_16(flagsp); for (;;) { - if ((state & FOFFSET_LOCKED) == 0) { + if ((state & lock_bit) == 0) { if (!atomic_fcmpset_acq_16(flagsp, &state, - FOFFSET_LOCKED)) + state | lock_bit)) continue; break; } - if ((state & FOFFSET_LOCK_WAITING) == 0) { + if ((state & lock_wait_bit) == 0) { if (!atomic_fcmpset_acq_16(flagsp, &state, - state | FOFFSET_LOCK_WAITING)) + state | lock_wait_bit)) continue; } DROP_GIANT(); - sleepq_add(&fp->f_vnread_flags, NULL, "vofflock", 0, 0); - sleepq_wait(&fp->f_vnread_flags, PRI_MAX_KERN); + sleepq_add(flagsp, NULL, "vofflock", 0, 0); + sleepq_wait(flagsp, PRI_MAX_KERN); PICKUP_GIANT(); - sleepq_lock(&fp->f_vnread_flags); + sleepq_lock(flagsp); state = atomic_load_16(flagsp); } - res = atomic_load_long(&fp->f_offset); - sleepq_release(&fp->f_vnread_flags); - return (res); + sleepq_release(flagsp); } -void -foffset_unlock(struct file *fp, off_t val, int flags) +static void +file_v_unlock(struct file *fp, short lock_bit, short lock_wait_bit) { - volatile short *flagsp; + short *flagsp; short state; + flagsp = &fp->f_vflags; + state = atomic_load_16(flagsp); + if ((state & lock_wait_bit) == 0 && + atomic_cmpset_rel_16(flagsp, state, state & ~lock_bit)) + return; + + sleepq_lock(flagsp); + MPASS((*flagsp & lock_bit) != 0); + MPASS((*flagsp & lock_wait_bit) != 0); + atomic_clear_16(flagsp, lock_bit | lock_wait_bit); + sleepq_broadcast(flagsp, SLEEPQ_SLEEP, 0, 0); + sleepq_release(flagsp); +} + +off_t +foffset_lock(struct file *fp, int flags) +{ + KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); + + if ((flags & FOF_NOLOCK) == 0) { + file_v_lock(fp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); + } + + /* + * According to McKusick the vn lock was protecting f_offset here. + * It is now protected by the FOFFSET_LOCKED flag. + */ + return (atomic_load_long(&fp->f_offset)); +} + +void +foffset_unlock(struct file *fp, off_t val, int flags) +{ KASSERT((flags & FOF_OFFSET) == 0, ("FOF_OFFSET passed")); if ((flags & FOF_NOUPDATE) == 0) @@ -859,21 +883,10 @@ foffset_unlock(struct file *fp, off_t val, int flags) if ((flags & FOF_NEXTOFF_W) != 0) fp->f_nextoff[UIO_WRITE] = val; - if ((flags & FOF_NOLOCK) != 0) - return; - - flagsp = &fp->f_vnread_flags; - state = atomic_load_16(flagsp); - if ((state & FOFFSET_LOCK_WAITING) == 0 && - atomic_cmpset_rel_16(flagsp, state, 0)) - return; - - sleepq_lock(&fp->f_vnread_flags); - MPASS((fp->f_vnread_flags & FOFFSET_LOCKED) != 0); - MPASS((fp->f_vnread_flags & FOFFSET_LOCK_WAITING) != 0); - fp->f_vnread_flags = 0; - sleepq_broadcast(&fp->f_vnread_flags, SLEEPQ_SLEEP, 0, 0); - sleepq_release(&fp->f_vnread_flags); + if ((flags & FOF_NOLOCK) == 0) { + file_v_unlock(fp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); + } } static off_t @@ -882,7 +895,35 @@ foffset_read(struct file *fp) return (atomic_load_long(&fp->f_offset)); } -#else + +#else /* OFF_MAX <= LONG_MAX */ + +static void +file_v_lock_mtxp(struct file *fp, struct mtx *mtxp, short lock_bit, + short lock_wait_bit) +{ + mtx_assert(mtxp, MA_OWNED); + + while ((fp->f_vflags & lock_bit) != 0) { + fp->f_vflags |= lock_wait_bit; + msleep(&fp->f_vflags, mtxp, PRI_MAX_KERN, + "vofflock", 0); + } + fp->f_vflags |= lock_bit; +} + +static void +file_v_unlock_mtxp(struct file *fp, struct mtx *mtxp, short lock_bit, + short lock_wait_bit) +{ + mtx_assert(mtxp, MA_OWNED); + + KASSERT((fp->f_vflags & lock_bit) != 0, ("Lost lock_bit")); + if ((fp->f_vflags & lock_wait_bit) != 0) + wakeup(&fp->f_vflags); + fp->f_vflags &= ~(lock_bit | lock_wait_bit); +} + off_t foffset_lock(struct file *fp, int flags) { @@ -894,12 +935,8 @@ foffset_lock(struct file *fp, int flags) mtxp = mtx_pool_find(mtxpool_sleep, fp); mtx_lock(mtxp); if ((flags & FOF_NOLOCK) == 0) { - while (fp->f_vnread_flags & FOFFSET_LOCKED) { - fp->f_vnread_flags |= FOFFSET_LOCK_WAITING; - msleep(&fp->f_vnread_flags, mtxp, PRI_MAX_KERN, - "vofflock", 0); - } - fp->f_vnread_flags |= FOFFSET_LOCKED; + file_v_lock_mtxp(fp, mtxp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); } res = fp->f_offset; mtx_unlock(mtxp); @@ -922,11 +959,8 @@ foffset_unlock(struct file *fp, off_t val, int flags) if ((flags & FOF_NEXTOFF_W) != 0) fp->f_nextoff[UIO_WRITE] = val; if ((flags & FOF_NOLOCK) == 0) { - KASSERT((fp->f_vnread_flags & FOFFSET_LOCKED) != 0, - ("Lost FOFFSET_LOCKED")); - if (fp->f_vnread_flags & FOFFSET_LOCK_WAITING) - wakeup(&fp->f_vnread_flags); - fp->f_vnread_flags = 0; + file_v_unlock_mtxp(fp, mtxp, FILE_V_FOFFSET_LOCKED, + FILE_V_FOFFSET_LOCK_WAITING); } mtx_unlock(mtxp); } diff --git a/sys/sys/file.h b/sys/sys/file.h index cc3c733580fd..9a072121e25f 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -197,7 +197,7 @@ struct file { struct vnode *f_vnode; /* NULL or applicable vnode */ struct ucred *f_cred; /* associated credentials. */ short f_type; /* descriptor type */ - short f_vnread_flags; /* (f) Sleep lock for f_offset */ + short f_vflags; /* (f) Sleep lock flags for members */ /* * DTYPE_VNODE specific fields. */ @@ -220,8 +220,8 @@ struct file { #define f_cdevpriv f_vnun.fvn_cdevpriv #define f_advice f_vnun.fvn_advice -#define FOFFSET_LOCKED 0x1 -#define FOFFSET_LOCK_WAITING 0x2 +#define FILE_V_FOFFSET_LOCKED 0x0001 +#define FILE_V_FOFFSET_LOCK_WAITING 0x0002 #endif /* __BSD_VISIBLE */ #endif /* _KERNEL || _WANT_FILE */