Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Jeff Layton and committed by
Christian Brauner
544a0ee1 d0eab9fc

+49 -17
+43 -14
fs/nfsd/filecache.c
··· 1086 1086 struct auth_domain *client, 1087 1087 struct svc_fh *fhp, 1088 1088 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) 1090 1090 { 1091 1091 unsigned char need = may_flags & NFSD_FILE_MAY_MASK; 1092 1092 struct nfsd_file *new, *nf; ··· 1097 1097 int ret; 1098 1098 1099 1099 retry: 1100 - if (rqstp) { 1101 - status = fh_verify(rqstp, fhp, S_IFREG, 1100 + if (rqstp) 1101 + status = fh_verify(rqstp, fhp, type, 1102 1102 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, 1105 1105 may_flags|NFSD_MAY_OWNER_OVERRIDE); 1106 - } 1106 + 1107 1107 if (status != nfs_ok) 1108 1108 return status; 1109 1109 inode = d_inode(fhp->fh_dentry); ··· 1176 1176 1177 1177 open_file: 1178 1178 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) { 1181 1184 if (file) { 1182 1185 get_file(file); 1183 1186 nf->nf_file = file; 1184 1187 status = nfs_ok; 1185 1188 trace_nfsd_file_opened(nf, status); 1186 1189 } else { 1187 - ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file); 1190 + ret = nfsd_open_verified(fhp, type, may_flags, &nf->nf_file); 1188 1191 if (ret == -EOPENSTALE && stale_retry) { 1189 1192 stale_retry = false; 1190 1193 nfsd_file_unhash(nf); ··· 1249 1246 unsigned int may_flags, struct nfsd_file **pnf) 1250 1247 { 1251 1248 return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, 1252 - fhp, may_flags, NULL, pnf, true); 1249 + fhp, may_flags, NULL, S_IFREG, true, pnf); 1253 1250 } 1254 1251 1255 1252 /** ··· 1274 1271 unsigned int may_flags, struct nfsd_file **pnf) 1275 1272 { 1276 1273 return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, 1277 - fhp, may_flags, NULL, pnf, false); 1274 + fhp, may_flags, NULL, S_IFREG, false, pnf); 1278 1275 } 1279 1276 1280 1277 /** ··· 1317 1314 const struct cred *save_cred = get_current_cred(); 1318 1315 __be32 beres; 1319 1316 1320 - beres = nfsd_file_do_acquire(NULL, net, cred, client, 1321 - fhp, may_flags, NULL, pnf, false); 1317 + beres = nfsd_file_do_acquire(NULL, net, cred, client, fhp, may_flags, 1318 + NULL, S_IFREG, false, pnf); 1322 1319 put_cred(revert_creds(save_cred)); 1323 1320 return beres; 1324 1321 } ··· 1347 1344 struct nfsd_file **pnf) 1348 1345 { 1349 1346 return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, 1350 - fhp, may_flags, file, pnf, false); 1347 + fhp, may_flags, file, S_IFREG, false, pnf); 1348 + } 1349 + 1350 + /** 1351 + * nfsd_file_acquire_dir - Get a struct nfsd_file with an open directory 1352 + * @rqstp: the RPC transaction being executed 1353 + * @fhp: the NFS filehandle of the file to be opened 1354 + * @pnf: OUT: new or found "struct nfsd_file" object 1355 + * 1356 + * The nfsd_file_object returned by this API is reference-counted 1357 + * but not garbage-collected. The object is unhashed after the 1358 + * final nfsd_file_put(). This opens directories only, and only 1359 + * in O_RDONLY mode. 1360 + * 1361 + * Return values: 1362 + * %nfs_ok - @pnf points to an nfsd_file with its reference 1363 + * count boosted. 1364 + * 1365 + * On error, an nfsstat value in network byte order is returned. 1366 + */ 1367 + __be32 1368 + nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, 1369 + struct nfsd_file **pnf) 1370 + { 1371 + return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, fhp, 1372 + NFSD_MAY_READ|NFSD_MAY_64BIT_COOKIE, 1373 + NULL, S_IFDIR, false, pnf); 1351 1374 } 1352 1375 1353 1376 /*
+2
fs/nfsd/filecache.h
··· 82 82 __be32 nfsd_file_acquire_local(struct net *net, struct svc_cred *cred, 83 83 struct auth_domain *client, struct svc_fh *fhp, 84 84 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); 85 87 int nfsd_file_cache_stats_show(struct seq_file *m, void *v); 86 88 #endif /* _FS_NFSD_FILECACHE_H */
+3 -2
fs/nfsd/vfs.c
··· 959 959 /** 960 960 * nfsd_open_verified - Open a regular file for the filecache 961 961 * @fhp: NFS filehandle of the file to open 962 + * @type: S_IFMT inode type allowed (0 means any type is allowed) 962 963 * @may_flags: internal permission flags 963 964 * @filp: OUT: open "struct file *" 964 965 * 965 966 * Returns zero on success, or a negative errno value. 966 967 */ 967 968 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) 969 970 { 970 - return __nfsd_open(fhp, S_IFREG, may_flags, filp); 971 + return __nfsd_open(fhp, type, may_flags, filp); 971 972 } 972 973 973 974 /*
+1 -1
fs/nfsd/vfs.h
··· 114 114 int nfsd_open_break_lease(struct inode *, int); 115 115 __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, 116 116 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, 118 118 struct file **filp); 119 119 __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, 120 120 struct file *file, loff_t offset,