Unverified Commit 544a0ee1 authored by Jeff Layton's avatar Jeff Layton Committed by Christian Brauner
Browse files

nfsd: allow filecache to hold S_IFDIR files



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: default avatarChuck Lever <chuck.lever@oracle.com>
Reviewed-by: default avatarNeilBrown <neil@brown.name>
Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20251111-dir-deleg-ro-v6-14-52f3feebb2f2@kernel.org


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent d0eab9fc
Loading
Loading
Loading
Loading
+43 −14
Original line number Diff line number Diff line
@@ -1086,7 +1086,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *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 = 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;

retry:
	if (rqstp) {
		status = fh_verify(rqstp, fhp, S_IFREG,
	if (rqstp)
		status = fh_verify(rqstp, fhp, type,
				   may_flags|NFSD_MAY_OWNER_OVERRIDE);
	} else {
		status = fh_verify_local(net, cred, client, fhp, S_IFREG,
	else
		status = fh_verify_local(net, cred, client, fhp, type,
					 may_flags|NFSD_MAY_OWNER_OVERRIDE);
	}

	if (status != nfs_ok)
		return status;
	inode = d_inode(fhp->fh_dentry);
@@ -1176,15 +1176,18 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,

open_file:
	trace_nfsd_file_alloc(nf);

	if (type == S_IFREG)
		nf->nf_mark = nfsd_file_mark_find_or_create(inode);
	if (nf->nf_mark) {

	if (type != S_IFREG || nf->nf_mark) {
		if (file) {
			get_file(file);
			nf->nf_file = file;
			status = nfs_ok;
			trace_nfsd_file_opened(nf, status);
		} else {
			ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file);
			ret = nfsd_open_verified(fhp, type, may_flags, &nf->nf_file);
			if (ret == -EOPENSTALE && stale_retry) {
				stale_retry = false;
				nfsd_file_unhash(nf);
@@ -1246,7 +1249,7 @@ nfsd_file_acquire_gc(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, true);
				    fhp, may_flags, NULL, S_IFREG, true, pnf);
}

/**
@@ -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);
}

/**
@@ -1314,8 +1317,8 @@ nfsd_file_acquire_local(struct net *net, struct svc_cred *cred,
	const struct cred *save_cred = get_current_cred();
	__be32 beres;

	beres = nfsd_file_do_acquire(NULL, net, cred, client,
				     fhp, may_flags, NULL, pnf, false);
	beres = 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, struct 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);
}

/*
+2 −0
Original line number Diff line number Diff line
@@ -82,5 +82,7 @@ __be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct 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 */
+3 −2
Original line number Diff line number Diff line
@@ -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);
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ __be32 nfsd_setxattr(struct svc_rqst *rqstp, struct svc_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,