summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2014-12-18 10:01:12 +0000
committerkib <kib@FreeBSD.org>2014-12-18 10:01:12 +0000
commit77c9d3f4e84458886633ec0fa2d06783735cd524 (patch)
treed6d1c37be8bcdc191674e99f86893f2fda397461
parentbefcdd660f271babed582714f57d94b131da4af5 (diff)
downloadFreeBSD-src-77c9d3f4e84458886633ec0fa2d06783735cd524.zip
FreeBSD-src-77c9d3f4e84458886633ec0fa2d06783735cd524.tar.gz
The VOP_LOOKUP() implementations for CREATE op do not put the name
into namecache, to avoid cache trashing when doing large operations. E.g., tar archive extraction is not usually followed by access to many of the files created. Right now, each VOP_LOOKUP() implementation explicitely knowns about this quirk and tests for both MAKEENTRY flag presence and op != CREATE to make the call to cache_enter(). Centralize the handling of the quirk into VFS, by deciding to cache only by MAKEENTRY flag in VOP. VFS now sets NOCACHE flag for CREATE namei() calls. Note that the change in semantic is backward-compatible and could be merged to the stable branch, and is compatible with non-changed third-party filesystems which correctly handle MAKEENTRY. Suggested by: Chris Torek <torek@pi-coral.com> Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c2
-rw-r--r--sys/fs/ext2fs/ext2_lookup.c2
-rw-r--r--sys/fs/fuse/fuse_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_lookup.c2
-rw-r--r--sys/fs/nandfs/nandfs_vnops.c2
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c3
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c12
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c2
-rw-r--r--sys/fs/unionfs/union_subr.c2
-rw-r--r--sys/fs/unionfs/union_vnops.c5
-rw-r--r--sys/kern/uipc_usrreq.c2
-rw-r--r--sys/kern/vfs_syscalls.c25
-rw-r--r--sys/kern/vfs_vnops.c6
-rw-r--r--sys/nfsclient/nfs_vnops.c3
-rw-r--r--sys/nfsserver/nfs_serv.c10
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c3
-rw-r--r--sys/ufs/ufs/ufs_lookup.c2
17 files changed, 47 insertions, 38 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 7763d44..5d7fa70 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -1548,7 +1548,7 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp,
/*
* Insert name into cache (as non-existent) if appropriate.
*/
- if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(dvp, *vpp, cnp);
/*
* Insert name into cache if appropriate.
diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c
index 34f720a..e59b606 100644
--- a/sys/fs/ext2fs/ext2_lookup.c
+++ b/sys/fs/ext2fs/ext2_lookup.c
@@ -514,7 +514,7 @@ notfound:
/*
* Insert name into cache (as non-existent) if appropriate.
*/
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(vdp, NULL, cnp);
return (ENOENT);
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
index 54f659f..085edba 100644
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -795,7 +795,7 @@ calldaemon:
* caching...)
*/
#if 0
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) {
+ if ((cnp->cn_flags & MAKEENTRY) != 0) {
FS_DEBUG("inserting NULL into cache\n");
cache_enter(dvp, NULL, cnp);
}
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
index 3704915..b5b8e31 100644
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -416,7 +416,7 @@ notfound:
* and 8.3 filenames. Hence, it may not invalidate all negative
* entries if a file with this name is later created.
*/
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(vdp, *vpp, cnp);
#endif
return (ENOENT);
diff --git a/sys/fs/nandfs/nandfs_vnops.c b/sys/fs/nandfs/nandfs_vnops.c
index 2c92f8b..65dcf64 100644
--- a/sys/fs/nandfs/nandfs_vnops.c
+++ b/sys/fs/nandfs/nandfs_vnops.c
@@ -478,7 +478,7 @@ out:
* the file might not be found and thus putting it into the namecache
* might be seen as negative caching.
*/
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(dvp, *vpp, cnp);
return (error);
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 9570b70..818551f 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1184,8 +1184,7 @@ nfs_lookup(struct vop_lookup_args *ap)
return (EJUSTRETURN);
}
- if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE &&
- dattrflag) {
+ if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) {
/*
* Cache the modification time of the parent
* directory from the post-op attributes in
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 9bf43c3..e6e02d7 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -994,7 +994,7 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
goto out;
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
- LOCKPARENT | LOCKLEAF | SAVESTART);
+ LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error)
@@ -1205,7 +1205,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
goto out;
}
}
- NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags);
+ NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags | NOCACHE);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error)
@@ -1658,7 +1658,7 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
}
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
- LOCKPARENT | SAVENAME);
+ LOCKPARENT | SAVENAME | NOCACHE);
if (!nd->nd_repstat) {
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
@@ -1735,7 +1735,7 @@ nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
*vpp = NULL;
NFSVNO_ATTRINIT(&nva);
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
- LOCKPARENT | SAVESTART);
+ LOCKPARENT | SAVESTART | NOCACHE);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (!error && !nd->nd_repstat)
@@ -1853,7 +1853,7 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
goto out;
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
- LOCKPARENT | SAVENAME);
+ LOCKPARENT | SAVENAME | NOCACHE);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error)
@@ -2782,7 +2782,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
}
if (create == NFSV4OPEN_CREATE)
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
- LOCKPARENT | LOCKLEAF | SAVESTART);
+ LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
else
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
LOCKLEAF | SAVESTART);
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 5ffab50..29ee389 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -195,7 +195,7 @@ tmpfs_lookup(struct vop_cachedlookup_args *v)
/* Store the result of this lookup in the cache. Avoid this if the
* request was for creation, as it does not improve timings on
* emprical tests. */
- if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(dvp, *vpp, cnp);
out:
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index e3391a7..74192dc 100644
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -536,6 +536,8 @@ unionfs_relookup(struct vnode *dvp, struct vnode **vpp,
cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART));
else if (RENAME == nameiop)
cn->cn_flags |= (cnp->cn_flags & SAVESTART);
+ else if (nameiop == CREATE)
+ cn->cn_flags |= NOCACHE;
vref(dvp);
VOP_UNLOCK(dvp, LK_RELEASE);
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 5076f16..6b60dbd 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -160,8 +160,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap)
LK_RETRY);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
- } else if (error == ENOENT && (cnflags & MAKEENTRY) &&
- nameiop != CREATE)
+ } else if (error == ENOENT && (cnflags & MAKEENTRY) != 0)
cache_enter(dvp, NULLVP, cnp);
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
@@ -337,7 +336,7 @@ unionfs_lookup_out:
if (lvp != NULLVP)
vrele(lvp);
- if (error == ENOENT && (cnflags & MAKEENTRY) && nameiop != CREATE)
+ if (error == ENOENT && (cnflags & MAKEENTRY) != 0)
cache_enter(dvp, NULLVP, cnp);
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index a540cc0..ef0b83c 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -505,7 +505,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
buf[namelen] = 0;
restart:
- NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME,
+ NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME | NOCACHE,
UIO_SYSSPACE, buf, fd, cap_rights_init(&rights, CAP_BINDAT), td);
/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
error = namei(&nd);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 2bcf85d..3105c2f 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1269,8 +1269,9 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
return (error);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- pathseg, path, fd, cap_rights_init(&rights, CAP_MKNODAT), td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
+ NOCACHE, pathseg, path, fd, cap_rights_init(&rights, CAP_MKNODAT),
+ td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -1384,8 +1385,9 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- pathseg, path, fd, cap_rights_init(&rights, CAP_MKFIFOAT), td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
+ NOCACHE, pathseg, path, fd, cap_rights_init(&rights, CAP_MKFIFOAT),
+ td);
if ((error = namei(&nd)) != 0)
return (error);
if (nd.ni_vp != NULL) {
@@ -1530,8 +1532,9 @@ again:
vrele(vp);
return (EPERM); /* POSIX */
}
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2,
- segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT), td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2 |
+ NOCACHE, segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT),
+ td);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL) {
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1650,8 +1653,9 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2,
AUDIT_ARG_TEXT(syspath);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- segflg, path2, fd, cap_rights_init(&rights, CAP_SYMLINKAT), td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
+ NOCACHE, segflg, path2, fd, cap_rights_init(&rights, CAP_SYMLINKAT),
+ td);
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
@@ -3581,8 +3585,9 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- segflg, path, fd, cap_rights_init(&rights, CAP_MKDIRAT), td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
+ NOCACHE, segflg, path, fd, cap_rights_init(&rights, CAP_MKDIRAT),
+ td);
nd.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&nd)) != 0)
return (error);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 687269d..40a69bb 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -189,7 +189,11 @@ restart:
fmode = *flagp;
if (fmode & O_CREAT) {
ndp->ni_cnd.cn_nameiop = CREATE;
- ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF;
+ /*
+ * Set NOCACHE to avoid flushing the cache when
+ * rolling in many files at once.
+ */
+ ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF | NOCACHE;
if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
ndp->ni_cnd.cn_flags |= FOLLOW;
if (!(vn_open_flags & VN_OPEN_NOAUDIT))
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index a841f65..2516d7d 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -1184,8 +1184,7 @@ nfsmout:
return (EJUSTRETURN);
}
- if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE &&
- dattrflag) {
+ if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) {
/*
* Cache the modification time of the parent
* directory from the post-op attributes in
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 1010da6..32fd3f5 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -1217,7 +1217,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE;
/*
* Call namei and do initial cleanup to get a few things
@@ -1501,7 +1501,7 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE;
/*
* Handle nfs_namei() call. If an error occurs, the nd structure
@@ -2030,7 +2030,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
VOP_UNLOCK(vp, 0);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT;
+ nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE;
error = nfs_namei(&nd, nfsd, dfhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, FALSE);
if (dirp && !v3) {
@@ -2153,7 +2153,7 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | NOCACHE;
error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, FALSE);
if (error == 0) {
@@ -2325,7 +2325,7 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT;
+ nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE;
error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, FALSE);
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 3df8932..099faeb 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -256,7 +256,8 @@ ffs_snapshot(mp, snapfile)
* Create the snapshot file.
*/
restart:
- NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, snapfile, td);
+ NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF | NOCACHE, UIO_SYSSPACE,
+ snapfile, td);
if ((error = namei(&nd)) != 0)
return (error);
if (nd.ni_vp != NULL) {
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index b34ed24..408349e 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -550,7 +550,7 @@ notfound:
/*
* Insert name into cache (as non-existent) if appropriate.
*/
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(vdp, NULL, cnp);
return (ENOENT);
OpenPOWER on IntegriCloud