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 --- |