From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8583340273; Tue, 11 Nov 2025 14:13:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870386; cv=none; b=K93gtOuXUILzRDhf42TEJV+cGPCKFxP3FG9ykS4hRzCxPc7TK/3mIFQsNny7gCNNDwEvNgh+EBU3kda7/j6eGs8Is6brvnibKuwPQfkcMph7PvpBoc00NbZQ5y9sXQTSLBuo7CMhZZ/x5ywdIAlGG2cYvMTPqLbhhTK0jwbOASA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870386; c=relaxed/simple; bh=ga4TmUR59KoVfl15gt127269qV+bjIfb/4EDiwVOlYg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F5M2IKzVP0OVK47wXLVYRr+PK3bA50wU9C/ARhtKUqmuzAuV3EUNyNcjKwzNksacsloA7xTb1caQRCLBfUZB3e/o1lfXVWZ3mEoQLc41mnDeogOFX17o6UT7cW4NytbqsiyfvqSiZL27tFanHi2blUUK9O4Hwr6cBBYFw+z/1yg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E9bXfKuB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="E9bXfKuB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E46A2C113D0; Tue, 11 Nov 2025 14:13:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870386; bh=ga4TmUR59KoVfl15gt127269qV+bjIfb/4EDiwVOlYg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=E9bXfKuBMW2JliZ6aGlTLM4Xd0dB4l7pUYEuG4qMSJW5e6n726UYTXe5n5ee7xago luZUPcBdKt06aOSNpLWX1rJhJnC1nCOHxkMjTGTJxV9c54tmnaz8u8y4bbqDAgwbWE d+fwCso2l96m3Oa644JlFnOm0V42ZvI0P4inYT4CVdnK+SADEl4UwyvQVqiZ0Kkq56 7qLDWQM7n294J01uwinZBCNnGUgnEHiEdhHUgv0uCbGk1rCwlBrFGN8iU4beultUEu cH9Ih5uM/vTn/16QIjbBTo5iJ+XQIMlhiDHsgo1tsxJj709JzAASMZYoppXEMgNc7f i3rCfy4awilzg== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:42 -0500 Subject: [PATCH v6 01/17] filelock: make lease_alloc() take a flags argument Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-1-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2743; i=jlayton@kernel.org; h=from:subject:message-id; bh=ga4TmUR59KoVfl15gt127269qV+bjIfb/4EDiwVOlYg=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RnLXY7FpMdMxxWLOen1XZNghWf2CF671/r6 gSGJLumTVaJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEZwAKCRAADmhBGVaC FcSPD/9rXYYtQ/eGtCAdPwikcbaFG8p7gG5XFbymlb3VCn7rw4OyvYgIYnVsnrTh+Wn5oRmTefA M6mZk/yrNPSTz9PrkRBrBssmrOAIfcaY3UEUHUE8vnOBEaucMbZxB09yoblM1cc3ukpE4MEfS/X K1Td/OPSJDOtH6B0csY4IFzDHWkRWGrzNAoVFNlk2+fxOJPKou6KzljUBHLv2gyKopDnC6kdoJW YRQLZCVwUOf//mXlYGqGQDVRpSK8lpwtzsBwwWjJgP0TDpRnFvqCf2JomQpej/NIks+1A4uLpZb bO4FvOygF7+pHiQTavwGA/IH+1HuXdaGWfUzG9BKEgK37C34aZBvUW2VhTrAlc7HFAXmvV0h1wz qYZSojOLkwohht0vh9uUe2cLaLWo2CCYerJ71XooJPOgI3pyTd7t+Yp+EE9UyFC6agKmin0Byri 3WgTC1rEbD6n+m90TdFQThE0+yAWxfNzoEdGhqQUzhjiVrkCX16uxLIgBXR1RvybmWYxAeTpFvt PoFlCNod8DWjiVjfhlPWv0w2H2J9puJ2fg5Z36wgVSl7WKYdp9Ojm9FYLcYjyDCQY4CMv4VcoPO 1az7EX0cX8i3SypZw2magCeiHAveZAFjy59Ae6g5N0p5huhHUOH3xb2EJArDw6fVZQpsJrY4SxK apjukdfuLJQjucQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 __break_lease() currently overrides the flc_flags field in the lease after allocating it. A forthcoming patch will add the ability to request a FL_DELEG type lease. Instead of overriding the flags field, add a flags argument to lease_alloc() and lease_init() so it's set correctly after allocating. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/locks.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 04a3f0e2072461b6e2d3d1cd12f2b089d69a7db3..b33c327c21dcd49341fbeac47ca= eb72cdf7455db 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -585,7 +585,7 @@ static const struct lease_manager_operations lease_mana= ger_ops =3D { /* * Initialize a lease, use the default lock manager operations */ -static int lease_init(struct file *filp, int type, struct file_lease *fl) +static int lease_init(struct file *filp, unsigned int flags, int type, str= uct file_lease *fl) { if (assign_type(&fl->c, type) !=3D 0) return -EINVAL; @@ -594,13 +594,13 @@ static int lease_init(struct file *filp, int type, st= ruct file_lease *fl) fl->c.flc_pid =3D current->tgid; =20 fl->c.flc_file =3D filp; - fl->c.flc_flags =3D FL_LEASE; + fl->c.flc_flags =3D flags; fl->fl_lmops =3D &lease_manager_ops; return 0; } =20 /* Allocate a file_lock initialised to this type of lease */ -static struct file_lease *lease_alloc(struct file *filp, int type) +static struct file_lease *lease_alloc(struct file *filp, unsigned int flag= s, int type) { struct file_lease *fl =3D locks_alloc_lease(); int error =3D -ENOMEM; @@ -608,7 +608,7 @@ static struct file_lease *lease_alloc(struct file *filp= , int type) if (fl =3D=3D NULL) return ERR_PTR(error); =20 - error =3D lease_init(filp, type, fl); + error =3D lease_init(filp, flags, type, fl); if (error) { locks_free_lease(fl); return ERR_PTR(error); @@ -1548,10 +1548,9 @@ int __break_lease(struct inode *inode, unsigned int = mode, unsigned int type) int want_write =3D (mode & O_ACCMODE) !=3D O_RDONLY; LIST_HEAD(dispose); =20 - new_fl =3D lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK); + new_fl =3D lease_alloc(NULL, type, want_write ? F_WRLCK : F_RDLCK); if (IS_ERR(new_fl)) return PTR_ERR(new_fl); - new_fl->c.flc_flags =3D type; =20 /* typically we will check that ctx is non-NULL before calling */ ctx =3D locks_inode_context(inode); @@ -2033,7 +2032,7 @@ static int do_fcntl_add_lease(unsigned int fd, struct= file *filp, int arg) struct fasync_struct *new; int error; =20 - fl =3D lease_alloc(filp, arg); + fl =3D lease_alloc(filp, FL_LEASE, arg); if (IS_ERR(fl)) return PTR_ERR(fl); =20 --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3910F359711; Tue, 11 Nov 2025 14:13:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870390; cv=none; b=FoNDCoAjYjJ8wtxyAnBz+5jnwd+8H9uOAayndpQv21QlYA7AYEiHsEsKJZnO0LgTFKeG46JwuET4ldh5+VUnyi1rM9AFAXSo/N/2vtQozchCMowR2ooLykNyYL5rzwf3DzA0AfXeEM7wlC3Xv6cKRXMZKN+XQvKdi9AlCK129GA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870390; c=relaxed/simple; bh=JnDYtjNs2LgX2rp0KidKE2SUheGqQk7VKtXIGy+UzJU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JdOMtyYC1CxOG+kmdVTIH9f/NgygLOPtcCOmEM7dzk+8sCAtjvJmKjOCocOaFNdSquVnP+0ZRdft0svyq7ovxBSeXrEZVioxDP2W3m1WTJFsH2accelMYLMyK3bw9zrGBoBcgrW9RLbdin8CcEwr24GDbeZyMRlVGigvdSzuFrE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DGQG26L3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DGQG26L3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 62F40C2BC86; Tue, 11 Nov 2025 14:13:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870389; bh=JnDYtjNs2LgX2rp0KidKE2SUheGqQk7VKtXIGy+UzJU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DGQG26L3SaX4Hl0ABkehcI2uOxNtNPNA0XnnXpxDf5wjf3K2fRT3EM3HB7EeiuS4e ggMw/5nSWH61ra4lUIt2DMTerVnVi9v32RGXfHMnlI+gqifuxRL4qkmQcop2R15qJP f4EWRs0XbgcQ2yqHGzrgAvx7lmMp6DWDhXvt/gAoOhWL7RpT9G91QnhvmotiYQ0DhN W2PBOgOoT4r7mQbHWXwtT5B3lhlSS/clRIEoad/nV7loaBw2US8/cLBGcauXas9U4+ wv+PDvknX64psefTbviVZa4Jbe0rgMDvqRn6e4XO55fzPhXTo1PhYvzaop+mSwfSjs 6syTaDzoOSF/w== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:43 -0500 Subject: [PATCH v6 02/17] filelock: rework the __break_lease API to use flags Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-2-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7089; i=jlayton@kernel.org; h=from:subject:message-id; bh=JnDYtjNs2LgX2rp0KidKE2SUheGqQk7VKtXIGy+UzJU=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RnMWsLWjRYwNuoPPxcEJe2OnWyPUTAF6DGv gfuJmeAhmGJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEZwAKCRAADmhBGVaC FaVEEACE/jISwP6EfI8q7LwEMJKitTtvI/vMxdaSuXE1eGtdOaRBlQsjdMSo0VxS1fF+Ene1j7t iQHAsRXAOnEz8mWtYipK8KZU3vSQ+nNT38/QaqydofrWegP+S0hMumbnf8sdpjgNYkC/HB2bOCj hA2/j32Pb53YsKL885BySeZVihqxF0eLNM12z2Ng3I8sD21c58xu1iH0PFLFsoc/Hcie4zQF2tz qG2S/DpHArZbmR6ap2DABIOcWikjtd9lqjGtTWYDi19PVMJ5b51EZUc6ea3xFBvA51R4psPMcKs g2lfVaVd6Rudpz3RNZ2i+EzZiHmiYVbG+nF7B8B2SHiUFJ8Y2PdZ74wL++uLQZ1wmzMI+Np5NoF hDmfnQ+3NddMJ1jtNnnUKok23IY+0uYdyMm4JoI+sonrn2+fYIqQTf15p6OfvpAbet0kGLzdVHP wrQ+Gd5mm2ewVzIf3nKUt0G8fRFn7sRZDp8BwfgfUsbnhPg6eM/gxU17VUqk5Ak4V4FnhgRvk/E KLgmp9bTrYriuYtH4veWbRuOSP1HnZaEGib8nq6gSjkbm/B0MuxShM8xfDG+eyX55nPWnS3GPBp 1NmRkSQuhINDevIhveU2Pw3DSdwRJ8OYzdD244hhAw02UJ9YTglaTE9XazLNW4PFwggCeQnwA6C G3mTL1txJN/dNgw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Currently __break_lease takes both a type and an openmode. With the addition of directory leases, that makes less sense. Declare a set of LEASE_BREAK_* flags that can be used to control how lease breaks work instead of requiring a type and an openmode. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/locks.c | 29 +++++++++++++++++---------- include/linux/filelock.h | 52 +++++++++++++++++++++++++++++++++++---------= ---- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index b33c327c21dcd49341fbeac47caeb72cdf7455db..3cdd84a0fbedc9bd1b47725a9cf= 963342aafbce9 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1529,24 +1529,31 @@ any_leases_conflict(struct inode *inode, struct fil= e_lease *breaker) /** * __break_lease - revoke all outstanding leases on file * @inode: the inode of the file to return - * @mode: O_RDONLY: break only write leases; O_WRONLY or O_RDWR: - * break all leases - * @type: FL_LEASE: break leases and delegations; FL_DELEG: break - * only delegations + * @flags: LEASE_BREAK_* flags * * break_lease (inlined for speed) has checked there already is at least * some kind of lock (maybe a lease) on this file. Leases are broken on - * a call to open() or truncate(). This function can sleep unless you - * specified %O_NONBLOCK to your open(). + * a call to open() or truncate(). This function can block waiting for the + * lease break unless you specify LEASE_BREAK_NONBLOCK. */ -int __break_lease(struct inode *inode, unsigned int mode, unsigned int typ= e) +int __break_lease(struct inode *inode, unsigned int flags) { - int error =3D 0; - struct file_lock_context *ctx; struct file_lease *new_fl, *fl, *tmp; + struct file_lock_context *ctx; unsigned long break_time; - int want_write =3D (mode & O_ACCMODE) !=3D O_RDONLY; + unsigned int type; LIST_HEAD(dispose); + bool want_write =3D !(flags & LEASE_BREAK_OPEN_RDONLY); + int error =3D 0; + + if (flags & LEASE_BREAK_LEASE) + type =3D FL_LEASE; + else if (flags & LEASE_BREAK_DELEG) + type =3D FL_DELEG; + else if (flags & LEASE_BREAK_LAYOUT) + type =3D FL_LAYOUT; + else + return -EINVAL; =20 new_fl =3D lease_alloc(NULL, type, want_write ? F_WRLCK : F_RDLCK); if (IS_ERR(new_fl)) @@ -1595,7 +1602,7 @@ int __break_lease(struct inode *inode, unsigned int m= ode, unsigned int type) if (list_empty(&ctx->flc_lease)) goto out; =20 - if (mode & O_NONBLOCK) { + if (flags & LEASE_BREAK_NONBLOCK) { trace_break_lease_noblock(inode, new_fl); error =3D -EWOULDBLOCK; goto out; diff --git a/include/linux/filelock.h b/include/linux/filelock.h index c2ce8ba05d068b451ecf8f513b7e532819a29944..47da6aa28d8dc9122618d02c660= 8deda0f3c4d3e 100644 --- a/include/linux/filelock.h +++ b/include/linux/filelock.h @@ -212,7 +212,14 @@ int locks_lock_inode_wait(struct inode *inode, struct = file_lock *fl); void locks_init_lease(struct file_lease *); void locks_free_lease(struct file_lease *fl); struct file_lease *locks_alloc_lease(void); -int __break_lease(struct inode *inode, unsigned int flags, unsigned int ty= pe); + +#define LEASE_BREAK_LEASE BIT(0) // break leases and delegations +#define LEASE_BREAK_DELEG BIT(1) // break delegations only +#define LEASE_BREAK_LAYOUT BIT(2) // break layouts only +#define LEASE_BREAK_NONBLOCK BIT(3) // non-blocking break +#define LEASE_BREAK_OPEN_RDONLY BIT(4) // readonly open event + +int __break_lease(struct inode *inode, unsigned int flags); void lease_get_mtime(struct inode *, struct timespec64 *time); int generic_setlease(struct file *, int, struct file_lease **, void **priv= ); int kernel_setlease(struct file *, int, struct file_lease **, void **); @@ -367,7 +374,7 @@ static inline int locks_lock_inode_wait(struct inode *i= node, struct file_lock *f return -ENOLCK; } =20 -static inline int __break_lease(struct inode *inode, unsigned int mode, un= signed int type) +static inline int __break_lease(struct inode *inode, unsigned int flags) { return 0; } @@ -428,6 +435,17 @@ static inline int locks_lock_file_wait(struct file *fi= lp, struct file_lock *fl) } =20 #ifdef CONFIG_FILE_LOCKING +static inline unsigned int openmode_to_lease_flags(unsigned int mode) +{ + unsigned int flags =3D 0; + + if ((mode & O_ACCMODE) =3D=3D O_RDONLY) + flags |=3D LEASE_BREAK_OPEN_RDONLY; + if (mode & O_NONBLOCK) + flags |=3D LEASE_BREAK_NONBLOCK; + return flags; +} + static inline int break_lease(struct inode *inode, unsigned int mode) { struct file_lock_context *flctx; @@ -443,11 +461,11 @@ static inline int break_lease(struct inode *inode, un= signed int mode) return 0; smp_mb(); if (!list_empty_careful(&flctx->flc_lease)) - return __break_lease(inode, mode, FL_LEASE); + return __break_lease(inode, LEASE_BREAK_LEASE | openmode_to_lease_flags(= mode)); return 0; } =20 -static inline int break_deleg(struct inode *inode, unsigned int mode) +static inline int break_deleg(struct inode *inode, unsigned int flags) { struct file_lock_context *flctx; =20 @@ -461,8 +479,10 @@ static inline int break_deleg(struct inode *inode, uns= igned int mode) if (!flctx) return 0; smp_mb(); - if (!list_empty_careful(&flctx->flc_lease)) - return __break_lease(inode, mode, FL_DELEG); + if (!list_empty_careful(&flctx->flc_lease)) { + flags |=3D LEASE_BREAK_DELEG; + return __break_lease(inode, flags); + } return 0; } =20 @@ -470,7 +490,7 @@ static inline int try_break_deleg(struct inode *inode, = struct inode **delegated_ { int ret; =20 - ret =3D break_deleg(inode, O_WRONLY|O_NONBLOCK); + ret =3D break_deleg(inode, LEASE_BREAK_NONBLOCK); if (ret =3D=3D -EWOULDBLOCK && delegated_inode) { *delegated_inode =3D inode; ihold(inode); @@ -482,7 +502,7 @@ static inline int break_deleg_wait(struct inode **deleg= ated_inode) { int ret; =20 - ret =3D break_deleg(*delegated_inode, O_WRONLY); + ret =3D break_deleg(*delegated_inode, 0); iput(*delegated_inode); *delegated_inode =3D NULL; return ret; @@ -491,20 +511,24 @@ static inline int break_deleg_wait(struct inode **del= egated_inode) static inline int break_layout(struct inode *inode, bool wait) { smp_mb(); - if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) - return __break_lease(inode, - wait ? O_WRONLY : O_WRONLY | O_NONBLOCK, - FL_LAYOUT); + if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) { + unsigned int flags =3D LEASE_BREAK_LAYOUT; + + if (!wait) + flags |=3D LEASE_BREAK_NONBLOCK; + + return __break_lease(inode, flags); + } return 0; } =20 #else /* !CONFIG_FILE_LOCKING */ -static inline int break_lease(struct inode *inode, unsigned int mode) +static inline int break_lease(struct inode *inode, bool wait) { return 0; } =20 -static inline int break_deleg(struct inode *inode, unsigned int mode) +static inline int break_deleg(struct inode *inode, unsigned int flags) { return 0; } --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ACBB535A921; Tue, 11 Nov 2025 14:13:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870393; cv=none; b=jlqgP9fkfyDnVa/c8JBuZ0kwOqj1EfikrMd9qBduRiJTciJoC4CXCUihrEDvbuctHLV0O7KbzOkFoQ/506mG4sZrKd+MT3HhH9GfHWsmqQSIl/GDoDRzyEeKkVzxiGYwjjZYg7WmdmZuhWrxNRvh2+Fjgv5fuTFJPrMgbcCWDWE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870393; c=relaxed/simple; bh=V8Nctj73gICiDSGTb2wnqFhIueJ8IABmBKooNfcEfec=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pT5gsCrs0cRhvKFlOTOhcTDMKzBlZaurnklPxBahCnUbm1QzdhOOXnCdVm2meJSvFkW9sneSqBXPgVPAWiAy5gDKqdbOifMvRhBny7S2zLMA8HiRWAvSG/JOImTJC6WO6ZvoxV6GpgX3hvvd9o0cGNKR8Yd9LdZN38p0jaZ4CrI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p2IoZNf1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="p2IoZNf1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DCD6DC116D0; Tue, 11 Nov 2025 14:13:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870393; bh=V8Nctj73gICiDSGTb2wnqFhIueJ8IABmBKooNfcEfec=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=p2IoZNf13l5ps724b3zns0BZfLCF5eNViK1cHQQBumZ7sMGUOYMe/y3MRMQ579SK9 BrvqXBXygUfVwQsX0QMJ8FDBp8hFOFW+2RBGkmGVyIVRTRCdQlVLC8r/Ea/xPa6DVR n7YdeIQd+GGmO4dw2PUDl3vO0ED6g/F/rR59wg09hjNatPmI9oULI0YccUaJ6yQ9Wu Iszprucy7kXz9x+BdF7uK9eA+jpZb4e+Ivy8k/HbV1n/dDCs+OouFGIhNDSBnC3MF0 0jUkukNGlSpQLIlEEYQ1zLQQLI1cQe6HQrnzZMh9TqyKJy/7RKRrFLuFSqhKTEDPuk TrdPWaJAkQoWw== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:44 -0500 Subject: [PATCH v6 03/17] filelock: add struct delegated_inode Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-3-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15568; i=jlayton@kernel.org; h=from:subject:message-id; bh=V8Nctj73gICiDSGTb2wnqFhIueJ8IABmBKooNfcEfec=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RnMDo9GVTOIBM785fQ6a32azk6JbnFc72yl LfZ7BCJ7IeJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEZwAKCRAADmhBGVaC FUWTD/wKuGcmP0b1noDMpt4/CI4QdpTJf0CAmBzKDey9/wUiBdso2A25zkFbzQ450g0Yr987qDs 7/qvVA51DmSe8B778ucybvKD+cGv3KWDi+qSJNsp61t26c1vFtjIayDOlPY4/a7JqbkrNexY3zQ ENBA8kOjSZrkdlF42lxlsF9p0OQwaX+4irmbsJhIMSclOlrmGImVYHBP0AoTmevd9d9Nw4JazMe WYKS16pcnAFsg0IQgKyaFoiyt3/86FX7fhOdZqgsTPlqVG4LMiUng6BU1nUQx0lLPCtHy4PPsZV dfrNqMKWO8p2fcIxF/lf2eixmWYwO9usoLH9IcNU6IKBdqCw+di0Lrm28zujbfFYxZhbkVFuk7o L7ZOW/gWvyBrQ+32cOti6BnDN7v6gO3rn6dfNCZUZiR9J25LIzOOUnmSkz/c2m/EvBFsN//j8Kp 12kR6kT2L9qDrRTEiXpYJHPdyLGzd3GH2JOBANxwavuSjEybamMKwZ3XPC4HaEkcDpm03gS/AUE C0t3M7fsaNn0bYjg+lLJIKG3gAKzpSxfQrh7GGbq9y2jyAjfO+tMCHyqKAmD7o6+6jXgy9Ni0B3 izA0E1fsxGhrxchZ9JHvloVfPnDAb4M4+nGCKON1Vp83t181qu/r+xjUHAPa/Baxb8ZQkSQVhqD AEyCtxmhzmiByZw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The current API requires a pointer to an inode pointer. It's easy for callers to get this wrong. Add a new delegated_inode structure and use that to pass back any inode that needs to be waited on. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/attr.c | 2 +- fs/namei.c | 18 +++++++++--------- fs/open.c | 8 ++++---- fs/posix_acl.c | 8 ++++---- fs/utimes.c | 4 ++-- fs/xattr.c | 12 ++++++------ include/linux/filelock.h | 36 +++++++++++++++++++++++++++--------- include/linux/fs.h | 9 +++++---- include/linux/xattr.h | 4 ++-- 9 files changed, 60 insertions(+), 41 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index 795f231d00e8eaaadf5b62f241655cb4b69cb507..b9ec6b47bab2fc2b561677b6396= 33bd32994022f 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -415,7 +415,7 @@ EXPORT_SYMBOL(may_setattr); * performed on the raw inode simply pass @nop_mnt_idmap. */ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry, - struct iattr *attr, struct inode **delegated_inode) + struct iattr *attr, struct delegated_inode *delegated_inode) { struct inode *inode =3D dentry->d_inode; umode_t mode =3D inode->i_mode; diff --git a/fs/namei.c b/fs/namei.c index 7377020a2cba02501483020e0fc93c279fb38d3e..bf42f146f847a5330fc581595c7= 256af28d9db90 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4648,7 +4648,7 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) * raw inode simply pass @nop_mnt_idmap. */ int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry, struct inode **delegated_inode) + struct dentry *dentry, struct delegated_inode *delegated_inode) { struct inode *target =3D dentry->d_inode; int error =3D may_delete(idmap, dir, dentry, 0); @@ -4706,7 +4706,7 @@ int do_unlinkat(int dfd, struct filename *name) struct qstr last; int type; struct inode *inode =3D NULL; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; unsigned int lookup_flags =3D 0; retry: error =3D filename_parentat(dfd, name, lookup_flags, &path, &last, &type); @@ -4743,7 +4743,7 @@ int do_unlinkat(int dfd, struct filename *name) if (inode) iput(inode); /* truncate the inode here */ inode =3D NULL; - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; @@ -4892,7 +4892,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname= , const char __user *, newn */ int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap, struct inode *dir, struct dentry *new_dentry, - struct inode **delegated_inode) + struct delegated_inode *delegated_inode) { struct inode *inode =3D old_dentry->d_inode; unsigned max_links =3D dir->i_sb->s_max_links; @@ -4968,7 +4968,7 @@ int do_linkat(int olddfd, struct filename *old, int n= ewdfd, struct mnt_idmap *idmap; struct dentry *new_dentry; struct path old_path, new_path; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; int how =3D 0; int error; =20 @@ -5012,7 +5012,7 @@ int do_linkat(int olddfd, struct filename *old, int n= ewdfd, new_dentry, &delegated_inode); out_dput: end_creating_path(&new_path, new_dentry); - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) { path_put(&old_path); @@ -5098,7 +5098,7 @@ int vfs_rename(struct renamedata *rd) struct inode *new_dir =3D d_inode(rd->new_parent); struct dentry *old_dentry =3D rd->old_dentry; struct dentry *new_dentry =3D rd->new_dentry; - struct inode **delegated_inode =3D rd->delegated_inode; + struct delegated_inode *delegated_inode =3D rd->delegated_inode; unsigned int flags =3D rd->flags; bool is_dir =3D d_is_dir(old_dentry); struct inode *source =3D old_dentry->d_inode; @@ -5261,7 +5261,7 @@ int do_renameat2(int olddfd, struct filename *from, i= nt newdfd, struct path old_path, new_path; struct qstr old_last, new_last; int old_type, new_type; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; unsigned int lookup_flags =3D 0, target_flags =3D LOOKUP_RENAME_TARGET | LOOKUP_CREATE; bool should_retry =3D false; @@ -5369,7 +5369,7 @@ int do_renameat2(int olddfd, struct filename *from, i= nt newdfd, exit3: unlock_rename(new_path.dentry, old_path.dentry); exit_lock_rename: - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; diff --git a/fs/open.c b/fs/open.c index 3d64372ecc675e4795eb0a0deda10f8f67b95640..fdaa6f08f6f4cac5c2fefd3eafa= 5e430e51f3979 100644 --- a/fs/open.c +++ b/fs/open.c @@ -631,7 +631,7 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) int chmod_common(const struct path *path, umode_t mode) { struct inode *inode =3D path->dentry->d_inode; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; struct iattr newattrs; int error; =20 @@ -651,7 +651,7 @@ int chmod_common(const struct path *path, umode_t mode) &newattrs, &delegated_inode); out_unlock: inode_unlock(inode); - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; @@ -756,7 +756,7 @@ int chown_common(const struct path *path, uid_t user, g= id_t group) struct mnt_idmap *idmap; struct user_namespace *fs_userns; struct inode *inode =3D path->dentry->d_inode; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; int error; struct iattr newattrs; kuid_t uid; @@ -791,7 +791,7 @@ int chown_common(const struct path *path, uid_t user, g= id_t group) error =3D notify_change(idmap, path->dentry, &newattrs, &delegated_inode); inode_unlock(inode); - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 4050942ab52f95741da2df13d191ade5c5ca12a2..768f027c142811ea907fe854515= 5ba7abd016305 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -1091,7 +1091,7 @@ int vfs_set_acl(struct mnt_idmap *idmap, struct dentr= y *dentry, int acl_type; int error; struct inode *inode =3D d_inode(dentry); - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; =20 acl_type =3D posix_acl_type(acl_name); if (acl_type < 0) @@ -1141,7 +1141,7 @@ int vfs_set_acl(struct mnt_idmap *idmap, struct dentr= y *dentry, out_inode_unlock: inode_unlock(inode); =20 - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; @@ -1212,7 +1212,7 @@ int vfs_remove_acl(struct mnt_idmap *idmap, struct de= ntry *dentry, int acl_type; int error; struct inode *inode =3D d_inode(dentry); - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; =20 acl_type =3D posix_acl_type(acl_name); if (acl_type < 0) @@ -1249,7 +1249,7 @@ int vfs_remove_acl(struct mnt_idmap *idmap, struct de= ntry *dentry, out_inode_unlock: inode_unlock(inode); =20 - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; diff --git a/fs/utimes.c b/fs/utimes.c index c7c7958e57b22f91646ca9f76d18781b64d371a3..bf9f45bdef54947de7ac55c9f87= 3ae9d0336dafa 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -22,7 +22,7 @@ int vfs_utimes(const struct path *path, struct timespec64= *times) int error; struct iattr newattrs; struct inode *inode =3D path->dentry->d_inode; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; =20 if (times) { if (!nsec_valid(times[0].tv_nsec) || @@ -66,7 +66,7 @@ int vfs_utimes(const struct path *path, struct timespec64= *times) error =3D notify_change(mnt_idmap(path->mnt), path->dentry, &newattrs, &delegated_inode); inode_unlock(inode); - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; diff --git a/fs/xattr.c b/fs/xattr.c index 8851a5ef34f5ab34383975dd4cef537de3f6391e..32d445fb60aaf2aaf4b16b62934= dc99bad378067 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -274,7 +274,7 @@ int __vfs_setxattr_noperm(struct mnt_idmap *idmap, int __vfs_setxattr_locked(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, - int flags, struct inode **delegated_inode) + int flags, struct delegated_inode *delegated_inode) { struct inode *inode =3D dentry->d_inode; int error; @@ -305,7 +305,7 @@ vfs_setxattr(struct mnt_idmap *idmap, struct dentry *de= ntry, const char *name, const void *value, size_t size, int flags) { struct inode *inode =3D dentry->d_inode; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; const void *orig_value =3D value; int error; =20 @@ -322,7 +322,7 @@ vfs_setxattr(struct mnt_idmap *idmap, struct dentry *de= ntry, flags, &delegated_inode); inode_unlock(inode); =20 - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; @@ -533,7 +533,7 @@ EXPORT_SYMBOL(__vfs_removexattr); int __vfs_removexattr_locked(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, - struct inode **delegated_inode) + struct delegated_inode *delegated_inode) { struct inode *inode =3D dentry->d_inode; int error; @@ -567,7 +567,7 @@ vfs_removexattr(struct mnt_idmap *idmap, struct dentry = *dentry, const char *name) { struct inode *inode =3D dentry->d_inode; - struct inode *delegated_inode =3D NULL; + struct delegated_inode delegated_inode =3D { }; int error; =20 retry_deleg: @@ -576,7 +576,7 @@ vfs_removexattr(struct mnt_idmap *idmap, struct dentry = *dentry, name, &delegated_inode); inode_unlock(inode); =20 - if (delegated_inode) { + if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; diff --git a/include/linux/filelock.h b/include/linux/filelock.h index 47da6aa28d8dc9122618d02c6608deda0f3c4d3e..208d108df2d73a9df65e5dc9968= d074af385f881 100644 --- a/include/linux/filelock.h +++ b/include/linux/filelock.h @@ -486,25 +486,35 @@ static inline int break_deleg(struct inode *inode, un= signed int flags) return 0; } =20 -static inline int try_break_deleg(struct inode *inode, struct inode **dele= gated_inode) +struct delegated_inode { + struct inode *di_inode; +}; + +static inline bool is_delegated(struct delegated_inode *di) +{ + return di->di_inode; +} + +static inline int try_break_deleg(struct inode *inode, + struct delegated_inode *di) { int ret; =20 ret =3D break_deleg(inode, LEASE_BREAK_NONBLOCK); - if (ret =3D=3D -EWOULDBLOCK && delegated_inode) { - *delegated_inode =3D inode; + if (ret =3D=3D -EWOULDBLOCK && di) { + di->di_inode =3D inode; ihold(inode); } return ret; } =20 -static inline int break_deleg_wait(struct inode **delegated_inode) +static inline int break_deleg_wait(struct delegated_inode *di) { int ret; =20 - ret =3D break_deleg(*delegated_inode, 0); - iput(*delegated_inode); - *delegated_inode =3D NULL; + ret =3D break_deleg(di->di_inode, 0); + iput(di->di_inode); + di->di_inode =3D NULL; return ret; } =20 @@ -523,6 +533,13 @@ static inline int break_layout(struct inode *inode, bo= ol wait) } =20 #else /* !CONFIG_FILE_LOCKING */ +struct delegated_inode { }; + +static inline bool is_delegated(struct delegated_inode *di) +{ + return false; +} + static inline int break_lease(struct inode *inode, bool wait) { return 0; @@ -533,12 +550,13 @@ static inline int break_deleg(struct inode *inode, un= signed int flags) return 0; } =20 -static inline int try_break_deleg(struct inode *inode, struct inode **dele= gated_inode) +static inline int try_break_deleg(struct inode *inode, + struct delegated_inode *delegated_inode) { return 0; } =20 -static inline int break_deleg_wait(struct inode **delegated_inode) +static inline int break_deleg_wait(struct delegated_inode *delegated_inode) { BUG(); return 0; diff --git a/include/linux/fs.h b/include/linux/fs.h index c895146c1444be36e0a779df55622cc38c9419ff..909a88e3979d4f1ba3104f3d051= 45e1096ed44d5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -80,6 +80,7 @@ struct fs_context; struct fs_parameter_spec; struct file_kattr; struct iomap_ops; +struct delegated_inode; =20 extern void __init inode_init(void); extern void __init inode_init_early(void); @@ -2119,10 +2120,10 @@ int vfs_mknod(struct mnt_idmap *, struct inode *, s= truct dentry *, int vfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *, const char *); int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *, - struct dentry *, struct inode **); + struct dentry *, struct delegated_inode *); int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *); int vfs_unlink(struct mnt_idmap *, struct inode *, struct dentry *, - struct inode **); + struct delegated_inode *); =20 /** * struct renamedata - contains all information required for renaming @@ -2140,7 +2141,7 @@ struct renamedata { struct dentry *old_dentry; struct dentry *new_parent; struct dentry *new_dentry; - struct inode **delegated_inode; + struct delegated_inode *delegated_inode; unsigned int flags; } __randomize_layout; =20 @@ -3071,7 +3072,7 @@ static inline int bmap(struct inode *inode, sector_t= *block) #endif =20 int notify_change(struct mnt_idmap *, struct dentry *, - struct iattr *, struct inode **); + struct iattr *, struct delegated_inode *); int inode_permission(struct mnt_idmap *, struct inode *, int); int generic_permission(struct mnt_idmap *, struct inode *, int); static inline int file_permission(struct file *file, int mask) diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 86b0d47984a16d935dd1c45ca80a3b8bb5b7295b..64e9afe7d647dc38f686a4b5c6f= 765e061cde54c 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -85,12 +85,12 @@ int __vfs_setxattr_noperm(struct mnt_idmap *, struct de= ntry *, const char *, const void *, size_t, int); int __vfs_setxattr_locked(struct mnt_idmap *, struct dentry *, const char *, const void *, size_t, int, - struct inode **); + struct delegated_inode *); int vfs_setxattr(struct mnt_idmap *, struct dentry *, const char *, const void *, size_t, int); int __vfs_removexattr(struct mnt_idmap *, struct dentry *, const char *); int __vfs_removexattr_locked(struct mnt_idmap *, struct dentry *, - const char *, struct inode **); + const char *, struct delegated_inode *); int vfs_removexattr(struct mnt_idmap *, struct dentry *, const char *); =20 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buff= er_size); --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C98C35A936; Tue, 11 Nov 2025 14:13:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870397; cv=none; b=blUCJq2n3F/rfHwyQFfq6C7zqWF6k7o1diCOeZPXP3IyDm4FePaUqJD2CFu9HArFjp0Krf5U+cxE04fCBiLLbze8JPTrkPStL4ONCaf6M5vt5VXGiNh94W3XQ1rmv/ew9lkAHX0SOANcWQFt1YS5PMbLu2uYYocgF34cOx3AtNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870397; c=relaxed/simple; bh=GcsMrS33yeMCZHbhLsrwn2fXghDYDgJpfU5BwKmzfzs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C4Hu4uwL0PurD0xbxYsujbu7bdS40QO8xuK1LwsdfT0I/0zlPA41oASGINtaGXaRRvDvfEn93GoWCmWVw/gVZ7jH58D0j8Ue9lv9UdzY7ZVP6XrvoQMa/77TzzK7UojyCFI6cygb8AxatgXeIjzT6UboDUa9tQez+7azCZREfLI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ivq4+v8L; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ivq4+v8L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71D2AC4CEF5; Tue, 11 Nov 2025 14:13:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870396; bh=GcsMrS33yeMCZHbhLsrwn2fXghDYDgJpfU5BwKmzfzs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ivq4+v8LZbq3VMIZRAx9xaEcxmalQwXvKiyED/tMFkRt4VVX7I025l65WOZnUOVL+ dPmRVH27FY//79kyYzRGBxHYShbY5Xdlxkv3fKCOsrbfNhXcF7t1gsY4WYcFe+6jeX 50np0rCyHx2NmNM2DSqzy8V7ZVdoq4MuE0tnj+NCZtn41egInm4GOC4GV+PDNzxdmy TpTko2hl/DCNiF5ui9sw4krd1L5uuWr8ij+5POHpmnbcAg3PyEml+dim6vT3TqbAM1 kSbnK6DWC04CE4jwPy4kQn/XXmhpqJOxKVKsbwv4VtZlPUKjzORSsOLav8C43m6MHz yu20qE7R7Efgw== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:45 -0500 Subject: [PATCH v6 04/17] filelock: push the S_ISREG check down to ->setlease handlers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-4-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3489; i=jlayton@kernel.org; h=from:subject:message-id; bh=GcsMrS33yeMCZHbhLsrwn2fXghDYDgJpfU5BwKmzfzs=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RnZXf5vWXMu7ocP8gL9oRsQGQv1qS2Zu5wH N2iZG33UIKJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEZwAKCRAADmhBGVaC FW4MD/9MZbM4ESjlmFlYCPKFhX1BTgL8Q+8KJzx5nJdclnxMFkFG0nH32rDWtvOppDG0LDftYcC fF6UvsBVPE2E2J+PGBvbQ9UYq9XmE0nu/5lFYVSWE6Wxk1/hYDlZOc85SdXOA5puFW261KPlfFO eAyPwB4sv4oAmJ/dkiaDWrZ0TGWemevtt1QkwBPTHmdfBmfd+SxtHBpxuRNtctnjDYo3soPJCMR fCOcgYT+3UVxoliPhnX/I1MMkbp6117M/SYkbGsfs5Dl66wiM44a4ZuaWN2w4sZ0TRSiSbcbpf1 T3fqHmIU6RXB4RifvAXE2PzLpIx7tkDjBGUi+CnMa6N5BDEtksc1X2LPn0I1Km4kNow7TyYNrac AyWrrqBE+bpArKW/JIOADVAXUL831m6MYwoUSareQcliPX+/uLdtUCRvb6+XDed7ppNkKEr+tL0 ZRhY6pT8bf7PxPpRq//ZEUVtHmdmfPyYfIFxON1s/7sLKTGz4uZRsP2V6VR3MNNdaudgI0dh/ss 4xTd3Xzlr4s3J+ogsk0+/CTXZXdDhve08Cn2MijyqF+0o0ecCr3qQOAQS2YIEMnEyS4/YHeEgsc T5INL5UHK6NJyT+PRsBZKbhmnBZ6P5ZW2l2K+HZ37wumHkc6Xy+PgsujQ9sYIOjVIlrTllqIT9U xvX0/3ZTPlu3ocQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 When nfsd starts requesting directory delegations, setlease handlers may see requests for leases on directories. Push the !S_ISREG check down into the non-trivial setlease handlers, so we can selectively enable them where they're supported. FUSE is special: It's the only filesystem that supports atomic_open and allows kernel-internal leases. atomic_open is issued when the VFS doesn't know the state of the dentry being opened. If the file doesn't exist, it may be created, in which case the dir lease should be broken. The existing kernel-internal lease implementation has no provision for this. Ensure that we don't allow directory leases by default going forward by explicitly disabling them there. Reviewed-by: NeilBrown Reviewed-by: Jan Kara Signed-off-by: Jeff Layton --- fs/fuse/dir.c | 1 + fs/locks.c | 5 +++-- fs/nfs/nfs4file.c | 2 ++ fs/smb/client/cifsfs.c | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index ecaec0fea3a132e7cbb88121e7db7fb504d57d3c..667774cc72a1d49796f531fcb34= 2d2e4878beb85 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -2230,6 +2230,7 @@ static const struct file_operations fuse_dir_operatio= ns =3D { .fsync =3D fuse_dir_fsync, .unlocked_ioctl =3D fuse_dir_ioctl, .compat_ioctl =3D fuse_dir_compat_ioctl, + .setlease =3D simple_nosetlease, }; =20 static const struct inode_operations fuse_common_inode_operations =3D { diff --git a/fs/locks.c b/fs/locks.c index 3cdd84a0fbedc9bd1b47725a9cf963342aafbce9..f5b210a2dc34c70ac36e972436c= 62482bbe32ca6 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1935,6 +1935,9 @@ static int generic_delete_lease(struct file *filp, vo= id *owner) int generic_setlease(struct file *filp, int arg, struct file_lease **flp, void **priv) { + if (!S_ISREG(file_inode(filp)->i_mode)) + return -EINVAL; + switch (arg) { case F_UNLCK: return generic_delete_lease(filp, *priv); @@ -2024,8 +2027,6 @@ vfs_setlease(struct file *filp, int arg, struct file_= lease **lease, void **priv) =20 if ((!vfsuid_eq_kuid(vfsuid, current_fsuid())) && !capable(CAP_LEASE)) return -EACCES; - if (!S_ISREG(inode->i_mode)) - return -EINVAL; error =3D security_file_lock(filp, arg); if (error) return error; diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 7f43e890d3564a000dab9365048a3e17dc96395c..7317f26892c5782a39660cae87e= c1afea24e36c0 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -431,6 +431,8 @@ void nfs42_ssc_unregister_ops(void) static int nfs4_setlease(struct file *file, int arg, struct file_lease **l= ease, void **priv) { + if (!S_ISREG(file_inode(file)->i_mode)) + return -EINVAL; return nfs4_proc_setlease(file, arg, lease, priv); } =20 diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 05b1fa76e8ccf1e86f0c174593cd6e1acb84608d..03c44c1d9bb631b87a8b67aa16e= 481d6bb3c7d14 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -1149,6 +1149,9 @@ cifs_setlease(struct file *file, int arg, struct file= _lease **lease, void **priv struct inode *inode =3D file_inode(file); struct cifsFileInfo *cfile =3D file->private_data; =20 + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + /* Check if file is oplocked if this is request for new lease */ if (arg =3D=3D F_UNLCK || ((arg =3D=3D F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ABD3E33F8A7; Tue, 11 Nov 2025 14:13:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870400; cv=none; b=awtQTmDYdFeIMPNn0ERKE6Lt7AUVJ1faTb9Rl3AqOJvhOxZ2k8hkWsipBofMeWzivxdQgCZhgHg8ioY5t9IWFeQ1nTIkbC3pQFXggXt4KSWWon82Ub000m90QcV5Zae23Obuzt1hHqfrjrXhLgw1/D37ew9EwNALuwZR12FGbCY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870400; c=relaxed/simple; bh=3+ZClpFIpySqsQF9IacI3LgDcwpX/JfG6YtjN83vd9E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NcgLkqAiZmzhKk7PHML0ORtKeSXnrsZeir91CPfJVtX8cyQKZZ+FFeZkZyg3JqbQKlKg7uWJ3picQrLHkgkep6jIKwWCUlzEP/LJcG3N0iZSWusg2JrkGU9qMqUNVttnMAtLPKB5Oe2Rl6pPMmM/sn15WfQneb4YZfVxkfwsvtE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BBgLV+Y2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BBgLV+Y2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E6969C19423; Tue, 11 Nov 2025 14:13:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870400; bh=3+ZClpFIpySqsQF9IacI3LgDcwpX/JfG6YtjN83vd9E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=BBgLV+Y2bM2cCIEiouEHiXnUo6Hc6aloXBXMBLGsp1JmSbQmkZolk3kPcbtIJP1Ru J62tYSNG+SL7GAvRKAuC3APnQOIC1ISdBi5WgpqjUW+RiYEzHT4biA1k/ChCdq8IQy TCXSuy6dW4dD3pwBST1Qt4lGZUqXb97xFISMKeQLNQfx01h9FsuUQN79gEo5kM+cI4 fJ0g4Cgk5nqe+hooQdtGPXkpQvJiQcp7rpHwj6bTgyzMx0ZXZzknTJalGDBFqplol3 CET8GVXNvKj2j+uj+lAvqlrrRdAZVvyUmISDW9ug5x0dEt8wE3YkeoaF34GBOpgk4d 8p0UJWQJ4DhRw== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:46 -0500 Subject: [PATCH v6 05/17] vfs: add try_break_deleg calls for parents to vfs_{link,rename,unlink} Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-5-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1915; i=jlayton@kernel.org; h=from:subject:message-id; bh=3+ZClpFIpySqsQF9IacI3LgDcwpX/JfG6YtjN83vd9E=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RnGMZtdn1x+LYL7VkmMQxhx/2imw/qsb2u+ ANbnARa4weJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEZwAKCRAADmhBGVaC Fd1MD/9rBfdwEp19fPzoIbMxyGyERq7h5UvA+/X6v4WNDDlRIuc0LUM3J1zhJKeUTFHrjjCTa+T W2i2rXMwkpcwwpzhxzniLIV/fMsVMkOsTP5YY+woGbayopCeNok5yaQITIrjrYTJNQuYQUJ2O/e DGtYIMWXVJ7nRvez6zvMm8nXYpMpFN2eN4zmTbC4tpCTGKFjrVOEXmyvXhp+j4KY6MryXSkKfbV Pq1GZ3g2vlCgJfSRzljBl7MLWKHg8MXvM5C8orWtthHm2rUbECe6r9uuSFWTS+bqPoHdNKGdF+G HAoRc87XuVIVhVGonOq5UF9GBfm+0LifJLvkBeP6kSxp23gxvv79W9LUB0T2ZegbBJwQkgrS92u T/QaFWikIb03PVrLM2WFieX+6YDky7PG8I4lBntkSgsHeN7/cm8sMshpFRvSMvX2nI4mF56Mnsn JdEyuoT7DPPlkZ8qByPxi4dIdhI3tIQVqYomMRFS9OTgGKovmPs3/37nWgiUL35qu6LnziVgKdV gEvxankJuGVgAdceIrAWUMtpPjh4bd7xrkPPLwEB65OY/LxUDfw1v7i4ipttVfyeIPegC41eJ98 lApAcuJYFpzi1YktAfqBj9dAOk/yI6tSd0XK7WdNjvAUwJesNHoOFoXy+8n62cgc/+k3545wWFk EC8E5CPghYnDkOQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. vfs_link, vfs_unlink, and vfs_rename all have existing delegation break handling for the children in the rename. Add the necessary calls for breaking delegations in the parent(s) as well. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/namei.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index bf42f146f847a5330fc581595c7256af28d9db90..5bcf3e93d350ffd290f72725c37= 8d3dffeeae364 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4667,6 +4667,9 @@ int vfs_unlink(struct mnt_idmap *idmap, struct inode = *dir, else { error =3D security_inode_unlink(dir, dentry); if (!error) { + error =3D try_break_deleg(dir, delegated_inode); + if (error) + goto out; error =3D try_break_deleg(target, delegated_inode); if (error) goto out; @@ -4936,7 +4939,9 @@ int vfs_link(struct dentry *old_dentry, struct mnt_id= map *idmap, else if (max_links && inode->i_nlink >=3D max_links) error =3D -EMLINK; else { - error =3D try_break_deleg(inode, delegated_inode); + error =3D try_break_deleg(dir, delegated_inode); + if (!error) + error =3D try_break_deleg(inode, delegated_inode); if (!error) error =3D dir->i_op->link(old_dentry, dir, new_dentry); } @@ -5203,6 +5208,14 @@ int vfs_rename(struct renamedata *rd) old_dir->i_nlink >=3D max_links) goto out; } + error =3D try_break_deleg(old_dir, delegated_inode); + if (error) + goto out; + if (new_dir !=3D old_dir) { + error =3D try_break_deleg(new_dir, delegated_inode); + if (error) + goto out; + } if (!is_dir) { error =3D try_break_deleg(source, delegated_inode); if (error) --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3615935F8C6; Tue, 11 Nov 2025 14:13:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870404; cv=none; b=r8s/V5rTZsxgGkFAkZUxqtZl7k2pek1dUbp/hFb5XkUxVM/b/WCN/V6y0tMKpYT3f4NcKnxAgBRluYnwNh7W6xLHR2UYh9ZSnG2aMsZhTB74RJoMUhZ9npo8O1vxnUcbcZyXQehO1AKzA7x+4vHiuxe457rgMyt4GDkV8kWIMp0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870404; c=relaxed/simple; bh=Abg5p2Lt31TlE/xurhC/XlffrDJLd5VW/QAzqsSk4cE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bjKhBMOkPelIHmkfdCJcWgd5klNH1fHR6PJjrN2Ymv0VGRSE+xPTG7LzdLcKaWWsG0xKs/PVQQBVoj5Rw8AcouqLrvlAWp9ZsZTC+svIyLT6GeLGD8JTTVKZAah2+Mz1D57ashlJQ29zyi7U8gn0lucVS8UTJddBqnZ14nA6Mhw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pzB3CLdD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pzB3CLdD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7CC9EC113D0; Tue, 11 Nov 2025 14:13:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870403; bh=Abg5p2Lt31TlE/xurhC/XlffrDJLd5VW/QAzqsSk4cE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pzB3CLdDU1Fwzx4eP3iHJGLC9mm0PuoT4Bx6OrtIV5FBRXnG0HAM46K6Tpl+0cIac saf3Bi2BYdsoavogObb4o3Pgrk4rOLWsU9HFfUy0uWQlIczUZUe88R4nrYL/pN7OJf L4Tn6SrL+5IEo79Sx8C9S5fafCy+TOm6ix/sccJ8yGAg0HNpHFUtjwJC459cPDIySy 7/A/hvQPNUX2iku5sXNr3BGtySOJgGbe3eB5Y39oBCbccXpBgOPI4YA8yb31o3r5/L 0tXo5bDY45sNQ8/9YN3cCRMobXuuTRXBC6UKKD1rNuFQFPEZh/4yRmlC2tx/BPolRt T1KM10dDChCow== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:47 -0500 Subject: [PATCH v6 06/17] vfs: allow mkdir to wait for delegation break on parent Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-6-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9247; i=jlayton@kernel.org; h=from:subject:message-id; bh=Abg5p2Lt31TlE/xurhC/XlffrDJLd5VW/QAzqsSk4cE=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0Ronpx3g3Y9Oo5KsszJzbgtNnh8oTLKOw9pA DgovbChOvGJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaAAKCRAADmhBGVaC FXPNEACRytqC5Ns/cmtzfwLF1FOecOcnQXCZwOojaWaxl8gIGaKrto5+efERW3BNtWDF+CR+TMH PN8foMV2XqldfyzbnkMPKdjQ0ulbHlTV+JfdfOkzxTM5bdFsIREVOGIwNyvy7ObVjRBv4ZaV9F4 M9AWrahJB7QrabDhq4T5mgOj337eVkzczrXWYmJL3hLx1V6lCjAcwziyarrpNFGvgqGDL56XiQe tGz3W3xm4lGjWgden7IwpQL9AULvD+gLz85r02kMptnGpTeBjgX7RpxXqx+Vn2nmfKyKc7C9PaL x0N+e1HgAB+2j2OKnJwXpFeYiI/xKl277d4IA75Hvy65cj7aZ8IDpGvFfY+EOqYgInLxkAZoA+W JF1gSAUkCSd670Wp5vDhP6uY/3eRuJBKHGQnZ8xwPZRA53Nz/57zqiOlA7Po+fTWGX24CuT7Oku rcHqB6zoBOgFvw1RfDePITLmAaoaKlI6PyZniuDy6TwvzW0srirMZDa6AFap42c6Gwnv2i5Mv9U hZLznWvnKjXfo9+J7y9J82acECUy7eOEBFyv0DxXvk2+KdAUTg4Y+9cUL4f1ApNteRLjxWEEIkq d/8n1Gn1cTTUrY1AzIkKLddYMKy07nFnri+thno6OxdA+HsUMwDxkPTuA/6F4QdyK8btDnRiJHF hHkTAB+pFLtGIOw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. Add a new delegated_inode parameter to vfs_mkdir. All of the existing callers set that to NULL for now, except for do_mkdirat which will properly block until the lease is gone. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- drivers/base/devtmpfs.c | 2 +- fs/cachefiles/namei.c | 2 +- fs/ecryptfs/inode.c | 2 +- fs/init.c | 2 +- fs/namei.c | 24 ++++++++++++++++++------ fs/nfsd/nfs4recover.c | 2 +- fs/nfsd/vfs.c | 2 +- fs/overlayfs/overlayfs.h | 2 +- fs/smb/server/vfs.c | 2 +- fs/xfs/scrub/orphanage.c | 2 +- include/linux/fs.h | 2 +- 11 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 9d4e46ad8352257a6a65d85526ebdbf9bf2d4b19..0e79621cb0f79870003b867ca38= 4199171ded4e0 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -180,7 +180,7 @@ static int dev_mkdir(const char *name, umode_t mode) if (IS_ERR(dentry)) return PTR_ERR(dentry); =20 - dentry =3D vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode); + dentry =3D vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode, = NULL); if (!IS_ERR(dentry)) /* mark as kernel-created inode */ d_inode(dentry)->i_private =3D &thread; diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index d1edb2ac38376c4f9d2a18026450bb3c774f7824..50c0f9c76d1fd4c05db90d7d0d1= bad574523ead0 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -130,7 +130,7 @@ struct dentry *cachefiles_get_directory(struct cachefil= es_cache *cache, goto mkdir_error; ret =3D cachefiles_inject_write_error(); if (ret =3D=3D 0) - subdir =3D vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700); + subdir =3D vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700, NULL); else subdir =3D ERR_PTR(ret); if (IS_ERR(subdir)) { diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ed1394da8d6bd7065f2a074378331f13fcda17f9..35830b3144f8f71374a78b3e746= 3b864f4fc216e 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -508,7 +508,7 @@ static struct dentry *ecryptfs_mkdir(struct mnt_idmap *= idmap, struct inode *dir, goto out; =20 lower_dentry =3D vfs_mkdir(&nop_mnt_idmap, lower_dir, - lower_dentry, mode); + lower_dentry, mode, NULL); rc =3D PTR_ERR(lower_dentry); if (IS_ERR(lower_dentry)) goto out; diff --git a/fs/init.c b/fs/init.c index 07f592ccdba868509d0f3aaf9936d8d890fdbec5..895f8a09a71acfd03e11164e3b4= 41a7d4e2de146 100644 --- a/fs/init.c +++ b/fs/init.c @@ -233,7 +233,7 @@ int __init init_mkdir(const char *pathname, umode_t mod= e) error =3D security_path_mkdir(&path, dentry, mode); if (!error) { dentry =3D vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode, - dentry, mode); + dentry, mode, NULL); if (IS_ERR(dentry)) error =3D PTR_ERR(dentry); } diff --git a/fs/namei.c b/fs/namei.c index 5bcf3e93d350ffd290f72725c378d3dffeeae364..76c0587d991ff7307e3dde69497= 719d716c8d7b8 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4407,10 +4407,11 @@ SYSCALL_DEFINE3(mknod, const char __user *, filenam= e, umode_t, mode, unsigned, d =20 /** * vfs_mkdir - create directory returning correct dentry if possible - * @idmap: idmap of the mount the inode was found from - * @dir: inode of the parent directory - * @dentry: dentry of the child directory - * @mode: mode of the child directory + * @idmap: idmap of the mount the inode was found from + * @dir: inode of the parent directory + * @dentry: dentry of the child directory + * @mode: mode of the child directory + * @delegated_inode: returns parent inode, if the inode is delegated. * * Create a directory. * @@ -4427,7 +4428,8 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename,= umode_t, mode, unsigned, d * In case of an error the dentry is dput() and an ERR_PTR() is returned. */ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry, umode_t mode) + struct dentry *dentry, umode_t mode, + struct delegated_inode *delegated_inode) { int error; unsigned max_links =3D dir->i_sb->s_max_links; @@ -4450,6 +4452,10 @@ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, st= ruct inode *dir, if (max_links && dir->i_nlink >=3D max_links) goto err; =20 + error =3D try_break_deleg(dir, delegated_inode); + if (error) + goto err; + de =3D dir->i_op->mkdir(idmap, dir, dentry, mode); error =3D PTR_ERR(de); if (IS_ERR(de)) @@ -4473,6 +4479,7 @@ int do_mkdirat(int dfd, struct filename *name, umode_= t mode) struct path path; int error; unsigned int lookup_flags =3D LOOKUP_DIRECTORY; + struct delegated_inode delegated_inode =3D { }; =20 retry: dentry =3D filename_create(dfd, name, &path, lookup_flags); @@ -4484,11 +4491,16 @@ int do_mkdirat(int dfd, struct filename *name, umod= e_t mode) mode_strip_umask(path.dentry->d_inode, mode)); if (!error) { dentry =3D vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode, - dentry, mode); + dentry, mode, &delegated_inode); if (IS_ERR(dentry)) error =3D PTR_ERR(dentry); } end_creating_path(&path, dentry); + if (is_delegated(&delegated_inode)) { + error =3D break_deleg_wait(&delegated_inode); + if (!error) + goto retry; + } if (retry_estale(error, lookup_flags)) { lookup_flags |=3D LOOKUP_REVAL; goto retry; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index e2b9472e5c78c9f03731090ffdfb26eb5de38fe0..1f56834b2072fcee1d0d400bbb5= 54b0c949ecab4 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -213,7 +213,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) * as well be forgiving and just succeed silently. */ goto out_put; - dentry =3D vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU); + dentry =3D vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, 0700, NULL); if (IS_ERR(dentry)) status =3D PTR_ERR(dentry); out_put: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 9cb20d4aeab159ef3ba3584d1a3a33ef16ba4dea..97aef140cbf5fca4c41738fdcac= cba3b57886463 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1558,7 +1558,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc= _fh *fhp, nfsd_check_ignore_resizing(iap); break; case S_IFDIR: - dchild =3D vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode); + dchild =3D vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode, NULL); if (IS_ERR(dchild)) { host_err =3D PTR_ERR(dchild); } else if (d_is_negative(dchild)) { diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index c8fd5951fc5ece1ae6b3e2a0801ca15f9faf7d72..0f65f9a5d54d4786b39e4f4f30f= 416d5b9016e70 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -248,7 +248,7 @@ static inline struct dentry *ovl_do_mkdir(struct ovl_fs= *ofs, { struct dentry *ret; =20 - ret =3D vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode); + ret =3D vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, NULL); pr_debug("mkdir(%pd2, 0%o) =3D %i\n", dentry, mode, PTR_ERR_OR_ZERO(ret)); return ret; } diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 891ed2dc2b7351a5cb14a2241d71095ffdd03f08..3d2190f26623b23ea79c6341090= 5a3c3ad684048 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -230,7 +230,7 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char= *name, umode_t mode) idmap =3D mnt_idmap(path.mnt); mode |=3D S_IFDIR; d =3D dentry; - dentry =3D vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode); + dentry =3D vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode, NULL); if (IS_ERR(dentry)) err =3D PTR_ERR(dentry); else if (d_is_negative(dentry)) diff --git a/fs/xfs/scrub/orphanage.c b/fs/xfs/scrub/orphanage.c index 9c12cb8442311ca26b169e4d1567939ae44a5be0..91c9d07b97f306f57aebb9b69ba= 564b0c2cb8c17 100644 --- a/fs/xfs/scrub/orphanage.c +++ b/fs/xfs/scrub/orphanage.c @@ -167,7 +167,7 @@ xrep_orphanage_create( */ if (d_really_is_negative(orphanage_dentry)) { orphanage_dentry =3D vfs_mkdir(&nop_mnt_idmap, root_inode, - orphanage_dentry, 0750); + orphanage_dentry, 0750, NULL); error =3D PTR_ERR(orphanage_dentry); if (IS_ERR(orphanage_dentry)) goto out_unlock_root; diff --git a/include/linux/fs.h b/include/linux/fs.h index 909a88e3979d4f1ba3104f3d05145e1096ed44d5..20bb4c8a4e8e1be7e11047d228c= 05920ea6c388d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2114,7 +2114,7 @@ bool inode_owner_or_capable(struct mnt_idmap *idmap, int vfs_create(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, bool); struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, - struct dentry *, umode_t); + struct dentry *, umode_t, struct delegated_inode *); int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, dev_t); int vfs_symlink(struct mnt_idmap *, struct inode *, --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C31B435F8DB; Tue, 11 Nov 2025 14:13:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870407; cv=none; b=ItIJUuoCktlpdzhIS3RlXrG61gJ4tFeTCk1B9MulWW+rsxdgJ1JuAH63JsidQT01u1wyUsQFC9gbY5jm0uq3vhWdTaAEtesbspUOP50k4tH74YcAW6BsuK+xdNfs0XAPt2/4MaV5NdOktNRgOIg0FIgskZqpoGrWrZJZuTHRaQg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870407; c=relaxed/simple; bh=nVt7zfcxkLtFpIV/AjQcJVwofL/t6x0LVRGY+VtgUx0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C1dBI6DHqc8gw9nvnXEi+I+ruP7KHosio85jyg5LXzTqrNOlQv9CLAOWnaXNgCZG+Ag6iz4KMU+8NsfzxmJZT4ioZBCSREoWBSihpF4y02NC0imnysHMWnDogNSl/RQbIYcYQ6fCQuzFhuk9WofHwGgdpH0JDt8/clSAS8C5hDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=e9mn+csA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="e9mn+csA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13757C4CEFB; Tue, 11 Nov 2025 14:13:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870407; bh=nVt7zfcxkLtFpIV/AjQcJVwofL/t6x0LVRGY+VtgUx0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=e9mn+csAe979dcJDDxtumYmdlDR1T0VUrgumfSa23lWzlrkL5hwYqunDCK+D6YRub ojj/t4zH1pCOPvyJcG5MBO3NNKvr0LHiJbdIg1tNXRxV+Ok491UVR+aheavtPiFDRe 4C2Nz2H3UQ1+B0caNuma+qP7s99O1r0ws3AdWlfoQGmD0hWTG+/c3G8/+CmtqzRr5A t5OQChfec6X+OqOlYfd/7OCmnX4KZUL83hHE6+Gr8TwxrZtlP9OMLLel3kQG99/EDr AirTXGDcrBsg9EKWvDILmSruiZeZbpyL+JI7eRRxVqTHVqwl8RygCu0sJBqDLZhBTx 0ztwYr+ld+E9w== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:48 -0500 Subject: [PATCH v6 07/17] vfs: allow rmdir to wait for delegation break on parent Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-7-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7777; i=jlayton@kernel.org; h=from:subject:message-id; bh=nVt7zfcxkLtFpIV/AjQcJVwofL/t6x0LVRGY+VtgUx0=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RoJS8Fj8piXf/NK6z2V8e4FFhMuVEkouPti WuChZ2J1TSJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaAAKCRAADmhBGVaC Fc6tD/9n/dNJbDu3AdHcn2AinnhD39pWeFFtgrL0uk+rQJgid0a0RmY0h15gE0a26Sw1emZYbb6 T/rBJt8n72LjWa89IBU1BVBSJSq/jI9LxSh4UrEnFE3AY7LdEJMEp2FqT0+Wm9wDmEDYV4gDvBC 0TtMW2E/YybyiedJf5GD+vKuwvqviC4br1t8Wnc0nWQghvSi5JxNuXsAji17vXWimlVJ3MTUwnu eZowNbSDGh2N/6AMQYm9atKgUOraPdkFPnUKImF+4mI6+KTq5R7DdJcTglPxAQZ/UANnxk1+RjS yaAUC8yjfGmGYdYVzlKP4e43iI+xnDHJ/+ddIxAKWzdxWhX1VVfyuJtlgFqpZ8AlOocWYHuAZeI KSEH+eaOxJfqZ2yyJstuRhYf0dkCcoSmYiQnXx0nDG8QPia0b6YQe9Prz1LEdCvWxGy73Ylcd9h 2tLR32ItZ3JIFfK03Ud6cK8JLckxsZW4D5ZENzfCgKkhUj04q+0g17WbsMssAWcKN7s/6iB/B8g Iw4Y0lfE7DwGJSw44Gm6F7DSa9KK02gudJpadhpf9wL14Hunpj2rYkXL+uEMu049pkBPDROnL0h igEulj4DqjN6Yy2sLIDrlxbLkdlCDZE5f8dY629ZzPb5x4KoY9z2C/cQ0BkIsS8/QNIDdP46KK7 P6+KbbdBfjW33LA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. Add a delegated_inode struct to vfs_rmdir() and populate that pointer with the parent inode if it's non-NULL. Most existing in-kernel callers pass in a NULL pointer. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- drivers/base/devtmpfs.c | 2 +- fs/ecryptfs/inode.c | 2 +- fs/namei.c | 22 +++++++++++++++++----- fs/nfsd/nfs4recover.c | 4 ++-- fs/nfsd/vfs.c | 2 +- fs/overlayfs/overlayfs.h | 2 +- fs/smb/server/vfs.c | 4 ++-- include/linux/fs.h | 3 ++- 8 files changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 0e79621cb0f79870003b867ca384199171ded4e0..104025104ef75381984fd94dfbd= 50feeaa8cdd22 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -261,7 +261,7 @@ static int dev_rmdir(const char *name) return PTR_ERR(dentry); if (d_inode(dentry)->i_private =3D=3D &thread) err =3D vfs_rmdir(&nop_mnt_idmap, d_inode(parent.dentry), - dentry); + dentry, NULL); else err =3D -EPERM; =20 diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 35830b3144f8f71374a78b3e7463b864f4fc216e..88631291b32535f623a3fbe4ea9= b6ed48a306ca0 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -540,7 +540,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct den= try *dentry) if (d_unhashed(lower_dentry)) rc =3D -EINVAL; else - rc =3D vfs_rmdir(&nop_mnt_idmap, lower_dir, lower_dentry); + rc =3D vfs_rmdir(&nop_mnt_idmap, lower_dir, lower_dentry, NULL); } if (!rc) { clear_nlink(d_inode(dentry)); diff --git a/fs/namei.c b/fs/namei.c index 76c0587d991ff7307e3dde69497719d716c8d7b8..9e0393a92091ac522b5324fcdad= 8c5592a948e8d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4522,9 +4522,10 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname= , umode_t, mode) =20 /** * vfs_rmdir - remove directory - * @idmap: idmap of the mount the inode was found from - * @dir: inode of the parent directory - * @dentry: dentry of the child directory + * @idmap: idmap of the mount the inode was found from + * @dir: inode of the parent directory + * @dentry: dentry of the child directory + * @delegated_inode: returns parent inode, if it's delegated. * * Remove a directory. * @@ -4535,7 +4536,7 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname,= umode_t, mode) * raw inode simply pass @nop_mnt_idmap. */ int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry) + struct dentry *dentry, struct delegated_inode *delegated_inode) { int error =3D may_delete(idmap, dir, dentry, 1); =20 @@ -4557,6 +4558,10 @@ int vfs_rmdir(struct mnt_idmap *idmap, struct inode = *dir, if (error) goto out; =20 + error =3D try_break_deleg(dir, delegated_inode); + if (error) + goto out; + error =3D dir->i_op->rmdir(dir, dentry); if (error) goto out; @@ -4583,6 +4588,7 @@ int do_rmdir(int dfd, struct filename *name) struct qstr last; int type; unsigned int lookup_flags =3D 0; + struct delegated_inode delegated_inode =3D { }; retry: error =3D filename_parentat(dfd, name, lookup_flags, &path, &last, &type); if (error) @@ -4612,7 +4618,8 @@ int do_rmdir(int dfd, struct filename *name) error =3D security_path_rmdir(&path, dentry); if (error) goto exit4; - error =3D vfs_rmdir(mnt_idmap(path.mnt), path.dentry->d_inode, dentry); + error =3D vfs_rmdir(mnt_idmap(path.mnt), path.dentry->d_inode, + dentry, &delegated_inode); exit4: dput(dentry); exit3: @@ -4620,6 +4627,11 @@ int do_rmdir(int dfd, struct filename *name) mnt_drop_write(path.mnt); exit2: path_put(&path); + if (is_delegated(&delegated_inode)) { + error =3D break_deleg_wait(&delegated_inode); + if (!error) + goto retry; + } if (retry_estale(error, lookup_flags)) { lookup_flags |=3D LOOKUP_REVAL; goto retry; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 1f56834b2072fcee1d0d400bbb554b0c949ecab4..30bae93931d9c9f8900dfcf96f7= 9403db4f3f458 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -337,7 +337,7 @@ nfsd4_unlink_clid_dir(char *name, struct nfsd_net *nn) status =3D -ENOENT; if (d_really_is_negative(dentry)) goto out; - status =3D vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry); + status =3D vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry, NULL); out: dput(dentry); out_unlock: @@ -427,7 +427,7 @@ purge_old(struct dentry *parent, struct dentry *child, = struct nfsd_net *nn) if (nfs4_has_reclaimed_state(name, nn)) goto out_free; =20 - status =3D vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child); + status =3D vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child, NULL); if (status) printk("failed to remove client recovery directory %pd\n", child); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 97aef140cbf5fca4c41738fdcaccba3b57886463..c400ea94ff2e837fd59719bf2c4= b79ef1d064743 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -2108,7 +2108,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fh= p, int type, break; } } else { - host_err =3D vfs_rmdir(&nop_mnt_idmap, dirp, rdentry); + host_err =3D vfs_rmdir(&nop_mnt_idmap, dirp, rdentry, NULL); } fh_fill_post_attrs(fhp); =20 diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 0f65f9a5d54d4786b39e4f4f30f416d5b9016e70..d215d7349489686b66bb66e939b= 27046f7d836f6 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -206,7 +206,7 @@ static inline int ovl_do_notify_change(struct ovl_fs *o= fs, static inline int ovl_do_rmdir(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry) { - int err =3D vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry); + int err =3D vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry, NULL); =20 pr_debug("rmdir(%pd2) =3D %i\n", dentry, err); return err; diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 3d2190f26623b23ea79c63410905a3c3ad684048..c5f0f3170d586cb2dc4d416b809= 48c642797fb82 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -609,7 +609,7 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, cons= t struct path *path) =20 idmap =3D mnt_idmap(path->mnt); if (S_ISDIR(d_inode(path->dentry)->i_mode)) { - err =3D vfs_rmdir(idmap, d_inode(parent), path->dentry); + err =3D vfs_rmdir(idmap, d_inode(parent), path->dentry, NULL); if (err && err !=3D -ENOTEMPTY) ksmbd_debug(VFS, "rmdir failed, err %d\n", err); } else { @@ -1090,7 +1090,7 @@ int ksmbd_vfs_unlink(struct file *filp) dget(dentry); =20 if (S_ISDIR(d_inode(dentry)->i_mode)) - err =3D vfs_rmdir(idmap, d_inode(dir), dentry); + err =3D vfs_rmdir(idmap, d_inode(dir), dentry, NULL); else err =3D vfs_unlink(idmap, d_inode(dir), dentry, NULL); =20 diff --git a/include/linux/fs.h b/include/linux/fs.h index 20bb4c8a4e8e1be7e11047d228c05920ea6c388d..12873214e1c7811735ea5d2dee3= d57e2a5604d8f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2121,7 +2121,8 @@ int vfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *, const char *); int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *, struct dentry *, struct delegated_inode *); -int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *); +int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *, + struct delegated_inode *); int vfs_unlink(struct mnt_idmap *, struct inode *, struct dentry *, struct delegated_inode *); =20 --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62576342528; Tue, 11 Nov 2025 14:13:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870411; cv=none; b=R4L91U+5iWqwjNI6ZtUfGufYlTCjopukn1Tvan7zlHbpRHl6CI9TDGiM5UpxMgB5guwUOIDDpCYri+ld+c71XwZ7OHOfdC17kovhbaPoCgkb9S5zaFm+nDnexF5ucRNTfuMfe7g/lF0CuZeI/Ii4w4d+A/5+/rrSblk4NWwvGSU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870411; c=relaxed/simple; bh=zBQyD4C+LOu4tUZSnzQKyrp9sE+YBQAdVnnbBh8HRrY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MUwigvQJVfysQ9GM2GTMlJsQziT3PTD1c6l/aeuR+1JDl6/2w3Ukm6c+JJy/yEAqqXkucRy/o6mycdGcZZUwMk3usRpT6Y9RO67W2ZhhcUK7vSZfTjzlwHtc0/a2HjZdUWdVM9PxKuXAPpTOSGDqLT4aoxLLVltghauoGCA2u+c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=q+JXl/qO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="q+JXl/qO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9007CC19423; Tue, 11 Nov 2025 14:13:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870410; bh=zBQyD4C+LOu4tUZSnzQKyrp9sE+YBQAdVnnbBh8HRrY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=q+JXl/qOGBjpG971jort9qetqPG0oOrL22kJpq2iodt2tQrpO9RtyTQFjG+aJ7a64 AGS8cjOAJ5M6QcE8tsK88YH6DvZ/Z//UmFl0OkCfci7nd8WmtSsy5CFBQzsKALsAXf SoOUro4hPgnDhsvE6t3dLwcfmFe2FxFqTRz2slxf7b5TnXNJuV4ftBxK8Bkxif6F3E bYclh+GkyH++my3xz28CE46eI3pdTyyjyZNf8SsmhfPv72F2ZvD5XAU2mA8gb8XFgJ Mg/RgAHrfij7j4CgsJT9sBFrA7KrCw6MW/MwpG1z3qaWqJgcV4cMbBbJyOpCYGRPKz lEf3Ry59HlzFA== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:49 -0500 Subject: [PATCH v6 08/17] vfs: break parent dir delegations in open(..., O_CREAT) codepath Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-8-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3106; i=jlayton@kernel.org; h=from:subject:message-id; bh=zBQyD4C+LOu4tUZSnzQKyrp9sE+YBQAdVnnbBh8HRrY=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0Rove0vkRkFCV/1Wn8zmFJ9RHK9gxr/mOYAQ 4Pet5flOdyJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaAAKCRAADmhBGVaC FQGKD/4sjIDoZy81s0foS2X40pi3J9sEGDlAZ2xEWmBBgxf4QOJluiLEaGvnXoXqAwuIgZxBoP2 FIJ0p0AKVbvFcu2WE288jAYyOlIy4mwjTR+MQhNNd+fsx89l4PsAJ3gLaEi+q36kDzHTtWiExCm VVy37eBlp/pNo0Ha8w/E4+d3iizh3XiJOiEET7516yQLthrC5sLEsSmoWLIBpCone8AroXGFW7c uPdnlxSu/XJEV9nZxuthyRE4adIXWjUcGXVvg03f5uwaj5ZcUF4dRufENFurgBNeP6NOA4sCP3k Ot9hasCXOHBc/nx8w/ZawJY16QWmJlXQku/jNycCvVuuJ4m5vl4P8M56sitEc4G1U4Psjx3dfnd wvkpdnKmdD+e1O8RlY1es8qEY50poTV9RxN3Y8GMI6H/qp7zkXvHUV/UjVDtng50afyiJBlU+En 9Uf/v7HFz/q8aZGFO9BozaqyjOs7epR7vGmrf3hR78dd4uvObj6/1TT1qpfHgGuVuG85S5rc8d3 qcLxlrf9oYJyNvO6Vb+LIotj0uahaxtfRDB5skZ2fOMljHAjBY/zt+fEFtCfysQeFanOdT5qmUI SWr/cOSlZ9mkM/fFqYuOjN8uY8TL4uFFlli5fS4RgeMsY1pbjOvXaT7KUgfO/MJ9vPD5zG1knYE CcJvNDnRUF5oGXA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. Add a delegated_inode parameter to lookup_open and have it break the delegation. Then, open_last_lookups can wait for the delegation break and retry the call to lookup_open once it's done. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/namei.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 9e0393a92091ac522b5324fcdad8c5592a948e8d..f439429bdfa271ccc64c937771e= f4175597feb53 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3697,7 +3697,7 @@ static struct dentry *atomic_open(struct nameidata *n= d, struct dentry *dentry, */ static struct dentry *lookup_open(struct nameidata *nd, struct file *file, const struct open_flags *op, - bool got_write) + bool got_write, struct delegated_inode *delegated_inode) { struct mnt_idmap *idmap; struct dentry *dir =3D nd->path.dentry; @@ -3786,6 +3786,11 @@ static struct dentry *lookup_open(struct nameidata *= nd, struct file *file, =20 /* Negative dentry, just create the file */ if (!dentry->d_inode && (open_flag & O_CREAT)) { + /* but break the directory lease first! */ + error =3D try_break_deleg(dir_inode, delegated_inode); + if (error) + goto out_dput; + file->f_mode |=3D FMODE_CREATED; audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE); if (!dir_inode->i_op->create) { @@ -3848,6 +3853,7 @@ static struct dentry *lookup_fast_for_open(struct nam= eidata *nd, int open_flag) static const char *open_last_lookups(struct nameidata *nd, struct file *file, const struct open_flags *op) { + struct delegated_inode delegated_inode =3D { }; struct dentry *dir =3D nd->path.dentry; int open_flag =3D op->open_flag; bool got_write =3D false; @@ -3879,7 +3885,7 @@ static const char *open_last_lookups(struct nameidata= *nd, return ERR_PTR(-ECHILD); } } - +retry: if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { got_write =3D !mnt_want_write(nd->path.mnt); /* @@ -3892,7 +3898,7 @@ static const char *open_last_lookups(struct nameidata= *nd, inode_lock(dir->d_inode); else inode_lock_shared(dir->d_inode); - dentry =3D lookup_open(nd, file, op, got_write); + dentry =3D lookup_open(nd, file, op, got_write, &delegated_inode); if (!IS_ERR(dentry)) { if (file->f_mode & FMODE_CREATED) fsnotify_create(dir->d_inode, dentry); @@ -3907,8 +3913,16 @@ static const char *open_last_lookups(struct nameidat= a *nd, if (got_write) mnt_drop_write(nd->path.mnt); =20 - if (IS_ERR(dentry)) + if (IS_ERR(dentry)) { + if (is_delegated(&delegated_inode)) { + int error =3D break_deleg_wait(&delegated_inode); + + if (!error) + goto retry; + return ERR_PTR(error); + } return ERR_CAST(dentry); + } =20 if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) { dput(nd->path.dentry); --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6D4D363C71; Tue, 11 Nov 2025 14:13:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870414; cv=none; b=o+EaEDyNpEHC3IXc8eAo7V9WZEga8zCv4V/wWnQ6Tss70a5duwAQAnysoR4eCm94vWpy14yD9sA5pdo78glY6ygYAdGCOqeX3y8QNz0GR+h05t95xou65dey+Y2YxhkVlRrkthyqhM84zMyMNF7IvvW2pRbmVQhTRzzdbWT4OYI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870414; c=relaxed/simple; bh=xYYzPncnr5v6WTYsf79FmQQV0HF9Y2wtQ2qoyImEjMg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rgwDqTzcyWlfx80QEQ5UwSisMkmsDPMBzoPACuU+rqLIOdc7P7ltTXXLelOlIne7tXXBF5TJ1mBKpON8tNV/icb0vwXpSnn/A6SOUfsLyVj6bGSJYbKC85ccFv3FqqbnSpB68+dgS6jLIhWXhvgY7xC5MJwS51m4/Ky5jENF8sg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Q4kDu+k+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Q4kDu+k+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 255FAC4CEF7; Tue, 11 Nov 2025 14:13:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870414; bh=xYYzPncnr5v6WTYsf79FmQQV0HF9Y2wtQ2qoyImEjMg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Q4kDu+k+If9JEXW8BIUNK8FPt9mJ9+IxAJzmdBkSrWBzctyyrwqFdTtW9cgC2noOJ Ibwv54F574WmiFdFw2QMdCS7ZvrB8yRYAcEm8BwcnW7YjvzcVhRIOxAukZ6QLjxQ3W 1MifA6vO3zGCaFSzmtYEXkYk0mscZMC9fhsJu6tJELkJ1nei1hWFLnHS81SgXl57ts YdlKO712ByZzuN12iZ5NNUFADpf0BDcZ/ppIU1QdK/KV7zsdycJelayiv1wmBc9azT Hm18TSMcU/3a/+QCzzkqpj2q7+Ske7onNQ+WcSle+YbNt54r7Tx+LfgpbYahZ1iDXh iZYj/NhpGDJeQ== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:50 -0500 Subject: [PATCH v6 09/17] vfs: clean up argument list for vfs_create() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-9-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6754; i=jlayton@kernel.org; h=from:subject:message-id; bh=xYYzPncnr5v6WTYsf79FmQQV0HF9Y2wtQ2qoyImEjMg=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RoDrRWliVdlAWm7FbEld26hIGo4FNf+p2VI CX7IlZSJFWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaAAKCRAADmhBGVaC FYh6EAC1spozRwwDuXFZqsWAXuf9rmOCVnSEkdDZKWm2rCwdgiVoLrDOEfHkd+L8wEdgeMHsAAc xXS9f64/AelzlQ1E6LO+TJTCnFfmfDTWtZIBIVT/i3cRxJZ840kh7Dkrug4pu3Gufw/yoppfSQB WWNdEiMcfB64/o/0DgEDMSk7PaUok6TyB9kirxOMneOV10NEG8PLvvkWWhKurh1Ip/tkPL60Hd6 9eq4VlPQ3sfhwWIuZ3ugmsTDDruf+9d8gw63pFIBEhS7vtnXCjS4Z0lyQM1ePo6zBdED+Kl9VoC 62Z7NoMy8EoaxnyY+GSkFPSHuFblQzhwk9tL/OrKGVlkVF5QEqvivKuu42QWsOVJ2075HuCHWWp PoQWeOtcOLOZavNcz1TT17WtHAbuv89iCHPReGBVzyxq5K3xPUen+0qCJSLWn7Mu2jSB76puxxn qLA0pV67PXaCa2pK42pmiP3At5H/12HuRUHF1MHk2dXisAM7j46SArryIaZjEIkqVG5eQcCK194 1ee6SyEh6pxTKBz/gPRzZGzw73/4TiWHoWzp+mwgJhANokPqRs5acMmQRdPT//UBLIA9gdW+DjG oKt3tgzpiZWJfi1x9h+g+Tk6PYvk29R/cVoHJF/FLa05sgjWe2GJ+zzTPg0TWXZ9DvQECunzaDg BK+vI+1RzO8iZ+Q== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 As Neil points out: "I would be in favour of dropping the "dir" arg because it is always d_inode(dentry->d_parent) which is stable." ...and... "Also *every* caller of vfs_create() passes ".excl =3D true". So maybe we don't need that arg at all." Drop both arguments from vfs_create() and fix up the callers. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/ecryptfs/inode.c | 3 +-- fs/namei.c | 11 ++++------- fs/nfsd/nfs3proc.c | 2 +- fs/nfsd/vfs.c | 3 +-- fs/open.c | 4 +--- fs/overlayfs/overlayfs.h | 2 +- fs/smb/server/vfs.c | 3 +-- include/linux/fs.h | 3 +-- 8 files changed, 11 insertions(+), 20 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 88631291b32535f623a3fbe4ea9b6ed48a306ca0..d109e3763a88150bfe64cd2d556= 4dc9802ef3386 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -188,8 +188,7 @@ ecryptfs_do_create(struct inode *directory_inode, =20 rc =3D lock_parent(ecryptfs_dentry, &lower_dentry, &lower_dir); if (!rc) - rc =3D vfs_create(&nop_mnt_idmap, lower_dir, - lower_dentry, mode, true); + rc =3D vfs_create(&nop_mnt_idmap, lower_dentry, mode); if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc =3D [%d]\n", __func__, rc); diff --git a/fs/namei.c b/fs/namei.c index f439429bdfa271ccc64c937771ef4175597feb53..9586c6aba6eae05a9fc3c103b85= 01d98767bef53 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3461,10 +3461,8 @@ static inline umode_t vfs_prepare_mode(struct mnt_id= map *idmap, /** * vfs_create - create new file * @idmap: idmap of the mount the inode was found from - * @dir: inode of the parent directory * @dentry: dentry of the child file * @mode: mode of the child file - * @want_excl: whether the file must not yet exist * * Create a new file. * @@ -3474,9 +3472,9 @@ static inline umode_t vfs_prepare_mode(struct mnt_idm= ap *idmap, * On non-idmapped mounts or if permission checking is to be performed on = the * raw inode simply pass @nop_mnt_idmap. */ -int vfs_create(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry, umode_t mode, bool want_excl) +int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mod= e) { + struct inode *dir =3D d_inode(dentry->d_parent); int error; =20 error =3D may_create(idmap, dir, dentry); @@ -3490,7 +3488,7 @@ int vfs_create(struct mnt_idmap *idmap, struct inode = *dir, error =3D security_inode_create(dir, dentry, mode); if (error) return error; - error =3D dir->i_op->create(idmap, dir, dentry, mode, want_excl); + error =3D dir->i_op->create(idmap, dir, dentry, mode, true); if (!error) fsnotify_create(dir, dentry); return error; @@ -4383,8 +4381,7 @@ static int do_mknodat(int dfd, struct filename *name,= umode_t mode, idmap =3D mnt_idmap(path.mnt); switch (mode & S_IFMT) { case 0: case S_IFREG: - error =3D vfs_create(idmap, path.dentry->d_inode, - dentry, mode, true); + error =3D vfs_create(idmap, dentry, mode); if (!error) security_path_post_mknod(idmap, dentry); break; diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index b6d03e1ef5f7a5e8dd111b0d56c061f1e91abff7..30ea7ffa2affdb9a959b0fd15a6= 30de056d6dc3c 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -344,7 +344,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh= *fhp, status =3D fh_fill_pre_attrs(fhp); if (status !=3D nfs_ok) goto out; - host_err =3D vfs_create(&nop_mnt_idmap, inode, child, iap->ia_mode, true); + host_err =3D vfs_create(&nop_mnt_idmap, child, iap->ia_mode); if (host_err < 0) { status =3D nfserrno(host_err); goto out; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index c400ea94ff2e837fd59719bf2c4b79ef1d064743..464fd54675f3b16fce9ae5f05ad= 22e0e6b363eb3 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1552,8 +1552,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc= _fh *fhp, err =3D 0; switch (type) { case S_IFREG: - host_err =3D vfs_create(&nop_mnt_idmap, dirp, dchild, - iap->ia_mode, true); + host_err =3D vfs_create(&nop_mnt_idmap, dchild, iap->ia_mode); if (!host_err) nfsd_check_ignore_resizing(iap); break; diff --git a/fs/open.c b/fs/open.c index fdaa6f08f6f4cac5c2fefd3eafa5e430e51f3979..e440f58e3ce81e137aabdf00510= d839342a19219 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1171,9 +1171,7 @@ struct file *dentry_create(const struct path *path, i= nt flags, umode_t mode, if (IS_ERR(f)) return f; =20 - error =3D vfs_create(mnt_idmap(path->mnt), - d_inode(path->dentry->d_parent), - path->dentry, mode, true); + error =3D vfs_create(mnt_idmap(path->mnt), path->dentry, mode); if (!error) error =3D vfs_open(path, f); =20 diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index d215d7349489686b66bb66e939b27046f7d836f6..2bdc434941ebc70f6d4f57cca4f= 68125112a7bc4 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -235,7 +235,7 @@ static inline int ovl_do_create(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry, umode_t mode) { - int err =3D vfs_create(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, true); + int err =3D vfs_create(ovl_upper_mnt_idmap(ofs), dentry, mode); =20 pr_debug("create(%pd2, 0%o) =3D %i\n", dentry, mode, err); return err; diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index c5f0f3170d586cb2dc4d416b80948c642797fb82..83ece2de4b23bf9209137e7ca41= 4a72439b5cc2e 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -188,8 +188,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const cha= r *name, umode_t mode) } =20 mode |=3D S_IFREG; - err =3D vfs_create(mnt_idmap(path.mnt), d_inode(path.dentry), - dentry, mode, true); + err =3D vfs_create(mnt_idmap(path.mnt), dentry, mode); if (!err) { ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(dentry)); diff --git a/include/linux/fs.h b/include/linux/fs.h index 12873214e1c7811735ea5d2dee3d57e2a5604d8f..21876ef1fec90181b9878372c7c= 7e710773aae9f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2111,8 +2111,7 @@ bool inode_owner_or_capable(struct mnt_idmap *idmap, /* * VFS helper functions.. */ -int vfs_create(struct mnt_idmap *, struct inode *, - struct dentry *, umode_t, bool); +int vfs_create(struct mnt_idmap *, struct dentry *, umode_t); struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, struct delegated_inode *); int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BED3364EBC; Tue, 11 Nov 2025 14:13:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870418; cv=none; b=AJAGTz1xnHduls4Y3++Ia9AxJyzaX3aMeJ0AF1gNh0d/KVPci+ueHtzKbPnDFstbp8NLcO+noCVDv1Azrvm+/dK+ULNYDlk5erWEnP5Fnjt9R3OxJ9GqSA858STDYs2i4tMkwnhLYpV06u2kwvKhfZaUtnYncFuNuS53tKl/1u4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870418; c=relaxed/simple; bh=lN/bhsS6C0iz3//+qsII4EritkMB9eULzkMq+tuTUUM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bV1WHZTTTG9dwZeuowz7XRsCyYDGYBJQW1kxVMcdLDSMIYtVBx2/J2Klr/68JJU3MWe7xAXDi20Wx5ibO0xfl765RM8GBisI7Yk9WRXl1mmkVTDEwQF9v/1NKpX9UC6khJapqAFMSs3/wYQE0pZ0sdQdB2qAMnEQdwcDG3J3wRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bxpQbyBn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bxpQbyBn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B0078C2BC86; Tue, 11 Nov 2025 14:13:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870418; bh=lN/bhsS6C0iz3//+qsII4EritkMB9eULzkMq+tuTUUM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bxpQbyBnEDn4k2874wXDcs6fPo20+05L8C8tc4UkWZ+n61WuGEqY/QdQOqaP+uxZD p8MOsh4qzPx6KtoCfxJ9c2PmdL1+9nHeYWyh39lZ/JF9x7+v5ZPnFPu7gorPJGtZv3 X8cI+aurUhJnPCoD+4HTTKkmG5140yC2rmJcjFc25w/pXQAeCT4+NShXB/3nScMy3h W0XPXF84m5+HOARD0HZ9zMeg7GWK2fifdvLN84slz9fVWnMjs68HWqDoPZebuwXEVu b4ijoQWNPNeNugffPU3JvDoc7ArLg6O5YUycOL70rTqUJNtmgNPyoIXaij8DyHlJka /RiGPSMNVhZyQ== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:51 -0500 Subject: [PATCH v6 10/17] vfs: make vfs_create break delegations on parent directory Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-10-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7095; i=jlayton@kernel.org; h=from:subject:message-id; bh=lN/bhsS6C0iz3//+qsII4EritkMB9eULzkMq+tuTUUM=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RoDY3I/ZordAIE3HZI2IoRn2BQcUK7gh082 A6xqK+nn3eJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaAAKCRAADmhBGVaC FWWhEACfQTAsSvIZiFlM/og07msAYn4Zs0NFwDE2wjAEm21Se4GIhV6xFwICLJL0OaVUpEmCdcC MDxcvsPS2Gd6fTbY0E9iM/ex9R/0CBYTwc0aVFKLOlMXPbvo7kKfhF6/1wPUOeBdPjtZSISzxk2 rlyBvv1PG7RSTinK1wd0PePzJAdudVXHwk7rtkjuFIn3V6dHvoWZbS/G0qZBcNl0lEzz1Mhaja5 Usy1UVQ7T5gJmp4FvJXQ74nqPSoDEeasr+p5k7qpRU0J/KR71/DbO6UZO0fcCoBTV0DNDDdMzX3 xvvntFoxygTuazM/tFnMBLpgCvkK62o0SnSs2ReJbp0/Rt7MVsysbLQM4HWCpLmEdX83Ikbh5W0 DkmuTAdkWzsN1oQ7p4gwCNJYaabfctPyAbk7EbPAbkn5Q9loTZUMpqTmBQTK2cqenZnzdsVI+zo YdgeUPR6mYAGYV1d02dEAUJo+dQCu0IFn8MF5qnBiYCu9qlDWwg5OEDGxL5hbwJ/9JlV384zVkg cvYIbcXG2m8MpbqLrz07cgddIhWx5qQQYOCRyjzaRGEjnV9O8bw3X3TYvfDXklsftRyz8qNiObm 9e1lS4s/z/nBB9hdWLOm4VT+FAuw2K9G9QSCy4qNzYBmxSXbfHSrv0BBNFD3QBxMy/UhEimQlhh QY32I8+Q8J5Z6iQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. Add a delegated_inode parameter to vfs_create. Most callers are converted to pass in NULL, but do_mknodat() is changed to wait for a delegation break if there is one. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/ecryptfs/inode.c | 2 +- fs/namei.c | 15 +++++++++++++-- fs/nfsd/nfs3proc.c | 2 +- fs/nfsd/vfs.c | 2 +- fs/open.c | 2 +- fs/overlayfs/overlayfs.h | 2 +- fs/smb/server/vfs.c | 2 +- include/linux/fs.h | 3 ++- 8 files changed, 21 insertions(+), 9 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index d109e3763a88150bfe64cd2d5564dc9802ef3386..3341f00dd08753c8feab184dd82= b8bfa63d3724a 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -188,7 +188,7 @@ ecryptfs_do_create(struct inode *directory_inode, =20 rc =3D lock_parent(ecryptfs_dentry, &lower_dentry, &lower_dir); if (!rc) - rc =3D vfs_create(&nop_mnt_idmap, lower_dentry, mode); + rc =3D vfs_create(&nop_mnt_idmap, lower_dentry, mode, NULL); if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc =3D [%d]\n", __func__, rc); diff --git a/fs/namei.c b/fs/namei.c index 9586c6aba6eae05a9fc3c103b8501d98767bef53..b20f053374a578d36fb764e0df8= 0fb7db9230dbe 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3463,6 +3463,7 @@ static inline umode_t vfs_prepare_mode(struct mnt_idm= ap *idmap, * @idmap: idmap of the mount the inode was found from * @dentry: dentry of the child file * @mode: mode of the child file + * @di: returns parent inode, if the inode is delegated. * * Create a new file. * @@ -3472,7 +3473,8 @@ static inline umode_t vfs_prepare_mode(struct mnt_idm= ap *idmap, * On non-idmapped mounts or if permission checking is to be performed on = the * raw inode simply pass @nop_mnt_idmap. */ -int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mod= e) +int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mod= e, + struct delegated_inode *di) { struct inode *dir =3D d_inode(dentry->d_parent); int error; @@ -3486,6 +3488,9 @@ int vfs_create(struct mnt_idmap *idmap, struct dentry= *dentry, umode_t mode) =20 mode =3D vfs_prepare_mode(idmap, dir, mode, S_IALLUGO, S_IFREG); error =3D security_inode_create(dir, dentry, mode); + if (error) + return error; + error =3D try_break_deleg(dir, di); if (error) return error; error =3D dir->i_op->create(idmap, dir, dentry, mode, true); @@ -4358,6 +4363,7 @@ static int may_mknod(umode_t mode) static int do_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev) { + struct delegated_inode di =3D { }; struct mnt_idmap *idmap; struct dentry *dentry; struct path path; @@ -4381,7 +4387,7 @@ static int do_mknodat(int dfd, struct filename *name,= umode_t mode, idmap =3D mnt_idmap(path.mnt); switch (mode & S_IFMT) { case 0: case S_IFREG: - error =3D vfs_create(idmap, dentry, mode); + error =3D vfs_create(idmap, dentry, mode, &di); if (!error) security_path_post_mknod(idmap, dentry); break; @@ -4396,6 +4402,11 @@ static int do_mknodat(int dfd, struct filename *name= , umode_t mode, } out2: end_creating_path(&path, dentry); + if (is_delegated(&di)) { + error =3D break_deleg_wait(&di); + if (!error) + goto retry; + } if (retry_estale(error, lookup_flags)) { lookup_flags |=3D LOOKUP_REVAL; goto retry; diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 30ea7ffa2affdb9a959b0fd15a630de056d6dc3c..2cb972b5ed994d69995146aeeac= 8651c1c04fa46 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -344,7 +344,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh= *fhp, status =3D fh_fill_pre_attrs(fhp); if (status !=3D nfs_ok) goto out; - host_err =3D vfs_create(&nop_mnt_idmap, child, iap->ia_mode); + host_err =3D vfs_create(&nop_mnt_idmap, child, iap->ia_mode, NULL); if (host_err < 0) { status =3D nfserrno(host_err); goto out; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 464fd54675f3b16fce9ae5f05ad22e0e6b363eb3..de5f46f8c6d3ab24fabddeed9bd= 59adbe7a486df 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1552,7 +1552,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc= _fh *fhp, err =3D 0; switch (type) { case S_IFREG: - host_err =3D vfs_create(&nop_mnt_idmap, dchild, iap->ia_mode); + host_err =3D vfs_create(&nop_mnt_idmap, dchild, iap->ia_mode, NULL); if (!host_err) nfsd_check_ignore_resizing(iap); break; diff --git a/fs/open.c b/fs/open.c index e440f58e3ce81e137aabdf00510d839342a19219..92cf2e11781b0efd16fe0b75128= 6ce943ea6b4e2 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1171,7 +1171,7 @@ struct file *dentry_create(const struct path *path, i= nt flags, umode_t mode, if (IS_ERR(f)) return f; =20 - error =3D vfs_create(mnt_idmap(path->mnt), path->dentry, mode); + error =3D vfs_create(mnt_idmap(path->mnt), path->dentry, mode, NULL); if (!error) error =3D vfs_open(path, f); =20 diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 2bdc434941ebc70f6d4f57cca4f68125112a7bc4..e30441cc9c63ff8b6c055db80be= 7974501d0023b 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -235,7 +235,7 @@ static inline int ovl_do_create(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry, umode_t mode) { - int err =3D vfs_create(ovl_upper_mnt_idmap(ofs), dentry, mode); + int err =3D vfs_create(ovl_upper_mnt_idmap(ofs), dentry, mode, NULL); =20 pr_debug("create(%pd2, 0%o) =3D %i\n", dentry, mode, err); return err; diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 83ece2de4b23bf9209137e7ca414a72439b5cc2e..3747851b61c8bad4c00e49866c3= 80c32e9f53a4b 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -188,7 +188,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const cha= r *name, umode_t mode) } =20 mode |=3D S_IFREG; - err =3D vfs_create(mnt_idmap(path.mnt), dentry, mode); + err =3D vfs_create(mnt_idmap(path.mnt), dentry, mode, NULL); if (!err) { ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(dentry)); diff --git a/include/linux/fs.h b/include/linux/fs.h index 21876ef1fec90181b9878372c7c7e710773aae9f..83b05aec4e10c846d3168018fb6= 2284e45ceb1a8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2111,7 +2111,8 @@ bool inode_owner_or_capable(struct mnt_idmap *idmap, /* * VFS helper functions.. */ -int vfs_create(struct mnt_idmap *, struct dentry *, umode_t); +int vfs_create(struct mnt_idmap *, struct dentry *, umode_t, + struct delegated_inode *); struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, struct delegated_inode *); int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D5CCE3590CD; Tue, 11 Nov 2025 14:13:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870422; cv=none; b=CGvAaX0A3GbbC22uV+GD8sDwBKfuvpF4auCsXGEShYAmsaNsxnqfEWCyfvS1Loo0WswFNdrF+Opb0pk27I93bA3qEZ5qyVwfOpMZrjciPO16UcRKxxQx5sGUDD0iukvFmcMwLUfc3jT8nDY6pifvvYymaa393ypKSfP7GwyQCxk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870422; c=relaxed/simple; bh=enwRSJtPuTCJax9ReM6vLhCWhCDrTpDxateSqGDz3Cs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VHhz3jNjHtEpvBdZqF4bfZ+nwEt3AuOF4aPz03pJvGAg+JRYAD3cS8H69KpRj0xGh9GWid9fvSsvZ/rWm7VNUNzenSpnHjm7Lsr61r2n63n7fNeFIzzGlgFjz1S6ti3fYBy02labbOKR9kxyLtaqJNz8ZtwWv5fviGgxcyWeN8A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DIef8j7r; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DIef8j7r" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35047C4CEF7; Tue, 11 Nov 2025 14:13:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870421; bh=enwRSJtPuTCJax9ReM6vLhCWhCDrTpDxateSqGDz3Cs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DIef8j7r7j8m7Tz8L5B52pLCo3Tr3H6dhqoQI9CpG9CKEVZaOWAOyhvjOYa3esHUL 4kfccZHc6wskWH6PDxX5+aKdCViqMrL1pyW/2dDG3ubJHYw5tqDicSAac+noqfuujI 3KYzdtRSuA5qgP/PVwWIkJ+CNtmDxgfoXCX9aIMWeG0Z+gnd8Jb3VzxRih8TF6WhCF 6IALdlnsRFzI4qjORlb5c7gbbyXHbDpKn0fb026FgXGt90kzpAxdxyEi4yDKuh5s5b zn2qDhokgkbk3lmEdYa4JZd9DhsFC3cYprvsutdeqkVJH2QSgS/dNdUTKBJWfG/s0b K7M1c+zr8yTGw== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:52 -0500 Subject: [PATCH v6 11/17] vfs: make vfs_mknod break delegations on parent directory Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-11-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7475; i=jlayton@kernel.org; h=from:subject:message-id; bh=enwRSJtPuTCJax9ReM6vLhCWhCDrTpDxateSqGDz3Cs=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0Rpk1y1A8sNErwfj9qKhHQ3qmrpcxU+kMG/m T5Sv9ZuKLCJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaQAKCRAADmhBGVaC Fbw1D/9VBzZ+GGVQuKakhQAmX5EreXtzJQop2bC3CkININks1SHSMeUZnbUARdrH+lrQ4KKS5oB zCYfTg+pe3P35d9Oa0tzoQjv1Rgf6M952fdu9SUyUBsIYYIuHmQcITqzSFOzGarBJ2c4q8ULnWe 4RoJnhAQmnPRZxgo8toixcV1jCsQWGxkXo58pJhNiXr0VPLMoXPL+/4Gq2DnYXd/Ntng4U7GyJ5 0z0E4fMn72VE8q1NNLcR60mnuivpqWz+wsi+9q+LNVeHbls6xYMXO5Y6jynOhCB4CqjH4DBCGiP bCB0Vbe3f3CNyd9lACzATQ4WW48zuiKMmrAsNRc0m3ecaDbIO54crEHaiZOTICo6t2PVn8G1kds JJD6SXxg8A6CAr4jaRr6/zfMMebrlSkQoctomeJfqvP+LgjmJy4H0DegE7fxFRmdUtTy5euVGds +FFfy4TQZ9bgYuVNu28MzvrIYVSnv53fo03RmKrHC7CValqvyEXnOGOhNVUgUgNzrkiZfPQ7yGn 0YWo06+uu+4SEcVDzegD3ThyYcOaY1MJNjPKBo4c+2+NdJ4hR17ZAG5hI9kdvyyjsLUQpkfnIdw z29mMkH+hhBwpA2zubUrskuHXqa8LIn2Gt3UGEcmfULIf0Dfd480Buf7YIOysLrTZYsurL0ayCy By3ufBmx4MdUiaw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. Add a new delegated_inode pointer to vfs_mknod() and have the appropriate callers wait when there is an outstanding delegation. All other callers just set the pointer to NULL. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- drivers/base/devtmpfs.c | 2 +- fs/ecryptfs/inode.c | 2 +- fs/init.c | 2 +- fs/namei.c | 23 +++++++++++++++-------- fs/nfsd/vfs.c | 2 +- fs/overlayfs/overlayfs.h | 2 +- include/linux/fs.h | 4 ++-- net/unix/af_unix.c | 2 +- 8 files changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 104025104ef75381984fd94dfbd50feeaa8cdd22..2f576ecf18324f767cd5ac6cbd2= 8adbf9f46b958 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -231,7 +231,7 @@ static int handle_create(const char *nodename, umode_t = mode, kuid_t uid, return PTR_ERR(dentry); =20 err =3D vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode, - dev->devt); + dev->devt, NULL); if (!err) { struct iattr newattrs; =20 diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 3341f00dd08753c8feab184dd82b8bfa63d3724a..83f06452476dec4025cc8f50e08= 2ae6ccbbc7914 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -564,7 +564,7 @@ ecryptfs_mknod(struct mnt_idmap *idmap, struct inode *d= ir, rc =3D lock_parent(dentry, &lower_dentry, &lower_dir); if (!rc) rc =3D vfs_mknod(&nop_mnt_idmap, lower_dir, - lower_dentry, mode, dev); + lower_dentry, mode, dev, NULL); if (rc || d_really_is_negative(lower_dentry)) goto out; rc =3D ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); diff --git a/fs/init.c b/fs/init.c index 895f8a09a71acfd03e11164e3b441a7d4e2de146..4f02260dd65b0dfcbfbf5812d2e= c6a33444a3b1f 100644 --- a/fs/init.c +++ b/fs/init.c @@ -157,7 +157,7 @@ int __init init_mknod(const char *filename, umode_t mod= e, unsigned int dev) error =3D security_path_mknod(&path, dentry, mode, dev); if (!error) error =3D vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode, - dentry, mode, new_decode_dev(dev)); + dentry, mode, new_decode_dev(dev), NULL); end_creating_path(&path, dentry); return error; } diff --git a/fs/namei.c b/fs/namei.c index b20f053374a578d36fb764e0df80fb7db9230dbe..e9616134390fb7f0d09a759be69= bf677f8800bc5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4295,13 +4295,15 @@ inline struct dentry *start_creating_user_path( } EXPORT_SYMBOL(start_creating_user_path); =20 + /** * vfs_mknod - create device node or file - * @idmap: idmap of the mount the inode was found from - * @dir: inode of the parent directory - * @dentry: dentry of the child device node - * @mode: mode of the child device node - * @dev: device number of device to create + * @idmap: idmap of the mount the inode was found from + * @dir: inode of the parent directory + * @dentry: dentry of the child device node + * @mode: mode of the child device node + * @dev: device number of device to create + * @delegated_inode: returns parent inode, if the inode is delegated. * * Create a device node or file. * @@ -4312,7 +4314,8 @@ EXPORT_SYMBOL(start_creating_user_path); * raw inode simply pass @nop_mnt_idmap. */ int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry, umode_t mode, dev_t dev) + struct dentry *dentry, umode_t mode, dev_t dev, + struct delegated_inode *delegated_inode) { bool is_whiteout =3D S_ISCHR(mode) && dev =3D=3D WHITEOUT_DEV; int error =3D may_create(idmap, dir, dentry); @@ -4336,6 +4339,10 @@ int vfs_mknod(struct mnt_idmap *idmap, struct inode = *dir, if (error) return error; =20 + error =3D try_break_deleg(dir, delegated_inode); + if (error) + return error; + error =3D dir->i_op->mknod(idmap, dir, dentry, mode, dev); if (!error) fsnotify_create(dir, dentry); @@ -4393,11 +4400,11 @@ static int do_mknodat(int dfd, struct filename *nam= e, umode_t mode, break; case S_IFCHR: case S_IFBLK: error =3D vfs_mknod(idmap, path.dentry->d_inode, - dentry, mode, new_decode_dev(dev)); + dentry, mode, new_decode_dev(dev), &di); break; case S_IFIFO: case S_IFSOCK: error =3D vfs_mknod(idmap, path.dentry->d_inode, - dentry, mode, 0); + dentry, mode, 0, &di); break; } out2: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index de5f46f8c6d3ab24fabddeed9bd59adbe7a486df..6684935007b17ed40723ff0a744= 045fd187ace5e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1573,7 +1573,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc= _fh *fhp, case S_IFIFO: case S_IFSOCK: host_err =3D vfs_mknod(&nop_mnt_idmap, dirp, dchild, - iap->ia_mode, rdev); + iap->ia_mode, rdev, NULL); break; default: printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n", diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index e30441cc9c63ff8b6c055db80be7974501d0023b..afd95721f76ea761cfe7133c390= 2028550f3e359 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -257,7 +257,7 @@ static inline int ovl_do_mknod(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { - int err =3D vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev); + int err =3D vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev, N= ULL); =20 pr_debug("mknod(%pd2, 0%o, 0%o) =3D %i\n", dentry, mode, dev, err); return err; diff --git a/include/linux/fs.h b/include/linux/fs.h index 83b05aec4e10c846d3168018fb62284e45ceb1a8..1a5d86cfafaa97fc89d15cd1a15= 6968b8c3dd377 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2116,7 +2116,7 @@ int vfs_create(struct mnt_idmap *, struct dentry *, u= mode_t, struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, struct delegated_inode *); int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, - umode_t, dev_t); + umode_t, dev_t, struct delegated_inode *); int vfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *, const char *); int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *, @@ -2152,7 +2152,7 @@ static inline int vfs_whiteout(struct mnt_idmap *idma= p, struct inode *dir, struct dentry *dentry) { return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE, - WHITEOUT_DEV); + WHITEOUT_DEV, NULL); } =20 struct file *kernel_tmpfile_open(struct mnt_idmap *idmap, diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 768098dec2310008632558ae928703b37c3cc8ef..db1fd8d6a84c2c7c0d45b43d9c5= a936b3d491b7b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1399,7 +1399,7 @@ static int unix_bind_bsd(struct sock *sk, struct sock= addr_un *sunaddr, idmap =3D mnt_idmap(parent.mnt); err =3D security_path_mknod(&parent, dentry, mode, 0); if (!err) - err =3D vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0); + err =3D vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0, NULL); if (err) goto out_path; err =3D mutex_lock_interruptible(&u->bindlock); --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96FF1359712; Tue, 11 Nov 2025 14:13:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870425; cv=none; b=KZVngMyGkx7mKk3HKum9563ZrjT53PWdVPy1CglwR7Bw1aLnV4EfLactalixNZ3xrCZZpVsfrnZXIij/gJSBPuNaoKQRKhzeGAPskO2FhoFsX22wg/tJ/40TuyeOIZ1pPABzY6IR5saWBkNEhf0vM8FKxZ2CaAg/TMwNCO45M84= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870425; c=relaxed/simple; bh=J0QOs1yYKO976WkbjbVTMOts98MrgGnpdHVhMu0ydug=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VgUXYXN1soAuUO70L/9H68qcezsxaTcp+pEXo9gZGUUknVP6IsUtJGEZTvj+SBfPxdYFoD2IULFNduogZ7zmj1ma3wRHMYdjy4ZJB7wPVWQdLFwx3Ud9xBPI1HIaolWxn5BvEKKtwvP7ff+XxBR2YwGslzFKazFpQvugoKmsztM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qFtParE8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qFtParE8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B319CC113D0; Tue, 11 Nov 2025 14:13:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870425; bh=J0QOs1yYKO976WkbjbVTMOts98MrgGnpdHVhMu0ydug=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qFtParE8vcjto+w10i6Unke4GXFQCvaaEhfDUgLOoIkJoffRRSBgXTOsHhBmvemC/ dPwDiTLDx7ifWJ9uGrVxJVMAzoWmkRTG6R5R0cWItpKAFppCa76c8Hfnsv60FaZIxY EYo9eplN39NFqnfU0Vsq3fI7B7LCVMMzlm8IcH8D/WTWK1+0lktfg0UhJg9MEvm4SD 19wMjcUxg7cIK+NM9AHUmmPTnV4AIim3JBwcCq1HftXkCEoJC8Lk8qtdbWgJJvbi4y yTY/1KBcPs1SZPFVjCBFqpQnDe+svN4aqvZtyfo/+OzOc4WOJZHX8pq6+lkceTvs94 gqtARVRE+Myqw== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:53 -0500 Subject: [PATCH v6 12/17] vfs: make vfs_symlink break delegations on parent dir Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-12-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5708; i=jlayton@kernel.org; h=from:subject:message-id; bh=J0QOs1yYKO976WkbjbVTMOts98MrgGnpdHVhMu0ydug=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RpvfGYcDB1q4EPk3wOt3lgRL42wL5qTGHek 0VZgiTR54mJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaQAKCRAADmhBGVaC FbsoEADXBrpZURLTTjM4/GTX0A1YkXG/GkUFWYJBb/WmoD/jflh9Z2UNdxBP31kxD5gqIDBuFoS n6gsr22o8YA7mgeiKV3erHSVtV1i7yzj05g7aZqSbeEr9kLLRVfl/ImOsKfj+Pln6V3KPTlF+27 un9EE79TWYZit2BRnmWm857K4E2fMDf3Cm1ihgUtpz2A7Svn9QC2SBPRDkyCPTKx5N/nXdMRzCb FKghnxT5tJWxMh/daMTHf8Bu8jPrqKL19O363OHNwt1SSPwn7m3Ivv9PVaF1jeRK39YHrtfwDyQ +ionhobazjYNKwxtt8GyH92yLXDbx3y+ucrs1V2ONOrt32QDu4dw7UcWZqCLztfSfbjwmVzYutg /KVha+MeasPW1f1scjCKPX6dnEJkuy7BrVj5SQCtPBlM7ZxjSFbqeeQWHpNYhVIuKM05LWhF4Cg gd4ylwifux67UdEYRsAYoiQtJSQda74kcVjEBLR5UclBN+K5E14PQi5rHmza/r5aU74tiv3u4L+ V8qm77+Bz5fjFoN1n1/8KdCRXz16oWGfesLQ0xK6NX4GQbpS9rc7GafF8LzheV+TLzUbLK5bbPA wejTsAQ3TP+N7SLFkV6F+TOOqCxVc6nkY7awxZqgW15ANgay9GPR1aWChCJIW6khZp+J7nC/z2e bTifQC4vVf0arWA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 In order to add directory delegation support, we must break delegations on the parent on any change to the directory. Add a delegated_inode parameter to vfs_symlink() and have it break the delegation. do_symlinkat() can then wait on the delegation break before proceeding. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/ecryptfs/inode.c | 2 +- fs/init.c | 2 +- fs/namei.c | 16 ++++++++++++++-- fs/nfsd/vfs.c | 2 +- fs/overlayfs/overlayfs.h | 2 +- include/linux/fs.h | 2 +- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 83f06452476dec4025cc8f50e082ae6ccbbc7914..ba15e7359dfa6e150b577205991= 010873a633511 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -479,7 +479,7 @@ static int ecryptfs_symlink(struct mnt_idmap *idmap, if (rc) goto out_lock; rc =3D vfs_symlink(&nop_mnt_idmap, lower_dir, lower_dentry, - encoded_symname); + encoded_symname, NULL); kfree(encoded_symname); if (rc || d_really_is_negative(lower_dentry)) goto out_lock; diff --git a/fs/init.c b/fs/init.c index 4f02260dd65b0dfcbfbf5812d2ec6a33444a3b1f..e0f5429c0a49d046bd3f231a260= 954ed0f90ef44 100644 --- a/fs/init.c +++ b/fs/init.c @@ -209,7 +209,7 @@ int __init init_symlink(const char *oldname, const char= *newname) error =3D security_path_symlink(&path, dentry, oldname); if (!error) error =3D vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode, - dentry, oldname); + dentry, oldname, NULL); end_creating_path(&path, dentry); return error; } diff --git a/fs/namei.c b/fs/namei.c index e9616134390fb7f0d09a759be69bf677f8800bc5..d5ab28947b2b6c6e19c7bb4a914= 0ccec407dc07c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4845,6 +4845,7 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname) * @dir: inode of the parent directory * @dentry: dentry of the child symlink file * @oldname: name of the file to link to + * @delegated_inode: returns victim inode, if the inode is delegated. * * Create a symlink. * @@ -4855,7 +4856,8 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname) * raw inode simply pass @nop_mnt_idmap. */ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir, - struct dentry *dentry, const char *oldname) + struct dentry *dentry, const char *oldname, + struct delegated_inode *delegated_inode) { int error; =20 @@ -4870,6 +4872,10 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inod= e *dir, if (error) return error; =20 + error =3D try_break_deleg(dir, delegated_inode); + if (error) + return error; + error =3D dir->i_op->symlink(idmap, dir, dentry, oldname); if (!error) fsnotify_create(dir, dentry); @@ -4883,6 +4889,7 @@ int do_symlinkat(struct filename *from, int newdfd, s= truct filename *to) struct dentry *dentry; struct path path; unsigned int lookup_flags =3D 0; + struct delegated_inode delegated_inode =3D { }; =20 if (IS_ERR(from)) { error =3D PTR_ERR(from); @@ -4897,8 +4904,13 @@ int do_symlinkat(struct filename *from, int newdfd, = struct filename *to) error =3D security_path_symlink(&path, dentry, from->name); if (!error) error =3D vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode, - dentry, from->name); + dentry, from->name, &delegated_inode); end_creating_path(&path, dentry); + if (is_delegated(&delegated_inode)) { + error =3D break_deleg_wait(&delegated_inode); + if (!error) + goto retry; + } if (retry_estale(error, lookup_flags)) { lookup_flags |=3D LOOKUP_REVAL; goto retry; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6684935007b17ed40723ff0a744045fd187ace5e..28710da4cce7cc7fc1e14d29420= 239dc357316f6 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1742,7 +1742,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *f= hp, err =3D fh_fill_pre_attrs(fhp); if (err !=3D nfs_ok) goto out_unlock; - host_err =3D vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path); + host_err =3D vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path, NUL= L); err =3D nfserrno(host_err); cerr =3D fh_compose(resfhp, fhp->fh_export, dnew, fhp); if (!err) diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index afd95721f76ea761cfe7133c3902028550f3e359..5065961bd370628c9afe914ea57= 0d9998a096660 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -267,7 +267,7 @@ static inline int ovl_do_symlink(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry, const char *oldname) { - int err =3D vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname); + int err =3D vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname, N= ULL); =20 pr_debug("symlink(\"%s\", %pd2) =3D %i\n", oldname, dentry, err); return err; diff --git a/include/linux/fs.h b/include/linux/fs.h index 1a5d86cfafaa97fc89d15cd1a156968b8c3dd377..64323e618724bc20dc101db1303= 5b042f5f88e4d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2118,7 +2118,7 @@ struct dentry *vfs_mkdir(struct mnt_idmap *, struct i= node *, int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, umode_t, dev_t, struct delegated_inode *); int vfs_symlink(struct mnt_idmap *, struct inode *, - struct dentry *, const char *); + struct dentry *, const char *, struct delegated_inode *); int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *, struct dentry *, struct delegated_inode *); int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *, --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07EB1359F92; Tue, 11 Nov 2025 14:13:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870429; cv=none; b=byKc+z2l0CQFH7QtQpppW8NpEwvCCe/PyBccIIld3D3zm0nUtR5Xl1fzCcwOczL4YqPCfxiaZNXElgLd7enwfzSXeLaxFSSDWKCUKsDQmZqk0USvEAEID0GljsV3N1oj8pbM++jsFGJUcovsFTL9W/ie5mZZVK/QY4zpNXGsaEo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870429; c=relaxed/simple; bh=fAStZ1VGox28sSBTaeIOxtIwVEbCulrkhuzHCrifXdg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Jyb7uBFwedt32CL0rEvX9gIIzT3CCOFYAWBbaC5FhstG1Txzqy8FQBthqknPeqor0jOx1Qa5ejEjWjGQj4iH8h8iyRPz7z5wm3Kj9HEO3uR3ay7qbQN0YtS/DI3wqcYCEU8dUNrllR3lIDvs8f9PMMx3F1uhTfaBBykI1zN65Ns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=If61DYpt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="If61DYpt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4228DC4CEF7; Tue, 11 Nov 2025 14:13:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870428; bh=fAStZ1VGox28sSBTaeIOxtIwVEbCulrkhuzHCrifXdg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=If61DYptj2Johvj4/0m2cxn+Jtx6+aoRvnud/ewIdmU7XltDGeH4eF8ApjFSI8p5l lnJ7p5pHfiWY9VAIz8ULd/GGL10Bo1rTaWcSoOxXrV4YoF7dUsDUhRdfSKXFKqjLBR 4bYovpJS5+2rVJs/dj6U0k+Vc9PZ8vLRrX+GPSq1UTXg0eTqBTv17mhEHH9U/8qJps AecM198CDxKtyTburtc8E+EolPZSo7VY7uhafX1OEVF92DT+qeEbud4TGLZaF8kAyW Y3+7hqpqm4xIbM7ZN8Mvxy4JMFETlKhjeFeDbkMB1KZrgYGtNZd7+mgPko37LvY4RY kPvS68ayzmBtQ== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:54 -0500 Subject: [PATCH v6 13/17] filelock: lift the ban on directory leases in generic_setlease Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-13-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1772; i=jlayton@kernel.org; h=from:subject:message-id; bh=fAStZ1VGox28sSBTaeIOxtIwVEbCulrkhuzHCrifXdg=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RpBaIjdJGfeWQB08MiWg68vBQK/vGgJilx1 nTpnUBoo3aJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaQAKCRAADmhBGVaC FYItD/43NGFBQ5pVg7GHt8Zf/jcXtSjHtrYj/S2C7cYhT3FJf+kTEgrMJmzVHxFLgryrDWaQ/eF Hza74PqVL/HtkUFhWpnbE0T2jdxkSwo63YJ5SPRIY7nGLhiWwWMv6Sow1jmTurFzbDj23w8AGQY rKKF/WikvDHwpkauZgxO84lKW19Nm2Qxrbj2c65+pKBSSe78HGLoCk7WhQAg4VoNn4FH0nIiKwJ zRjj6qtxRPz0rzGoK9IchUm17FCzUCnohzcScWvZMRyE1hrJF+yKvx+wFwMdCUz7MMBP92PJ7RL +l0oBdrf9TuwtKYYQ4QcnCYevsCgAuHAunOxeyQ83zcISxxNXxt+ZllngERPizslssMyW6NY6xD HjDGAzJYWwEX0WkA+Rvc/4Kq567dEJe+u5IMSBzvgFeFw12HmcB9/mvHSD5KlkSJ21UXcH/dYa9 R56vExc39LcDoV5BPWE6CV62jc0YY/6WWXxNWO/YeDpyP3suDCkvJaIT/15e0s4i21Gp8T62+Ls cQRPYMGq2ORcvKEoO/OkzFlziji/kzKo2otj/FtxNr4sTKdWPrOpA2t+iyvfaErv5FCJHToXT8f aH+eQnX2C5+Q/whAqJdJmLVWmR3LOgrSry1lK8+XC93T+ov3d33KDhqIEHltVL6aUJGMQf+zNi3 +WIHlD8FCIVSy1g== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 With the addition of the try_break_lease calls in directory changing operations, allow generic_setlease to hand them out. Write leases on directories are never allowed however, so continue to reject them. For now, there is no API for requesting delegations from userland, so ensure that userland is prevented from acquiring a lease on a directory. Reviewed-by: Jan Kara Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/locks.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index f5b210a2dc34c70ac36e972436c62482bbe32ca6..dd290a87f58eb5d522f03fa99d6= 12fbad84dacf3 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1935,14 +1935,19 @@ static int generic_delete_lease(struct file *filp, = void *owner) int generic_setlease(struct file *filp, int arg, struct file_lease **flp, void **priv) { - if (!S_ISREG(file_inode(filp)->i_mode)) + struct inode *inode =3D file_inode(filp); + + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) return -EINVAL; =20 switch (arg) { case F_UNLCK: return generic_delete_lease(filp, *priv); - case F_RDLCK: case F_WRLCK: + if (S_ISDIR(inode->i_mode)) + return -EINVAL; + fallthrough; + case F_RDLCK: if (!(*flp)->fl_lmops->lm_break) { WARN_ON_ONCE(1); return -ENOLCK; @@ -2071,6 +2076,9 @@ static int do_fcntl_add_lease(unsigned int fd, struct= file *filp, int arg) */ int fcntl_setlease(unsigned int fd, struct file *filp, int arg) { + if (S_ISDIR(file_inode(filp)->i_mode)) + return -EINVAL; + if (arg =3D=3D F_UNLCK) return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp); return do_fcntl_add_lease(fd, filp, arg); --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DC5536A009; Tue, 11 Nov 2025 14:13:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870432; cv=none; b=WHKXHHHYFM/bed8JOmEwZ+A0gaRkiNGhP/35s+EUcyaPBKv6Yyz5EuB7PVqCX6QIh7+nLmRw+j8t7U+U5LlaWqbkXmadjW45HOBlq6dbosRk80pivJw4uxyVEVYFfLLnwoKCGFR1VY0jMvgkRs5MooJN7+6auk3qbLVIpF10zCc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870432; c=relaxed/simple; bh=G0m38I9O+Xy6gwLh+3apyDgrdcwDPUcZ3ukE2nInTzc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P8MiVuUO7q3kasl88jHsdLQ+PT7TgorTZl/jFKd1ip7AytvUakmCEw9TlFXrXYxHweMjDl7IELHutjhMnc7DcEYLUHmQ1eTtk8vLzgeMJkjgHHq3h+5PzzbTz6nN/OOO+RubLHSGLZokLcUmXxsWO6WGRjNnZ/jtpnOJTPhGEHg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EZLaam8q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EZLaam8q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D7F58C4CEF5; Tue, 11 Nov 2025 14:13:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870432; bh=G0m38I9O+Xy6gwLh+3apyDgrdcwDPUcZ3ukE2nInTzc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EZLaam8q/m84Mccq+ldTfGb+lLthgofVrxSTgxHFYHR1TWI++tIQRNxZ3J1ojMO0O SiPWgNfBOFegNiK7NsI0koXwxKEfzFQkjhMGK1ZtEOB2nsdGxZ7yAPbOULjcJ4cJoZ wmi5KCmG9A9mRVeQhAC1rVphapZA9c+7U318FF/qZF5d3W4bjlnxq1RO+Bw5B7PXV8 uvaL7FcMeiDh90o2Bhokqx+lOQL+bgv+K82CLURrQntQl/NNH05+nH9wN5G9Mez9yo bkuBI2WXUY+y+NXdAet/3WVtQQzJRiX9yfsXhUTPx/zWlYFHv8ZBBFgtUi1XLtGPvS R+O9UODI4zV0Q== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:55 -0500 Subject: [PATCH v6 14/17] nfsd: allow filecache to hold S_IFDIR files Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-14-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7422; i=jlayton@kernel.org; h=from:subject:message-id; bh=G0m38I9O+Xy6gwLh+3apyDgrdcwDPUcZ3ukE2nInTzc=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RpOizcbshl/yDe1GjOVijvlEC/q+naK70vy r1p/G8Ic1WJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEaQAKCRAADmhBGVaC FVwaEACDPSsx8HV1P28gwfKCVWI8Ggqa7BtmlcmDK3voXsl0rsp0W/bUh3//MrdHtVX009HifS7 tJXmygEZdc8cG94a2KEjC6l5fjy8MpMPPYvZzFC5qZgMW9IYrKojPTAH+ZZ7/a5vkU1HDmWFb5w /0soT0SR+WKjN/Fwr16rngLjxAZRhgxqjxJK+isSljY1onAODZBDUNkXOHITdUsucXeH78gZ5/W 5r4+J/qGjIHnWwaWwHWQNdR41jOwZVikpeUByG07dO4AtywL2yusH8vhFzLLngB2sMOGwt/R8BI qCRgJ4OocKrnvgEbct99oA5hh81/D7mNHRb+uOTV+k+QIBb7a0oV83DfrQ2WqARWYXwwRGOh+E5 leVal53BSqIn69LyWSSPmXzJB/ZrxN4eo6VRRMGmKy8a+V9KthGHSXGVqgODknWOEHUfxiFVXkZ N8lUFWge3ltW2QacfuLUi5pSxkr6KaQGAFfrAOhprnIp4HyrjxKV9InmvyLCQiLOfVvpoVv5kkp gr3cpN225kk0uFlZAERdqyzgAQTc8B0du/XQERJnoPasXQqazOmvsrfv11Y9Eo5oXkqTL5PtSJK 1pW+AVN4/+95JBwgU/SZDcjaM21mkhx7lv2qBYF6wIh91k8R/NbP+aW5JxkzpvAcvcA/koyG5m/ X9Of3lTKkG3DRjw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The filecache infrastructure will only handle S_IFREG files at the moment. Directory delegations will require adding support for opening S_IFDIR inodes. Plumb a "type" argument into nfsd_file_do_acquire() and have all of the existing callers set it to S_IFREG. Add a new nfsd_file_acquire_dir() wrapper that nfsd can call to request a nfsd_file that holds a directory open. For now, there is no need for a fsnotify_mark for directories, as CB_NOTIFY is not yet supported. Change nfsd_file_do_acquire() to avoid allocating one for non-S_IFREG inodes. Reviewed-by: Chuck Lever Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/nfsd/filecache.c | 57 ++++++++++++++++++++++++++++++++++++++++---------= ---- fs/nfsd/filecache.h | 2 ++ fs/nfsd/vfs.c | 5 +++-- fs/nfsd/vfs.h | 2 +- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index a238b6725008a5c2988bd3da874d1f34ee778437..93798575b8075c63f95cd415b6d= 24df706ada0f6 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -1086,7 +1086,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct n= et *net, struct auth_domain *client, struct svc_fh *fhp, unsigned int may_flags, struct file *file, - struct nfsd_file **pnf, bool want_gc) + umode_t type, bool want_gc, struct nfsd_file **pnf) { unsigned char need =3D may_flags & NFSD_FILE_MAY_MASK; struct nfsd_file *new, *nf; @@ -1097,13 +1097,13 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct= net *net, int ret; =20 retry: - if (rqstp) { - status =3D fh_verify(rqstp, fhp, S_IFREG, + if (rqstp) + status =3D fh_verify(rqstp, fhp, type, may_flags|NFSD_MAY_OWNER_OVERRIDE); - } else { - status =3D fh_verify_local(net, cred, client, fhp, S_IFREG, + else + status =3D fh_verify_local(net, cred, client, fhp, type, may_flags|NFSD_MAY_OWNER_OVERRIDE); - } + if (status !=3D nfs_ok) return status; inode =3D d_inode(fhp->fh_dentry); @@ -1176,15 +1176,18 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct= net *net, =20 open_file: trace_nfsd_file_alloc(nf); - nf->nf_mark =3D nfsd_file_mark_find_or_create(inode); - if (nf->nf_mark) { + + if (type =3D=3D S_IFREG) + nf->nf_mark =3D nfsd_file_mark_find_or_create(inode); + + if (type !=3D S_IFREG || nf->nf_mark) { if (file) { get_file(file); nf->nf_file =3D file; status =3D nfs_ok; trace_nfsd_file_opened(nf, status); } else { - ret =3D nfsd_open_verified(fhp, may_flags, &nf->nf_file); + ret =3D nfsd_open_verified(fhp, type, may_flags, &nf->nf_file); if (ret =3D=3D -EOPENSTALE && stale_retry) { stale_retry =3D false; nfsd_file_unhash(nf); @@ -1246,7 +1249,7 @@ nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct s= vc_fh *fhp, unsigned int may_flags, struct nfsd_file **pnf) { return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, - fhp, may_flags, NULL, pnf, true); + fhp, may_flags, NULL, S_IFREG, true, pnf); } =20 /** @@ -1271,7 +1274,7 @@ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_= fh *fhp, unsigned int may_flags, struct nfsd_file **pnf) { return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, - fhp, may_flags, NULL, pnf, false); + fhp, may_flags, NULL, S_IFREG, false, pnf); } =20 /** @@ -1314,8 +1317,8 @@ nfsd_file_acquire_local(struct net *net, struct svc_c= red *cred, const struct cred *save_cred =3D get_current_cred(); __be32 beres; =20 - beres =3D nfsd_file_do_acquire(NULL, net, cred, client, - fhp, may_flags, NULL, pnf, false); + beres =3D nfsd_file_do_acquire(NULL, net, cred, client, fhp, may_flags, + NULL, S_IFREG, false, pnf); put_cred(revert_creds(save_cred)); return beres; } @@ -1344,7 +1347,33 @@ nfsd_file_acquire_opened(struct svc_rqst *rqstp, str= uct svc_fh *fhp, struct nfsd_file **pnf) { return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, - fhp, may_flags, file, pnf, false); + fhp, may_flags, file, S_IFREG, false, pnf); +} + +/** + * nfsd_file_acquire_dir - Get a struct nfsd_file with an open directory + * @rqstp: the RPC transaction being executed + * @fhp: the NFS filehandle of the file to be opened + * @pnf: OUT: new or found "struct nfsd_file" object + * + * The nfsd_file_object returned by this API is reference-counted + * but not garbage-collected. The object is unhashed after the + * final nfsd_file_put(). This opens directories only, and only + * in O_RDONLY mode. + * + * Return values: + * %nfs_ok - @pnf points to an nfsd_file with its reference + * count boosted. + * + * On error, an nfsstat value in network byte order is returned. + */ +__be32 +nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, + struct nfsd_file **pnf) +{ + return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, fhp, + NFSD_MAY_READ|NFSD_MAY_64BIT_COOKIE, + NULL, S_IFDIR, false, pnf); } =20 /* diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h index e3d6ca2b60308e5e91ba4bb32d935f54527d8bda..b383dbc5b9218d21a29b852572f= 80fab08de9fa9 100644 --- a/fs/nfsd/filecache.h +++ b/fs/nfsd/filecache.h @@ -82,5 +82,7 @@ __be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, s= truct svc_fh *fhp, __be32 nfsd_file_acquire_local(struct net *net, struct svc_cred *cred, struct auth_domain *client, struct svc_fh *fhp, unsigned int may_flags, struct nfsd_file **pnf); +__be32 nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, + struct nfsd_file **pnf); int nfsd_file_cache_stats_show(struct seq_file *m, void *v); #endif /* _FS_NFSD_FILECACHE_H */ diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 28710da4cce7cc7fc1e14d29420239dc357316f6..8c3ffacc533e9de0d506fb2ec22= 2387446ba8e9f 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -959,15 +959,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp,= umode_t type, /** * nfsd_open_verified - Open a regular file for the filecache * @fhp: NFS filehandle of the file to open + * @type: S_IFMT inode type allowed (0 means any type is allowed) * @may_flags: internal permission flags * @filp: OUT: open "struct file *" * * Returns zero on success, or a negative errno value. */ int -nfsd_open_verified(struct svc_fh *fhp, int may_flags, struct file **filp) +nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, struct= file **filp) { - return __nfsd_open(fhp, S_IFREG, may_flags, filp); + return __nfsd_open(fhp, type, may_flags, filp); } =20 /* diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 0c0292611c6de3daf6f3ed51e2c61c0ad2751de4..09de48c50cbef8e7c4828b38dcb= 663b529514a30 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -114,7 +114,7 @@ __be32 nfsd_setxattr(struct svc_rqst *rqstp, struct sv= c_fh *fhp, int nfsd_open_break_lease(struct inode *, int); __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, int, struct file **); -int nfsd_open_verified(struct svc_fh *fhp, int may_flags, +int nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, struct file **filp); __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D493936A01B; Tue, 11 Nov 2025 14:13:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870436; cv=none; b=OcQXE+cPGqsyLv927iY6O2BhZoX+WRPtX3uGwzAb7DrzZ3MsbxgymclN/qfwyM6se8vrqJBibgaogjg+54ZySFWaFFy623X64XQ2W1uOt037oOMNsxdSK1WNb+2Tb6WHirKfJnp4CUKyiohkOdHVh8HWJw6qJ1SP6BxlioRsryk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870436; c=relaxed/simple; bh=yulLeJZn1mX+cSvDuaJcOgJyv8hH6SOCKBioc8zxN20=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MW7gLPvmtd72ECZ+R3JsK1cN/p5KJGZN1A7BCYRDvylaBc1kY90D1Wx/lkZDJHppym3IXdWYpEuZvqz6Ly9DeDa+axGFjL/uGz18/nmP4d+xDC5bZuu3uJmEAh0n/2PgIUy7ITzg3pUOEnLd2xhxLk3HN/goLT8/ZiHeaajoG6A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sBriXazs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sBriXazs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 583DCC16AAE; Tue, 11 Nov 2025 14:13:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870435; bh=yulLeJZn1mX+cSvDuaJcOgJyv8hH6SOCKBioc8zxN20=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sBriXazsGvwzX8sfYOAoq6YOjrzTz9m9C6K3aqyg8PpCzCvY4JZCBPE/4yEdrOZEf mmTxKD173a6r0SHow4/2EFTDvLoFkwn48cHacDAMVlecwUdWmlsZc0wJdIB9GEQKwJ D2JywEUtfYXroa7hEvkEiSrzT7w/UqlpNMAWA1O+fw2BnIAfaQsyLjV8afDcZVKz/a +Z83MmQj30CuG37weAlonjzUFETuXkx2NtJbxgGIu6VV8fnPT6s45Std0bcyWWospw IEwx5myLSUQ20/Pn6xs6rEEp8pA/qwqxnXvdm38SR6KxTth51lkCN2VXp0wy1cp3Qo Ybz2ZgymNvQaQ== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:56 -0500 Subject: [PATCH v6 15/17] nfsd: allow DELEGRETURN on directories Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-15-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1228; i=jlayton@kernel.org; h=from:subject:message-id; bh=yulLeJZn1mX+cSvDuaJcOgJyv8hH6SOCKBioc8zxN20=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RqWSACxk50vyNQMQP4PR4OYc58LpTlSBjs+ 2A3IG27B8GJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEagAKCRAADmhBGVaC FQvtEADOPlbj0rDKzXOHmg547rZDguovFl+WNjgEQKxUTxUVDdL+z5sZUZu6KbqrqOGnOcTI93b 2ehze8MZsDpKz9NZBbNebzkoP38Zy5LqyOZQ7usMdiqHJBuPBrQsf+eWRrS3YDbgzenrb57Zg2x 2nCAwKgvgJjnXm0XfsNr/32e3wiG/w0+YY+DiPFyPormrp1V2WXVZy5rh+CLDGgGlUC5+yDIhuV XY54Vm3ysK1JAxWFpbtm92jXv4h6R0BAtNDTQOl2BkKz6bW6NxVhOfyyhSRAsaYG7Bq/L9IdDhx ybJl6qI5M9PdQgU3+PMnEKZ2IgpMwunMqBKF2MZQNh+QgQeyM7KCj6569LMPUr0nceynnnDzx+V NrWN17J6UJZNzuKzf2/CLz5XnxkPeaYSIYZTzJ8RnvDLSAL/wf+l+4O3QWp2o+Itsq/d/Da2UVO TxuTKygqAYG/jtKEkj4jAZZ7hFtlvKIbD79hMw/HgX/4XgtuhEtHKOQSp2wC16sk6O79TvPQJIf 1qFWAwdSFlstTGK0Si5Qo6j19/1LwoyCgY6vhsPBPHnqFmhvPNDWZfwY++1qv7dBQ22+2R+RusH E+Q9C90sZUwVl9T8J6lkjJ3PebfP8xhj+M5bbhpBt4mzEvGSBt52fXHmN9zBCw1IlJAm7/ppEfI wfUiePRk+RTI7yQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 As Trond pointed out: "...provided that the presented stateid is actually valid, it is also sufficient to uniquely identify the file to which it is associated (see RFC8881 Section 8.2.4), so the filehandle should be considered mostly irrelevant for operations like DELEGRETURN." Don't ask fh_verify to filter on file type. Reviewed-by: Chuck Lever Reviewed-by: NeilBrown Signed-off-by: Jeff Layton --- fs/nfsd/nfs4state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 81fa7cc6c77b3cdc5ff22bc60ab0654f95dc258d..da66798023aba4c36c38208cec7= 333db237e46e0 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -7828,7 +7828,8 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd= 4_compound_state *cstate, __be32 status; struct nfsd_net *nn =3D net_generic(SVC_NET(rqstp), nfsd_net_id); =20 - if ((status =3D fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) + status =3D fh_verify(rqstp, &cstate->current_fh, 0, 0); + if (status) return status; =20 status =3D nfsd4_lookup_stateid(cstate, stateid, SC_TYPE_DELEG, SC_STATUS= _REVOKED, &s, nn); --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EE9C35A92F; Tue, 11 Nov 2025 14:13:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870439; cv=none; b=Myxs/OupMXoA5pgOLqEPSx2v0FFzHj6NvtHQP9lrm+grBh2QKRCutNvY0MIJ/vfeXt80Ou7KL7FHk3pKAjZkvrc50EvHUd873vRyPntageovI4KuEe+wTmJ8VuaxAepNnEJtES/bvk31ei2udJV6P8lmqDSvOa+FisUcfDc5fi4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870439; c=relaxed/simple; bh=8uFhmfmnSTsd3LwYNioQRWlGjzSH6flkvXdmZ7xJmTo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TiKSySlJp56JQYLf+Y4Lm8hLmGNEg+GzFkKUNr1/W76GNTHAuUDBvd4011Rb8tzWF9/AbXK+E3/lf9qPVd0A0DPVTDkH0Xw5SGkpzi6PlCLptlpZXurd6UNaYzjQF7eI4C9gepaYiCU2cA/7eW5ZbvAa81ZJo1aDyaB3RCnFQ0I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ADE4zx0U; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ADE4zx0U" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED3C1C19425; Tue, 11 Nov 2025 14:13:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870439; bh=8uFhmfmnSTsd3LwYNioQRWlGjzSH6flkvXdmZ7xJmTo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ADE4zx0U+dY3ymbgLF76eruT+Tdmizqc2sh3/Vj3CpBjwMEuYXST47ozKP0T3bGjz vFs0GKFXxp1KtJkYYrU3wmmLdjUMv0hCF3gVnjsvhqE29aEeqs1EvsMgjSmLJIg0ro y2lar4xW9fO4gCmuGrj/9ZGqxmTxj4xc/AV1ICwvBocGUPaKHFd/z/mSihN5Sf3dxE ir3mIJvN+H4WcT/j4wMGfgyEt28XjtUkajXW1UAIXB2JEyHsD0Bohi2M5waUCyd+7h pQHyzg49qSv4xKEesf0eIPII8bUlmHtOTp6yNX1lQYaSjJQ//QLgDE8qSGMP7Gd0Gw 3eAduSIGUok/A== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:57 -0500 Subject: [PATCH v6 16/17] nfsd: wire up GET_DIR_DELEGATION handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-16-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5577; i=jlayton@kernel.org; h=from:subject:message-id; bh=8uFhmfmnSTsd3LwYNioQRWlGjzSH6flkvXdmZ7xJmTo=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0RqrbaxwqjXBw/mCwGTDoNyTUQGYEkLVKKY0 K5KHGxCcBuJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEagAKCRAADmhBGVaC FfT5D/9PCXSsP2elpTVOuR7M5QMEnbqXo6/Pafr32iIbZKEHRIvpPFy/AULK6Py64dziwrsNhvH lTuY+MhqG75BSG2tV/5ONaBGZxohCd060io1H6ESXBRA5gRA9OuMf6oj0zCbNqfAd7sRfUqkZnK qs4FRciJ2xnU6EmA59xO6PJTDFs4tGOChglK1cORgu8tPtf4N86k5iGaZ1v9XWszw5Isone4lO5 Opia27Tfp/sWCUfj76aSqctmL3hQ3f/MBwmgVkGkG6Tgi67HzqHJd6XkjA/l1W1pi/6qOze8x2a 8Mxc7EQ6ikWT2PxAZ11moyBCUDk9az954nk/OAh0jAhKRRhHuYZsP5NtQWg5T9lfos53ABxEMvh 1iKInFzDMD4B2w5+ER4TWlKwCM6eT8jYy09RweRL3IkvREhvafN8aS6+EwvVzFGdyo5vjslVYKF jIVGj2enlslQjsZM1UnXwz0dF9gXpiFVqK7RzH01CHop7ri5xPXLGGQ1/4h4AH9oLjDKIS4xuH4 /FL0PAraASQjoLs45opepzKwEWFsm+GryWtwoKo/eOxEUDjIjQRmItsftNAVXb8b76owKaD+NeK sNMK9iCXBcQWywbivwYrjbK7IQeEXV27xaqNVaxx+aFezi12nOsH055sd6mpKx8NqGHmSn/4zv2 AtLXlGi4T94YgJw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add a new routine for acquiring a read delegation on a directory. These are recallable-only delegations with no support for CB_NOTIFY. That will be added in a later phase. Since the same CB_RECALL/DELEGRETURN infrastructure is used for regular and directory delegations, a normal nfs4_delegation is used to represent a directory delegation. Reviewed-by: NeilBrown Reviewed-by: Chuck Lever Signed-off-by: Jeff Layton --- fs/nfsd/nfs4proc.c | 22 +++++++++++- fs/nfsd/nfs4state.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ fs/nfsd/state.h | 5 +++ 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index e466cf52d7d7e1a78c3a469613a85ab3546d6d17..517968dddf4a33651313658d300= f9f929f83c5af 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2341,6 +2341,13 @@ nfsd4_get_dir_delegation(struct svc_rqst *rqstp, union nfsd4_op_u *u) { struct nfsd4_get_dir_delegation *gdd =3D &u->get_dir_delegation; + struct nfs4_delegation *dd; + struct nfsd_file *nf; + __be32 status; + + status =3D nfsd_file_acquire_dir(rqstp, &cstate->current_fh, &nf); + if (status !=3D nfs_ok) + return status; =20 /* * RFC 8881, section 18.39.3 says: @@ -2354,7 +2361,20 @@ nfsd4_get_dir_delegation(struct svc_rqst *rqstp, * return NFS4_OK with a non-fatal status of GDD4_UNAVAIL in this * situation. */ - gdd->gddrnf_status =3D GDD4_UNAVAIL; + dd =3D nfsd_get_dir_deleg(cstate, gdd, nf); + nfsd_file_put(nf); + if (IS_ERR(dd)) { + int err =3D PTR_ERR(dd); + + if (err !=3D -EAGAIN) + return nfserrno(err); + gdd->gddrnf_status =3D GDD4_UNAVAIL; + return nfs_ok; + } + + gdd->gddrnf_status =3D GDD4_OK; + memcpy(&gdd->gddr_stateid, &dd->dl_stid.sc_stateid, sizeof(gdd->gddr_stat= eid)); + nfs4_put_stid(&dd->dl_stid); return nfs_ok; } =20 diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index da66798023aba4c36c38208cec7333db237e46e0..8f8c9385101e15b64883eabec71= 775f26b14f890 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -9347,3 +9347,103 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp= , struct dentry *dentry, nfs4_put_stid(&dp->dl_stid); return status; } + +/** + * nfsd_get_dir_deleg - attempt to get a directory delegation + * @cstate: compound state + * @gdd: GET_DIR_DELEGATION arg/resp structure + * @nf: nfsd_file opened on the directory + * + * Given a GET_DIR_DELEGATION request @gdd, attempt to acquire a delegation + * on the directory to which @nf refers. Note that this does not set up any + * sort of async notifications for the delegation. + */ +struct nfs4_delegation * +nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate, + struct nfsd4_get_dir_delegation *gdd, + struct nfsd_file *nf) +{ + struct nfs4_client *clp =3D cstate->clp; + struct nfs4_delegation *dp; + struct file_lease *fl; + struct nfs4_file *fp, *rfp; + int status =3D 0; + + fp =3D nfsd4_alloc_file(); + if (!fp) + return ERR_PTR(-ENOMEM); + + nfsd4_file_init(&cstate->current_fh, fp); + + rfp =3D nfsd4_file_hash_insert(fp, &cstate->current_fh); + if (unlikely(!rfp)) { + put_nfs4_file(fp); + return ERR_PTR(-ENOMEM); + } + + if (rfp !=3D fp) { + put_nfs4_file(fp); + fp =3D rfp; + } + + /* if this client already has one, return that it's unavailable */ + spin_lock(&state_lock); + spin_lock(&fp->fi_lock); + /* existing delegation? */ + if (nfs4_delegation_exists(clp, fp)) { + status =3D -EAGAIN; + } else if (!fp->fi_deleg_file) { + fp->fi_deleg_file =3D nfsd_file_get(nf); + fp->fi_delegees =3D 1; + } else { + ++fp->fi_delegees; + } + spin_unlock(&fp->fi_lock); + spin_unlock(&state_lock); + + if (status) { + put_nfs4_file(fp); + return ERR_PTR(status); + } + + /* Try to set up the lease */ + status =3D -ENOMEM; + dp =3D alloc_init_deleg(clp, fp, NULL, NFS4_OPEN_DELEGATE_READ); + if (!dp) + goto out_delegees; + + fl =3D nfs4_alloc_init_lease(dp); + if (!fl) + goto out_put_stid; + + status =3D kernel_setlease(nf->nf_file, + fl->c.flc_type, &fl, NULL); + if (fl) + locks_free_lease(fl); + if (status) + goto out_put_stid; + + /* + * Now, try to hash it. This can fail if we race another nfsd task + * trying to set a delegation on the same file. If that happens, + * then just say UNAVAIL. + */ + spin_lock(&state_lock); + spin_lock(&clp->cl_lock); + spin_lock(&fp->fi_lock); + status =3D hash_delegation_locked(dp, fp); + spin_unlock(&fp->fi_lock); + spin_unlock(&clp->cl_lock); + spin_unlock(&state_lock); + + if (!status) + return dp; + + /* Something failed. Drop the lease and clean up the stid */ + kernel_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp); +out_put_stid: + nfs4_put_stid(&dp->dl_stid); +out_delegees: + put_deleg_file(fp); + return ERR_PTR(status); +} diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 1e736f4024263ffa9c93bcc9ec48f44566a8cc77..b052c1effdc5356487c610db972= 8df8ecfe851d4 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -867,4 +867,9 @@ static inline bool try_to_expire_client(struct nfs4_cli= ent *clp) =20 extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_delegation **pdp); + +struct nfsd4_get_dir_delegation; +struct nfs4_delegation *nfsd_get_dir_deleg(struct nfsd4_compound_state *cs= tate, + struct nfsd4_get_dir_delegation *gdd, + struct nfsd_file *nf); #endif /* NFSD4_STATE_H */ --=20 2.51.1 From nobody Fri Dec 19 14:21:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 392E236C59A; Tue, 11 Nov 2025 14:14:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870443; cv=none; b=ag+VwmvkdMVTeKRZXDa18VuSjyN0iB6S56/pecTRdylOoVQ7eoNzogzK2pn1fUoWhWWrxXstsaqfujoJKejzSDojOJM7jFHCh7+PbMrDsJJp5bFtuk2LOLozCDLwvt5TcXt8yDUwtqoPEvE6d6UNgXBw3z7o2UfKRq0AyV+kcGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762870443; c=relaxed/simple; bh=WdewGaiNuFLjHV1a6vCFo/mDFJ2AWK1PFe+Yl6HB3Sk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Cr2+r9Q7SwfHi3K7CshA3FjCficCwZYKOJqd5GNKFo1wUSlVdGjIV3x6RbJAXR19TiFRb9KUdrDofKeya3leu0AVWCxEnFEwxtiMXkDaD80ERdzdoSdiyziu6TtQbP7u8IEjyNybPRVj9iilO0TWXGRyKANgSMvN7xQ+exmM6pQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l15myyQI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="l15myyQI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6EF65C4CEF7; Tue, 11 Nov 2025 14:13:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762870442; bh=WdewGaiNuFLjHV1a6vCFo/mDFJ2AWK1PFe+Yl6HB3Sk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=l15myyQIerMvxjgtiRi6NwuRnkXFNTFcl60S3EzEy5KHr7vD5SJE25gbpJBLscxRe tZ+TF5RNMOPAgumvBWteGwwBJqcf/CpQtr1SDnn2Rjrtj9qBBzArMZhh9ddqoy+CjD rvTeM4E+m/QTBMkeNes1o7UL6DzVXut+2zpjb68DQap317Td29xpx5LijMTQkSRYKl u362c7yWxTpdQpWZRy4Cy44JvutBF7vCD8hQbVAdRMSv7eWTv3fv3e+VkGXDNHcVET +oXc4M7SafwrMJyCrtHM68p4NBgut2PRkYGSmg89k3LjKveh8qwKqXKPJD+iUnEfw9 4Rcb0wgf3KpcQ== From: Jeff Layton Date: Tue, 11 Nov 2025 09:12:58 -0500 Subject: [PATCH v6 17/17] vfs: expose delegation support to userland Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251111-dir-deleg-ro-v6-17-52f3feebb2f2@kernel.org> References: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> In-Reply-To: <20251111-dir-deleg-ro-v6-0-52f3feebb2f2@kernel.org> To: Miklos Szeredi , Alexander Viro , Christian Brauner , Jan Kara , Chuck Lever , Alexander Aring , Trond Myklebust , Anna Schumaker , Steve French , Paulo Alcantara , Ronnie Sahlberg , Shyam Prasad N , Tom Talpey , Bharath SM , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , David Howells , Tyler Hicks , NeilBrown , Olga Kornievskaia , Dai Ngo , Amir Goldstein , Namjae Jeon , Steve French , Sergey Senozhatsky , Carlos Maiolino , Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, netfs@lists.linux.dev, ecryptfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-xfs@vger.kernel.org, netdev@vger.kernel.org, linux-api@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6536; i=jlayton@kernel.org; h=from:subject:message-id; bh=WdewGaiNuFLjHV1a6vCFo/mDFJ2AWK1PFe+Yl6HB3Sk=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpE0Rqurk9cWPo6zP4fAmosJ6He97p9pqHQES7s Z06KXXBPjWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaRNEagAKCRAADmhBGVaC FTB/EACh5AspYIZTqRbll6q3mdwbK586tz7VH6SHn0JNvaDbeCV5/kAN0/r/8NI5lSY/RXE9gfA NjDm600CiqSZi94ckvFWfZdcUb/cwo7kbMk4UQHL+JH8fcRjqE1v2KGmf8gFejRebq7xo4/BxLa 3r+EIRxQoWimgPyhqtSPeBGqq2KOdBrYWqzAB6NZdULUezfg4g5aHo7aPxHtn4P0n4ZUMIdpJ8J 7z0K+s6lGWBNtXTFb3pSiNF7NXM3amOPp4TYrxSMmigVmvBD/kdoy2UOyGr4hMWx/DawdzNuBxQ vwgik4WPHaUMdUZBS+7wPoEJnDML2IRdKFET2wLPlN6X/Xf4vA3t4sC7Z0g+u8gFNjKLB0S+6O0 rM58JVJ8PvU4+PAUQsabbYf0YWm+49DC03SLQrOKX/oNFKaP1PSJFmzzqH/I1Tu0xd8usz4Lzvn HPjh1KW+KhUOtuUphSu/+eCRdEOc3vU9X9QYvPeSLdFurXnezJvxuEedvoaYop03JBRZ3kZzo/H Sr4QfnmZ+D7XqOdSPKDdz5IplJfDj71bOagfmFVc5ckULbrLCbrGmeESpfEqEqNbtiTVmq8QRX+ AChQAZDZPCkee/EMaXoyb3CsgpEUzjpyhGQSFi6zLmXSviCpp4yfqo3tkyxqpoqiakzaqXVIzui g4ecbM/7WKg19EQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Now that support for recallable directory delegations is available, expose this functionality to userland with new F_SETDELEG and F_GETDELEG commands for fcntl(). Note that this also allows userland to request a FL_DELEG type lease on files too. Userland applications that do will get signalled when there are metadata changes in addition to just data changes (which is a limitation of FL_LEASE leases). These commands accept a new "struct delegation" argument that contains a flags field for future expansion. Signed-off-by: Jeff Layton --- fs/fcntl.c | 13 +++++++++++++ fs/locks.c | 45 ++++++++++++++++++++++++++++++++++++++++--= --- include/linux/filelock.h | 12 ++++++++++++ include/uapi/linux/fcntl.h | 11 +++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index 72f8433d9109889eecef56b32d20a85b4e12ea44..f93dbca0843557d197bd1e02351= 9cfa0f00ad78f 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -445,6 +445,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned= long arg, struct file *filp) { void __user *argp =3D (void __user *)arg; + struct delegation deleg; int argi =3D (int)arg; struct flock flock; long err =3D -EINVAL; @@ -550,6 +551,18 @@ static long do_fcntl(int fd, unsigned int cmd, unsigne= d long arg, case F_SET_RW_HINT: err =3D fcntl_set_rw_hint(filp, arg); break; + case F_GETDELEG: + if (copy_from_user(&deleg, argp, sizeof(deleg))) + return -EFAULT; + err =3D fcntl_getdeleg(filp, &deleg); + if (!err && copy_to_user(argp, &deleg, sizeof(deleg))) + return -EFAULT; + break; + case F_SETDELEG: + if (copy_from_user(&deleg, argp, sizeof(deleg))) + return -EFAULT; + err =3D fcntl_setdeleg(fd, filp, &deleg); + break; default: break; } diff --git a/fs/locks.c b/fs/locks.c index dd290a87f58eb5d522f03fa99d612fbad84dacf3..7f4ccc7974bc8d3e82500ee692c= 6520b53f2280f 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1703,7 +1703,7 @@ EXPORT_SYMBOL(lease_get_mtime); * XXX: sfr & willy disagree over whether F_INPROGRESS * should be returned to userspace. */ -int fcntl_getlease(struct file *filp) +static int __fcntl_getlease(struct file *filp, unsigned int flavor) { struct file_lease *fl; struct inode *inode =3D file_inode(filp); @@ -1719,7 +1719,8 @@ int fcntl_getlease(struct file *filp) list_for_each_entry(fl, &ctx->flc_lease, c.flc_list) { if (fl->c.flc_file !=3D filp) continue; - type =3D target_leasetype(fl); + if (fl->c.flc_flags & flavor) + type =3D target_leasetype(fl); break; } spin_unlock(&ctx->flc_lock); @@ -1730,6 +1731,19 @@ int fcntl_getlease(struct file *filp) return type; } =20 +int fcntl_getlease(struct file *filp) +{ + return __fcntl_getlease(filp, FL_LEASE); +} + +int fcntl_getdeleg(struct file *filp, struct delegation *deleg) +{ + if (deleg->d_flags !=3D 0 || deleg->__pad !=3D 0) + return -EINVAL; + deleg->d_type =3D __fcntl_getlease(filp, FL_DELEG); + return 0; +} + /** * check_conflicting_open - see if the given file points to an inode that = has * an existing open that would conflict with the @@ -2039,13 +2053,13 @@ vfs_setlease(struct file *filp, int arg, struct fil= e_lease **lease, void **priv) } EXPORT_SYMBOL_GPL(vfs_setlease); =20 -static int do_fcntl_add_lease(unsigned int fd, struct file *filp, int arg) +static int do_fcntl_add_lease(unsigned int fd, struct file *filp, unsigned= int flavor, int arg) { struct file_lease *fl; struct fasync_struct *new; int error; =20 - fl =3D lease_alloc(filp, FL_LEASE, arg); + fl =3D lease_alloc(filp, flavor, arg); if (IS_ERR(fl)) return PTR_ERR(fl); =20 @@ -2081,7 +2095,28 @@ int fcntl_setlease(unsigned int fd, struct file *fil= p, int arg) =20 if (arg =3D=3D F_UNLCK) return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp); - return do_fcntl_add_lease(fd, filp, arg); + return do_fcntl_add_lease(fd, filp, FL_LEASE, arg); +} + +/** + * fcntl_setdeleg - sets a delegation on an open file + * @fd: open file descriptor + * @filp: file pointer + * @deleg: delegation request from userland + * + * Call this fcntl to establish a delegation on the file. + * Note that you also need to call %F_SETSIG to + * receive a signal when the lease is broken. + */ +int fcntl_setdeleg(unsigned int fd, struct file *filp, struct delegation *= deleg) +{ + /* For now, no flags are supported */ + if (deleg->d_flags !=3D 0 || deleg->__pad !=3D 0) + return -EINVAL; + + if (deleg->d_type =3D=3D F_UNLCK) + return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp); + return do_fcntl_add_lease(fd, filp, FL_DELEG, deleg->d_type); } =20 /** diff --git a/include/linux/filelock.h b/include/linux/filelock.h index 208d108df2d73a9df65e5dc9968d074af385f881..54b824c05299261e6bd6acc4175= cb277ea35b35d 100644 --- a/include/linux/filelock.h +++ b/include/linux/filelock.h @@ -159,6 +159,8 @@ int fcntl_setlk64(unsigned int, struct file *, unsigned= int, =20 int fcntl_setlease(unsigned int fd, struct file *filp, int arg); int fcntl_getlease(struct file *filp); +int fcntl_setdeleg(unsigned int fd, struct file *filp, struct delegation *= deleg); +int fcntl_getdeleg(struct file *filp, struct delegation *deleg); =20 static inline bool lock_is_unlock(struct file_lock *fl) { @@ -278,6 +280,16 @@ static inline int fcntl_getlease(struct file *filp) return F_UNLCK; } =20 +static inline int fcntl_setdeleg(unsigned int fd, struct file *filp, struc= t delegation *deleg) +{ + return -EINVAL; +} + +static inline int fcntl_getdeleg(struct file *filp, struct delegation *del= eg) +{ + return -EINVAL; +} + static inline bool lock_is_unlock(struct file_lock *fl) { return false; diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h index 3741ea1b73d8500061567b6590ccf5fb4c6770f0..008fac15e573084a9b48e4e9915= 28b4363c54047 100644 --- a/include/uapi/linux/fcntl.h +++ b/include/uapi/linux/fcntl.h @@ -79,6 +79,17 @@ */ #define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET =20 +/* Set/Get delegations */ +#define F_GETDELEG (F_LINUX_SPECIFIC_BASE + 15) +#define F_SETDELEG (F_LINUX_SPECIFIC_BASE + 16) + +/* Argument structure for F_GETDELEG and F_SETDELEG */ +struct delegation { + uint32_t d_flags; /* Must be 0 */ + uint16_t d_type; /* F_RDLCK, F_WRLCK, F_UNLCK */ + uint16_t __pad; /* Must be 0 */ +}; + /* * Types of directory notifications that may be requested. */ --=20 2.51.1