From nobody Sat Oct 4 09:10:08 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 4cf09Y2Ywxz6B8Gy; Sat, 04 Oct 2025 09:10:09 +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 4cf09Y0T6rz3LTd; Sat, 04 Oct 2025 09:10:09 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1759569009; 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=bKA04UsMozzvekcShg96Vc3A6pik5zs6Yv4QQ8GG+s8=; b=AP25+CPznefPg2NubXQd8xlBmwEiNVu+BQ4jThtkuS937LQ60xtsVB7UnHDa+yCugXxKN4 UL5AnbWxmsCY7zZcEM/3Cyy4CkJrCii+RCHqxEMcDhKAwhVqke7N35zRsROCrGZ1rSTjt5 h/KtkkEm5Oq1FkUGXY/BsHfZi9KiXM1dt7SWMH+1N/X9CH5bMHf6yva2TlVriKifD4VipU PYQmk6iASiqgss0CF743ECkvB+jhAzyvubaUwLQdfbBGirB3POOqLu733zfiI+7ILtETdp 2A3BFiPce7iOtXKUnwe3qEEB8n2K0o/fDi6uOiBpPs2q3XYhzhk2L3p3QRg0/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1759569009; 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=bKA04UsMozzvekcShg96Vc3A6pik5zs6Yv4QQ8GG+s8=; b=aE+CqYtjkGnaZ7KbzL3/yUItI20iSR4IixNhQxw1ZR3heZnlzYGN03JR5Ga5jYoIpGnBnA w+YfJdYShodSUvGnsiIF4R5x+6M3ul9On3+92QqwEmnVpNf/oZZpmp0iK1bpjqSPNGJ6a8 mRJROE63YIWL7R5isyRu5tFBcCci4JxUQCUohF00XeCwaHTwcIbZat5aYIA3Sm3QiFL3h1 YdU4o9FDb3G/PxmZzH4NCBE9wjTxw0aPcY9m20FJvUdbPSgDE855T8X3nu0YBvuLqbmrop PHX/dSMD8EKJEYeb33q3ZO0p7uno7svprgCjgp1hCFAJyE9iLN0fAaLn4lSBdg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1759569009; a=rsa-sha256; cv=none; b=Tz4Y0B/l24CaZ1jGsSSI9tQiTEd7zCNHv4oHsEDsqNsG/QIquK8MvU+1XjlwNTCPBIxzoN o97zRSczZQ/K8KRLlG7KnrxrEoTl4GHS+eEP1fzK+BUVoHkrhBNdHI4CkZWynKqlI3dWEF a7W6A47/GNIsHcAZiOZA663ZPtOiIgX8rjBgBLqFQEO53+NphSU9qiw73pMshctOQ7i5iL SV4nHYe16LaQYKKRsx9qxYX1l0Q3wiT8sIhnUlU2zh2S7jqrlbpyY2pNnJyo4HJTRbryX/ eKncHd1PrQPcvqOrYSwF65QNZf+aD+JkkJE7ua5Jm1uxZd/Bd4RIpLGcEmgOWw== 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 4cf09Y0414zbfM; Sat, 04 Oct 2025 09:10:09 +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 5949A8me098796; Sat, 4 Oct 2025 09:10:08 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 5949A80e098791; Sat, 4 Oct 2025 09:10:08 GMT (envelope-from git) Date: Sat, 4 Oct 2025 09:10:08 GMT Message-Id: <202510040910.5949A80e098791@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: 7b980bf5e526 - stable/14 - 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/stable/14 X-Git-Reftype: branch X-Git-Commit: 7b980bf5e5262332c8f5679ad4dd7b17fd5db8a9 Auto-Submitted: auto-generated The branch stable/14 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=7b980bf5e5262332c8f5679ad4dd7b17fd5db8a9 commit 7b980bf5e5262332c8f5679ad4dd7b17fd5db8a9 Author: Konstantin Belousov AuthorDate: 2025-09-10 16:35:01 +0000 Commit: Konstantin Belousov CommitDate: 2025-10-04 09:09:45 +0000 kern/vfs_vnops.c: generalize the lock primitive for file foffset (cherry picked from commit 94a0f9f63e164e4f3791bc7d105d6f267b4d47bc) --- 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 79fee79295fb..5b25e2680ee4 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -759,58 +759,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) @@ -820,21 +844,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 @@ -843,7 +856,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) { @@ -855,12 +896,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); @@ -883,11 +920,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 7d1a191b4374..349605939d30 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -194,7 +194,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. */ @@ -217,8 +217,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 */