mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
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: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: NeilBrown <neil@brown.name> Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20251111-dir-deleg-ro-v6-14-52f3feebb2f2@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
committed by
Christian Brauner
parent
d0eab9fc10
commit
544a0ee152
@@ -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 @@ out:
|
||||
|
||||
open_file:
|
||||
trace_nfsd_file_alloc(nf);
|
||||
nf->nf_mark = nfsd_file_mark_find_or_create(inode);
|
||||
if (nf->nf_mark) {
|
||||
|
||||
if (type == S_IFREG)
|
||||
nf->nf_mark = nfsd_file_mark_find_or_create(inode);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -959,15 +959,16 @@ retry:
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user