Deleted Added
full compact
nfs_clvnops.c (227543) nfs_clvnops.c (230394)
1/*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * from nfs_vnops.c 8.16 (Berkeley) 5/27/95
33 */
34
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * from nfs_vnops.c 8.16 (Berkeley) 5/27/95
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clvnops.c 227543 2011-11-15 23:35:43Z rmacklem $");
36__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clvnops.c 230394 2012-01-20 20:02:01Z jhb $");
37
38/*
39 * vnode op calls for Sun NFS version 2, 3 and 4
40 */
41
42#include "opt_kdtrace.h"
43#include "opt_inet.h"
44

--- 966 unchanged lines hidden (view full) ---

1011 struct componentname *cnp = ap->a_cnp;
1012 struct vnode *dvp = ap->a_dvp;
1013 struct vnode **vpp = ap->a_vpp;
1014 struct mount *mp = dvp->v_mount;
1015 int flags = cnp->cn_flags;
1016 struct vnode *newvp;
1017 struct nfsmount *nmp;
1018 struct nfsnode *np, *newnp;
37
38/*
39 * vnode op calls for Sun NFS version 2, 3 and 4
40 */
41
42#include "opt_kdtrace.h"
43#include "opt_inet.h"
44

--- 966 unchanged lines hidden (view full) ---

1011 struct componentname *cnp = ap->a_cnp;
1012 struct vnode *dvp = ap->a_dvp;
1013 struct vnode **vpp = ap->a_vpp;
1014 struct mount *mp = dvp->v_mount;
1015 int flags = cnp->cn_flags;
1016 struct vnode *newvp;
1017 struct nfsmount *nmp;
1018 struct nfsnode *np, *newnp;
1019 int error = 0, attrflag, dattrflag, ltype;
1019 int error = 0, attrflag, dattrflag, ltype, ncticks;
1020 struct thread *td = cnp->cn_thread;
1021 struct nfsfh *nfhp;
1022 struct nfsvattr dnfsva, nfsva;
1023 struct vattr vattr;
1020 struct thread *td = cnp->cn_thread;
1021 struct nfsfh *nfhp;
1022 struct nfsvattr dnfsva, nfsva;
1023 struct vattr vattr;
1024 struct timespec dmtime;
1024 struct timespec nctime;
1025
1026 *vpp = NULLVP;
1027 if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) &&
1028 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1029 return (EROFS);
1030 if (dvp->v_type != VDIR)
1031 return (ENOTDIR);
1032 nmp = VFSTONFS(mp);

--- 4 unchanged lines hidden (view full) ---

1037 while (NFSHASNFSV4(nmp) && (np->n_flag & NREMOVEINPROG)) {
1038 np->n_flag |= NREMOVEWANT;
1039 (void) msleep((caddr_t)np, &np->n_mtx, PZERO, "nfslkup", 0);
1040 }
1041 mtx_unlock(&np->n_mtx);
1042
1043 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
1044 return (error);
1025
1026 *vpp = NULLVP;
1027 if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) &&
1028 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1029 return (EROFS);
1030 if (dvp->v_type != VDIR)
1031 return (ENOTDIR);
1032 nmp = VFSTONFS(mp);

--- 4 unchanged lines hidden (view full) ---

