Linux CIFS filesystem development
 help / color / mirror / Atom feed
* [PATCH v2 01/14] fixes for vfs_lookup_open, and integration with nfsd
@ 2026-09-19  2:06 NeilBrown
  2026-09-19  2:06 ` [PATCH v2 01/14] VFS: revise and expand documentation for atomic_open NeilBrown
                   ` (14 more replies)
  0 siblings, 15 replies; 48+ messages in thread
From: NeilBrown @ 2026-09-19  2:06 UTC (permalink / raw)
  To: Alexander Viro, Christian Brauner, Chuck Lever, Jeff Layton,
	Jori Koolstra, Mateusz Guzik, Dorjoy Chowdhury
  Cc: Trond Myklebust, Anna Schumaker, Andreas Gruenbacher, gfs2,
	Ilya Dryomov, Alex Markuze, Viacheslav Dubeyko, ceph-devel,
	Paulo Alcantara, Namjae Jeon, linux-cifs, linux-fsdevel,
	linux-nfs

Greetings.

 NFSv4 has an "OPEN" request which combines lookup and create and
 truncate and permission checks etc much like the open() syscall.  When
 nfsd implements this, I want it to share a much code as (reasonably)
 possible with the open() paths - in particular I want it to use lookup_open() 
 and so that it uses ->atomic_open() the same way that other code does.
 (Longer term I want to make some locking changes and having all the code
 central makes that easier.)
 vfs_lookup_open() is a step towards that  but it isn't quite ready yet.
 This series aims to make it ready, then use it.

 A particular issue is that using __O_REGULAR exactly meets the needs of
 nfsd (it doesn't want to open anything else) but the errors returned by
 __O_REGULAR aren't what nfsd needs.  nfsd needs to know if it was a
 directory, or a symlink, or something else.

 I don't think __O_REGULAR should cause symlinks to result in -EFTYPE.
 If a symlink is found, then it should be followed.  That is what
 happens with filesystems that don't support ->atomic_open, but some
 ->atomic_open handlers return -EFTYPE for symlinks when __O_REGULAR is
 present.  I think that O_NOFOLLOW can affect how symlink are handled,
 but where possible it is best to just return the symlink to the caller
 and let it figure out what to do.

 For directories, nfsd wants EISDIR rather than EFTYPE.  It may be that
 user-space could benefit from seeing EISDIR too, but that is a separate
 issue.  So I want ->atomic_open to return EISDIR (if it returns an
 error at all) rather than EFTYPE if a directory is found.  VFS code can
 then map that to EFTYPE if needed.

 So the first few patches in this series improve the documentation for
 atomic_open and then make changes to nfs, gfs2, ceph, cifs to better
 match this documentation.  I would appreciate an Ack-by (or whatever
 else might be appropriate) from fs maintainers for those.

 Subsequent patches make changes to vfs_lookup_open() and then to nfsd
 to use it.

 A significant change here is that opening a file with
 O_NONBLOCK|O_CREAT will result in -EWOULDBLOCK if a delegation
 exists on the parent directory - currently it blocks.
 Jeff - could you comment on that change (07/14)?

 There are quite a lot of changes here since my previous post,
 particularly the changes to various filesystems.
 I've stopped trying to return the dentry from vfs_lookup_open()
 in the error case - no-one liked that.

 Thanks for your time,
 NeilBrown


 [PATCH v2 01/14] VFS: revise and expand documentation for
 [PATCH v2 02/14] nfs: correctly handle NFS4ERR_WRONG_TYPE from v4
 [PATCH v2 03/14] gfs2: simplify atomic_open handling.
 [PATCH v2 04/14] ceph: simplify atomic_open to use finish_no_open()
 [PATCH v2 05/14] cifs: allow -EISDIR precedence over -EFTYPE in
 [PATCH v2 06/14] vfs: add some allowed open flags to
 [PATCH v2 07/14] vfs: O_NONBLOCK|O_CREAT open shouldn't wait for
 [PATCH v2 08/14] vfs: don't return -ENODEV from vfs_lookup_open()
 [PATCH v2 09/14] vfs: change vfs_lookup_open() to use do_open(), not
 [PATCH v2 10/14] nfsd: make EEXIST checks in nfsd4_create_file() more
 [PATCH v2 11/14] nfsd: check for mountpoints after non-creating open.
 [PATCH v2 12/14] nfsd: switch NFS4 OPEN to use vfs_lookup_open()
 [PATCH v2 13/14] nfsd: change nfsd_check_obj_isreg() to use nfs error
 [PATCH v2 14/14] nfsd: use vfs_lookup_open() for non-creating open

^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [PATCH v2 11/14] nfsd: check for mountpoints after non-creating open.
@ 2026-09-20 17:08 Chuck Lever
  0 siblings, 0 replies; 48+ messages in thread
From: Chuck Lever @ 2026-09-20 17:08 UTC (permalink / raw)
  To: neilb
  Cc: viro, brauner, jlayton, jkoolstra, mjguzik, dorjoychy111, trondmy,
	anna, agruenba, gfs2, idryomov, amarkuze, slava, ceph-devel, pc,
	linkinjeon, linux-cifs, linux-fsdevel, linux-nfs

On 9/18/26 9:26 PM, NeilBrown wrote:
> From: NeilBrown <neil@brown.name>
> 
> A file can be a mountpoint for nfsd purposes when it isn't in the
> dcache.  This happens when it is a junction (nfsd4_is_junction()).
> So when we open a file and find that it already existed though
> not in the dcache, we have to check if it is a mountpoint (or junction)
> and potentially follow the junction.
> 
> So move the mountpoint crossing code in nfsd4_create_file() to a new
> label at the end of the function and goto there both when an in-dcache
> lookup finds an existing file, and when vfs_lookup_open() finds an
> existing file.
> 
> Signed-off-by: NeilBrown <neil@brown.name>

At this point in the series, nfsd4_create_file() still calls the local
do_lookup_open() helper. Nothing under fs/nfsd calls vfs_lookup_open()
until 12/14. Can the last sentence name do_lookup_open() instead?


> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index 6e443503d0b7..3d37754f787b 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c

[ ... ]

> @@ -339,21 +340,8 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>  						    open->op_fnamelen),
>  					  parent.dentry);
>  		if (child && !IS_ERR(child) && d_is_reg(child) &&
> -		    unlikely(nfsd_mountpoint(child, fhp->fh_export))) {

[ ... ]

> +		    unlikely(nfsd_mountpoint(child, fhp->fh_export)))
> +			goto do_cross_mnt;
>  		if (!IS_ERR(child))
>  			dput(child);
>  	}
> @@ -466,6 +454,14 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>  			status = nfserr_exist;
>  			goto out;
>  		}
> +		/* We opened an existing file, it might be a junction. */
> +		if (unlikely(nfsd_mountpoint(child, fhp->fh_export) == 1)) {
> +			dget(child);
> +			nfsd_filp_close(open->op_filp);
> +			open->op_filp = NULL;
> +			goto do_cross_mnt;
> +		}

