Skip to content

Commit 544a0ee

Browse files
jtlaytonbrauner
authored andcommitted
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>
1 parent d0eab9f commit 544a0ee

4 files changed

Lines changed: 49 additions & 17 deletions

File tree

fs/nfsd/filecache.c

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
10861086
struct auth_domain *client,
10871087
struct svc_fh *fhp,
10881088
unsigned int may_flags, struct file *file,
1089-
struct nfsd_file **pnf, bool want_gc)
1089+
umode_t type, bool want_gc, struct nfsd_file **pnf)
10901090
{
10911091
unsigned char need = may_flags & NFSD_FILE_MAY_MASK;
10921092
struct nfsd_file *new, *nf;
@@ -1097,13 +1097,13 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
10971097
int ret;
10981098

10991099
retry:
1100-
if (rqstp) {
1101-
status = fh_verify(rqstp, fhp, S_IFREG,
1100+
if (rqstp)
1101+
status = fh_verify(rqstp, fhp, type,
11021102
may_flags|NFSD_MAY_OWNER_OVERRIDE);
1103-
} else {
1104-
status = fh_verify_local(net, cred, client, fhp, S_IFREG,
1103+
else
1104+
status = fh_verify_local(net, cred, client, fhp, type,
11051105
may_flags|NFSD_MAY_OWNER_OVERRIDE);
1106-
}
1106+
11071107
if (status != nfs_ok)
11081108
return status;
11091109
inode = d_inode(fhp->fh_dentry);
@@ -1176,15 +1176,18 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
11761176

11771177
open_file:
11781178
trace_nfsd_file_alloc(nf);
1179-
nf->nf_mark = nfsd_file_mark_find_or_create(inode);
1180-
if (nf->nf_mark) {
1179+
1180+
if (type == S_IFREG)
1181+
nf->nf_mark = nfsd_file_mark_find_or_create(inode);
1182+
1183+
if (type != S_IFREG || nf->nf_mark) {
11811184
if (file) {
11821185
get_file(file);
11831186
nf->nf_file = file;
11841187
status = nfs_ok;
11851188
trace_nfsd_file_opened(nf, status);
11861189
} else {
1187-
ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file);
1190+
ret = nfsd_open_verified(fhp, type, may_flags, &nf->nf_file);
11881191
if (ret == -EOPENSTALE && stale_retry) {
11891192
stale_retry = false;
11901193
nfsd_file_unhash(nf);
@@ -1246,7 +1249,7 @@ nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
12461249
unsigned int may_flags, struct nfsd_file **pnf)
12471250
{
12481251
return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL,
1249-
fhp, may_flags, NULL, pnf, true);
1252+
fhp, may_flags, NULL, S_IFREG, true, pnf);
12501253
}
12511254

12521255
/**
@@ -1271,7 +1274,7 @@ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
12711274
unsigned int may_flags, struct nfsd_file **pnf)
12721275
{
12731276
return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL,
1274-
fhp, may_flags, NULL, pnf, false);
1277+
fhp, may_flags, NULL, S_IFREG, false, pnf);
12751278
}
12761279

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

1317-
beres = nfsd_file_do_acquire(NULL, net, cred, client,
1318-
fhp, may_flags, NULL, pnf, false);
1320+
beres = nfsd_file_do_acquire(NULL, net, cred, client, fhp, may_flags,
1321+
NULL, S_IFREG, false, pnf);
13191322
put_cred(revert_creds(save_cred));
13201323
return beres;
13211324
}
@@ -1344,7 +1347,33 @@ nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
13441347
struct nfsd_file **pnf)
13451348
{
13461349
return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL,
1347-
fhp, may_flags, file, pnf, false);
1350+
fhp, may_flags, file, S_IFREG, false, pnf);
1351+
}
1352+
1353+
/**
1354+
* nfsd_file_acquire_dir - Get a struct nfsd_file with an open directory
1355+
* @rqstp: the RPC transaction being executed
1356+
* @fhp: the NFS filehandle of the file to be opened
1357+
* @pnf: OUT: new or found "struct nfsd_file" object
1358+
*
1359+
* The nfsd_file_object returned by this API is reference-counted
1360+
* but not garbage-collected. The object is unhashed after the
1361+
* final nfsd_file_put(). This opens directories only, and only
1362+
* in O_RDONLY mode.
1363+
*
1364+
* Return values:
1365+
* %nfs_ok - @pnf points to an nfsd_file with its reference
1366+
* count boosted.
1367+
*
1368+
* On error, an nfsstat value in network byte order is returned.
1369+
*/
1370+
__be32
1371+
nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp,
1372+
struct nfsd_file **pnf)
1373+
{
1374+
return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, fhp,
1375+
NFSD_MAY_READ|NFSD_MAY_64BIT_COOKIE,
1376+
NULL, S_IFDIR, false, pnf);
13481377
}
13491378

13501379
/*

fs/nfsd/filecache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,7 @@ __be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
8282
__be32 nfsd_file_acquire_local(struct net *net, struct svc_cred *cred,
8383
struct auth_domain *client, struct svc_fh *fhp,
8484
unsigned int may_flags, struct nfsd_file **pnf);
85+
__be32 nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp,
86+
struct nfsd_file **pnf);
8587
int nfsd_file_cache_stats_show(struct seq_file *m, void *v);
8688
#endif /* _FS_NFSD_FILECACHE_H */

fs/nfsd/vfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,15 +959,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
959959
/**
960960
* nfsd_open_verified - Open a regular file for the filecache
961961
* @fhp: NFS filehandle of the file to open
962+
* @type: S_IFMT inode type allowed (0 means any type is allowed)
962963
* @may_flags: internal permission flags
963964
* @filp: OUT: open "struct file *"
964965
*
965966
* Returns zero on success, or a negative errno value.
966967
*/
967968
int
968-
nfsd_open_verified(struct svc_fh *fhp, int may_flags, struct file **filp)
969+
nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, struct file **filp)
969970
{
970-
return __nfsd_open(fhp, S_IFREG, may_flags, filp);
971+
return __nfsd_open(fhp, type, may_flags, filp);
971972
}
972973

973974
/*

fs/nfsd/vfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ __be32 nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
114114
int nfsd_open_break_lease(struct inode *, int);
115115
__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t,
116116
int, struct file **);
117-
int nfsd_open_verified(struct svc_fh *fhp, int may_flags,
117+
int nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags,
118118
struct file **filp);
119119
__be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
120120
struct file *file, loff_t offset,

0 commit comments

Comments
 (0)