1037 while (NFSHASNFSV4(nmp) && (np->n_flag & NREMOVEINPROG)) {
1038 np->n_flag |= NREMOVEWANT;
1039 (void) msleep((caddr_t)np, &np->n_mtx, PZERO, "nfslkup", 0);
1040 }
1041 mtx_unlock(&np->n_mtx);
1042
1043 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
1044 return (error);
1045 error = cache_lookup(dvp, vpp, cnp);
1045 error = cache_lookup_times(dvp, vpp, cnp, &nctime, &ncticks);
1046 if (error > 0 && error != ENOENT)
1047 return (error);
1048 if (error == -1) {
1049 /*
1046 if (error > 0 && error != ENOENT)
1047 return (error);
1048 if (error == -1) {
1049 /*
1050 * Lookups of "." are special and always return the
1051 * current directory. cache_lookup() already handles
1052 * associated locking bookkeeping, etc.
1053 */
1054 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
1055 /* XXX: Is this really correct? */
1056 if (cnp->cn_nameiop != LOOKUP &&
1057 (flags & ISLASTCN))
1058 cnp->cn_flags |= SAVENAME;
1059 return (0);
1060 }
1061
1062 /*
1050 * We only accept a positive hit in the cache if the
1051 * change time of the file matches our cached copy.
1052 * Otherwise, we discard the cache entry and fallback
1053 * to doing a lookup RPC.
1054 *
1055 * To better handle stale file handles and attributes,
1056 * clear the attribute cache of this node if it is a
1057 * leaf component, part of an open() call, and not

--- 10 unchanged lines hidden (view full) ---

1068 !(newnp->n_flag & NMODIFIED)) {
1069 mtx_lock(&newnp->n_mtx);
1070 newnp->n_attrstamp = 0;
1071 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
1072 mtx_unlock(&newnp->n_mtx);
1073 }
1074 if (nfscl_nodeleg(newvp, 0) == 0 ||
1075 (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
1063 * We only accept a positive hit in the cache if the
1064 * change time of the file matches our cached copy.
1065 * Otherwise, we discard the cache entry and fallback
1066 * to doing a lookup RPC.
1067 *
1068 * To better handle stale file handles and attributes,
1069 * clear the attribute cache of this node if it is a
1070 * leaf component, part of an open() call, and not

--- 10 unchanged lines hidden (view full) ---

1081 !(newnp->n_flag & NMODIFIED)) {
1082 mtx_lock(&newnp->n_mtx);
1083 newnp->n_attrstamp = 0;
1084 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
1085 mtx_unlock(&newnp->n_mtx);
1086 }
1087 if (nfscl_nodeleg(newvp, 0) == 0 ||
1088 (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
1076 timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==))) {
1089 timespeccmp(&vattr.va_ctime, &nctime, ==))) {
1077 NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
1078 if (cnp->cn_nameiop != LOOKUP &&
1079 (flags & ISLASTCN))
1080 cnp->cn_flags |= SAVENAME;
1081 return (0);
1082 }
1083 cache_purge(newvp);
1084 if (dvp != newvp)
1085 vput(newvp);
1086 else
1087 vrele(newvp);
1088 *vpp = NULLVP;
1089 } else if (error == ENOENT) {
1090 if (dvp->v_iflag & VI_DOOMED)
1091 return (ENOENT);
1092 /*
1093 * We only accept a negative hit in the cache if the
1094 * modification time of the parent directory matches
1090 NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
1091 if (cnp->cn_nameiop != LOOKUP &&
1092 (flags & ISLASTCN))
1093 cnp->cn_flags |= SAVENAME;
1094 return (0);
1095 }
1096 cache_purge(newvp);
1097 if (dvp != newvp)
1098 vput(newvp);
1099 else
1100 vrele(newvp);
1101 *vpp = NULLVP;
1102 } else if (error == ENOENT) {
1103 if (dvp->v_iflag & VI_DOOMED)
1104 return (ENOENT);
1105 /*
1106 * We only accept a negative hit in the cache if the
1107 * modification time of the parent directory matches
1095 * our cached copy. Otherwise, we discard all of the
1096 * negative cache entries for this directory. We also
1097 * only trust -ve cache entries for less than
1098 * nm_negative_namecache_timeout seconds.
1108 * the cached copy in the name cache entry.
1109 * Otherwise, we discard all of the negative cache
1110 * entries for this directory. We also only trust
1111 * negative cache entries for up to nm_negnametimeo
1112 * seconds.
1099 */
1113 */
1100 if ((u_int)(ticks - np->n_dmtime_ticks) <
1101 (nmp->nm_negnametimeo * hz) &&
1114 if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) &&
1102 VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
1115 VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
1103 timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) {
1116 timespeccmp(&vattr.va_mtime, &nctime, ==)) {
1104 NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
1105 return (ENOENT);
1106 }
1107 cache_purge_negative(dvp);
1117 NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
1118 return (ENOENT);
1119 }
1120 cache_purge_negative(dvp);
1108 mtx_lock(&np->n_mtx);
1109 timespecclear(&np->n_dmtime);
1110 mtx_unlock(&np->n_mtx);
1111 }
1112
1121 }
1122
1113 /*
1114 * Cache the modification time of the parent directory in case
1115 * the lookup fails and results in adding the first negative
1116 * name cache entry for the directory. Since this is reading
1117 * a single time_t, don't bother with locking. The
1118 * modification time may be a bit stale, but it must be read
1119 * before performing the lookup RPC to prevent a race where
1120 * another lookup updates the timestamp on the directory after
1121 * the lookup RPC has been performed on the server but before
1122 * n_dmtime is set at the end of this function.
1123 */
1124 dmtime = np->n_vattr.na_mtime;
1125 error = 0;
1126 newvp = NULLVP;
1127 NFSINCRGLOBAL(newnfsstats.lookupcache_misses);
1128 error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
1129 cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag,
1130 NULL);
1131 if (dattrflag)
1132 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);