Can this leak the dentry and export references held in resfhp? By the
time this branch runs, resfhp has already been composed, just above:

	status = fh_compose(resfhp, fhp->fh_export, child, fhp);
	if (status != nfs_ok)
		goto out;

and do_cross_mnt then calls fh_compose(resfhp, ...) a second time.
fh_compose() releases its target only when ref_fh == fhp, which is not
the case here, so it complains and then overwrites both pointers:

fs/nfsd/nfsfh.c:fh_compose() {
    ...
	if (fhp->fh_dentry) {
		printk(KERN_ERR "fh_compose: fh %pd2 not initialized!\n",
		       dentry);
	}
    ...
	fhp->fh_dentry = dget(dentry); /* our internal copy */
	fhp->fh_export = exp_get(exp);
    ...
}

The goto from the try_lookup_noperm() check is fine, since it is taken
before resfhp is composed. Calling fh_put(resfhp) before this goto might
be enough.

Nit: The dcache check above tests nfsd_mountpoint() for nonzero while
this one tests for == 1. I think that works because a d_managed()
dentry (return value 2) is pinned in the dcache, so the earlier check
always catches it. Is that the reasoning? If so, could the comment say
that? nfsd_mountpoint() also returns 1 for NFSEXP_V4ROOT exports, so
it isn't only junctions that arrive here.


> +
>  		/* NFSv4 protocol requires change attributes
>  		 * even though no change happened.
>  		 */
> @@ -511,6 +507,21 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>  out:
>  	nfsd_attrs_free(&attrs);
>  	return status;
> +
> +do_cross_mnt:
> +	exp = exp_get(fhp->fh_export);
> +
> +	status = nfsd_cross_mnt(rqstp, &child, &exp);
> +	if (status == nfs_ok)
> +		status = fh_compose(resfhp, exp,
> +				    child, fhp);
> +	fh_fill_post_noop(fhp);
> +	open->op_truncate =
> +		(iap->ia_valid & ATTR_SIZE) &&
> +		!iap->ia_size;