--- 19 unchanged lines hidden (view full) ---

1152 * MNT_RDONLY.
1153 */
1154 if (mp->mnt_flag & MNT_RDONLY)
1155 return (EROFS);
1156 cnp->cn_flags |= SAVENAME;
1157 return (EJUSTRETURN);
1158 }
1159
1123 error = 0;
1124 newvp = NULLVP;
1125 NFSINCRGLOBAL(newnfsstats.lookupcache_misses);
1126 error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
1127 cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag,
1128 NULL);
1129 if (dattrflag)
1130 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);

--- 19 unchanged lines hidden (view full) ---

1150 * MNT_RDONLY.
1151 */
1152 if (mp->mnt_flag & MNT_RDONLY)
1153 return (EROFS);
1154 cnp->cn_flags |= SAVENAME;
1155 return (EJUSTRETURN);
1156 }
1157
1160 if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
1158 if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE &&
1159 dattrflag) {
1161 /*
1160 /*
1162 * Maintain n_dmtime as the modification time
1163 * of the parent directory when the oldest -ve
1164 * name cache entry for this directory was
1165 * added. If a -ve cache entry has already
1166 * been added with a newer modification time
1167 * by a concurrent lookup, then don't bother
1168 * adding a cache entry. The modification
1169 * time of the directory might have changed
1170 * due to the file this lookup failed to find
1171 * being created. In that case a subsequent
1172 * lookup would incorrectly use the entry
1173 * added here instead of doing an extra
1174 * lookup.
1161 * Cache the modification time of the parent
1162 * directory from the post-op attributes in
1163 * the name cache entry. The negative cache
1164 * entry will be ignored once the directory
1165 * has changed. Don't bother adding the entry
1166 * if the directory has already changed.
1175 */
1176 mtx_lock(&np->n_mtx);
1167 */
1168 mtx_lock(&np->n_mtx);
1177 if (timespeccmp(&np->n_dmtime, &dmtime, <=)) {
1178 if (!timespecisset(&np->n_dmtime)) {
1179 np->n_dmtime = dmtime;
1180 np->n_dmtime_ticks = ticks;
1181 }
1169 if (timespeccmp(&np->n_vattr.na_mtime,
1170 &dnfsva.na_mtime, ==)) {
1182 mtx_unlock(&np->n_mtx);
1171 mtx_unlock(&np->n_mtx);
1183 cache_enter(dvp, NULL, cnp);
1172 cache_enter_time(dvp, NULL, cnp,
1173 &dnfsva.na_mtime);
1184 } else
1185 mtx_unlock(&np->n_mtx);
1186 }
1187 return (ENOENT);
1188 }
1189
1190 /*
1191 * Handle RENAME case...

--- 82 unchanged lines hidden (view full) ---

1274 np->n_attrstamp = 0;
1275 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
1276 mtx_unlock(&np->n_mtx);
1277 }
1278 }
1279 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1280 cnp->cn_flags |= SAVENAME;
1281 if ((cnp->cn_flags & MAKEENTRY) &&
1174 } else
1175 mtx_unlock(&np->n_mtx);
1176 }
1177 return (ENOENT);
1178 }
1179
1180 /*
1181 * Handle RENAME case...

--- 82 unchanged lines hidden (view full) ---

1264 np->n_attrstamp = 0;
1265 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
1266 mtx_unlock(&np->n_mtx);
1267 }
1268 }
1269 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1270 cnp->cn_flags |= SAVENAME;
1271 if ((cnp->cn_flags & MAKEENTRY) &&
1282 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
1283 np->n_ctime = np->n_vattr.na_vattr.va_ctime;
1284 cache_enter(dvp, newvp, cnp);
1272 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) && attrflag) {
1273 cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime);
1285 }
1286 *vpp = newvp;
1287 return (0);
1288}
1289
1290/*
1291 * nfs read call.
1292 * Just call ncl_bioread() to do the work.

--- 2185 unchanged lines hidden ---
1274 }
1275 *vpp = newvp;
1276 return (0);
1277}
1278
1279/*
1280 * nfs read call.
1281 * Just call ncl_bioread() to do the work.

--- 2185 unchanged lines hidden ---