Nit: The non-crossing path includes d_is_reg(child) in this expression:

	open->op_truncate = (d_is_reg(child) &&
			     (iap->ia_valid & ATTR_SIZE) &&
			     !iap->ia_size);

After nfsd_cross_mnt(), child might no longer be a regular file.
do_open_lookup() rejects that via nfsd_check_obj_isreg() before
op_truncate is used, so nothing breaks. Perhaps the two expressions
should match?


> +	dput(child);
> +	exp_put(exp);
> +	goto out;
>  }


-- 
Chuck Lever (Come to NFS Bake-a-thon! https://nfsv4bat.org)

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2026-09-29 22:04 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-19  2:06 [PATCH v2 01/14] fixes for vfs_lookup_open, and integration with nfsd NeilBrown
2026-09-19  2:06 ` [PATCH v2 01/14] VFS: revise and expand documentation for atomic_open NeilBrown
2026-09-24 12:25   ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 02/14] nfs: correctly handle NFS4ERR_WRONG_TYPE from v4 OPEN request NeilBrown
2026-09-24 12:55   ` Jeff Layton
2026-09-24 13:01   ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 03/14] gfs2: simplify atomic_open handling NeilBrown
2026-09-19 16:49   ` Andreas Gruenbacher
2026-09-19 22:22     ` NeilBrown
2026-09-20 16:31       ` Andreas Gruenbacher
2026-09-22 21:16         ` NeilBrown
2026-09-19  2:06 ` [PATCH v2 04/14] ceph: simplify atomic_open to use finish_no_open() NeilBrown
2026-09-24 13:02   ` Jeff Layton
2026-09-25 21:49     ` NeilBrown
2026-09-26 11:48       ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 05/14] cifs: allow -EISDIR precedence over -EFTYPE in __cifs_do_create() NeilBrown
2026-09-23  5:54   ` Namjae Jeon
2026-09-23  6:50     ` NeilBrown
2026-09-23  7:52       ` Namjae Jeon
2026-09-23  8:13   ` Namjae Jeon
2026-09-19  2:06 ` [PATCH v2 06/14] vfs: add some allowed open flags to vfs_lookup_open() NeilBrown
2026-09-24 12:54   ` Jeff Layton
2026-09-29 15:18   ` Jori Koolstra
2026-09-29 22:04     ` NeilBrown
2026-09-19  2:06 ` [PATCH v2 07/14] vfs: O_NONBLOCK|O_CREAT open shouldn't wait for directory delegation NeilBrown
2026-09-24 12:51   ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 08/14] vfs: don't return -ENODEV from vfs_lookup_open() NeilBrown
2026-09-24 13:07   ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 09/14] vfs: change vfs_lookup_open() to use do_open(), not vfs_open() NeilBrown
2026-09-24 13:13   ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 10/14] nfsd: make EEXIST checks in nfsd4_create_file() more consistent NeilBrown
2026-09-24 13:23   ` Jeff Layton
2026-09-25 21:57     ` NeilBrown
2026-09-19  2:06 ` [PATCH v2 11/14] nfsd: check for mountpoints after non-creating open NeilBrown
2026-09-24 13:03   ` Jeff Layton
2026-09-25 22:14     ` NeilBrown
2026-09-19  2:06 ` [PATCH v2 12/14] nfsd: switch NFS4 OPEN to use vfs_lookup_open() NeilBrown
2026-09-20 17:10   ` Chuck Lever
2026-09-22 21:55     ` NeilBrown
2026-09-23  4:07       ` NeilBrown
2026-09-19  2:06 ` [PATCH v2 13/14] nfsd: change nfsd_check_obj_isreg() to use nfs error codes NeilBrown
2026-09-24 13:25   ` Jeff Layton
2026-09-19  2:06 ` [PATCH v2 14/14] nfsd: use vfs_lookup_open() for non-creating open requests too NeilBrown
2026-09-20 17:13   ` Chuck Lever
2026-09-25 22:26     ` NeilBrown
2026-09-25 16:04 ` [PATCH v2 01/14] fixes for vfs_lookup_open, and integration with nfsd Christian Brauner
2026-09-25 16:56   ` Chuck Lever
  -- strict thread matches above, loose matches on Subject: below --
2026-09-20 17:08 [PATCH v2 11/14] nfsd: check for mountpoints after non-creating open Chuck Lever

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox