nfs_vnops.c (224733) | nfs_vnops.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 * @(#)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 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 33 */ 34 35#include <sys/cdefs.h> |
36__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_vnops.c 224733 2011-08-09 15:29:58Z jhb $"); | 36__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_vnops.c 230394 2012-01-20 20:02:01Z jhb $"); |
37 38/* 39 * vnode op calls for Sun NFS version 2 and 3 40 */ 41 42#include "opt_inet.h" 43#include "opt_kdtrace.h" 44 --- 863 unchanged lines hidden (view full) --- 908static int 909nfs_lookup(struct vop_lookup_args *ap) 910{ 911 struct componentname *cnp = ap->a_cnp; 912 struct vnode *dvp = ap->a_dvp; 913 struct vnode **vpp = ap->a_vpp; 914 struct mount *mp = dvp->v_mount; 915 struct vattr vattr; | 37 38/* 39 * vnode op calls for Sun NFS version 2 and 3 40 */ 41 42#include "opt_inet.h" 43#include "opt_kdtrace.h" 44 --- 863 unchanged lines hidden (view full) --- 908static int 909nfs_lookup(struct vop_lookup_args *ap) 910{ 911 struct componentname *cnp = ap->a_cnp; 912 struct vnode *dvp = ap->a_dvp; 913 struct vnode **vpp = ap->a_vpp; 914 struct mount *mp = dvp->v_mount; 915 struct vattr vattr; |
916 struct timespec dmtime; | 916 struct timespec nctime; |
917 int flags = cnp->cn_flags; 918 struct vnode *newvp; 919 struct nfsmount *nmp; 920 caddr_t bpos, dpos; 921 struct mbuf *mreq, *mrep, *md, *mb; 922 long len; 923 nfsfh_t *fhp; 924 struct nfsnode *np, *newnp; | 917 int flags = cnp->cn_flags; 918 struct vnode *newvp; 919 struct nfsmount *nmp; 920 caddr_t bpos, dpos; 921 struct mbuf *mreq, *mrep, *md, *mb; 922 long len; 923 nfsfh_t *fhp; 924 struct nfsnode *np, *newnp; |
925 int error = 0, attrflag, fhsize, ltype; | 925 int error = 0, attrflag, dattrflag, fhsize, ltype, ncticks; |
926 int v3 = NFS_ISV3(dvp); 927 struct thread *td = cnp->cn_thread; 928 929 *vpp = NULLVP; 930 if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) && 931 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 932 return (EROFS); 933 if (dvp->v_type != VDIR) 934 return (ENOTDIR); 935 nmp = VFSTONFS(mp); 936 np = VTONFS(dvp); 937 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) { 938 *vpp = NULLVP; 939 return (error); 940 } | 926 int v3 = NFS_ISV3(dvp); 927 struct thread *td = cnp->cn_thread; 928 929 *vpp = NULLVP; 930 if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) && 931 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 932 return (EROFS); 933 if (dvp->v_type != VDIR) 934 return (ENOTDIR); 935 nmp = VFSTONFS(mp); 936 np = VTONFS(dvp); 937 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) { 938 *vpp = NULLVP; 939 return (error); 940 } |
941 error = cache_lookup(dvp, vpp, cnp); | 941 error = cache_lookup_times(dvp, vpp, cnp, &nctime, &ncticks); |
942 if (error > 0 && error != ENOENT) 943 return (error); 944 if (error == -1) { 945 /* | 942 if (error > 0 && error != ENOENT) 943 return (error); 944 if (error == -1) { 945 /* |
946 * Lookups of "." are special and always return the 947 * current directory. cache_lookup() already handles 948 * associated locking bookkeeping, etc. 949 */ 950 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 951 /* XXX: Is this really correct? */ 952 if (cnp->cn_nameiop != LOOKUP && 953 (flags & ISLASTCN)) 954 cnp->cn_flags |= SAVENAME; 955 return (0); 956 } 957 958 /* |
|
946 * We only accept a positive hit in the cache if the 947 * change time of the file matches our cached copy. 948 * Otherwise, we discard the cache entry and fallback 949 * to doing a lookup RPC. 950 * 951 * To better handle stale file handles and attributes, 952 * clear the attribute cache of this node if it is a 953 * leaf component, part of an open() call, and not --- 9 unchanged lines hidden (view full) --- 963 (flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && 964 !(newnp->n_flag & NMODIFIED)) { 965 mtx_lock(&newnp->n_mtx); 966 newnp->n_attrstamp = 0; 967 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); 968 mtx_unlock(&newnp->n_mtx); 969 } 970 if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 && | 959 * We only accept a positive hit in the cache if the 960 * change time of the file matches our cached copy. 961 * Otherwise, we discard the cache entry and fallback 962 * to doing a lookup RPC. 963 * 964 * To better handle stale file handles and attributes, 965 * clear the attribute cache of this node if it is a 966 * leaf component, part of an open() call, and not --- 9 unchanged lines hidden (view full) --- 976 (flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && 977 !(newnp->n_flag & NMODIFIED)) { 978 mtx_lock(&newnp->n_mtx); 979 newnp->n_attrstamp = 0; 980 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); 981 mtx_unlock(&newnp->n_mtx); 982 } 983 if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 && |
971 timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==)) { | 984 timespeccmp(&vattr.va_ctime, &nctime, ==)) { |
972 nfsstats.lookupcache_hits++; 973 if (cnp->cn_nameiop != LOOKUP && 974 (flags & ISLASTCN)) 975 cnp->cn_flags |= SAVENAME; 976 return (0); 977 } 978 cache_purge(newvp); 979 if (dvp != newvp) 980 vput(newvp); 981 else 982 vrele(newvp); 983 *vpp = NULLVP; 984 } else if (error == ENOENT) { 985 if (dvp->v_iflag & VI_DOOMED) 986 return (ENOENT); 987 /* 988 * We only accept a negative hit in the cache if the 989 * modification time of the parent directory matches | 985 nfsstats.lookupcache_hits++; 986 if (cnp->cn_nameiop != LOOKUP && 987 (flags & ISLASTCN)) 988 cnp->cn_flags |= SAVENAME; 989 return (0); 990 } 991 cache_purge(newvp); 992 if (dvp != newvp) 993 vput(newvp); 994 else 995 vrele(newvp); 996 *vpp = NULLVP; 997 } else if (error == ENOENT) { 998 if (dvp->v_iflag & VI_DOOMED) 999 return (ENOENT); 1000 /* 1001 * We only accept a negative hit in the cache if the 1002 * modification time of the parent directory matches |
990 * our cached copy. Otherwise, we discard all of the 991 * negative cache entries for this directory. We also 992 * only trust -ve cache entries for less than 993 * nm_negative_namecache_timeout seconds. | 1003 * the cached copy in the name cache entry. 1004 * Otherwise, we discard all of the negative cache 1005 * entries for this directory. We also only trust 1006 * negative cache entries for up to nm_negnametimeo 1007 * seconds. |
994 */ | 1008 */ |
995 if ((u_int)(ticks - np->n_dmtime_ticks) < 996 (nmp->nm_negnametimeo * hz) && | 1009 if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) && |
997 VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 && | 1010 VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 && |
998 timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) { | 1011 timespeccmp(&vattr.va_mtime, &nctime, ==)) { |
999 nfsstats.lookupcache_hits++; 1000 return (ENOENT); 1001 } 1002 cache_purge_negative(dvp); | 1012 nfsstats.lookupcache_hits++; 1013 return (ENOENT); 1014 } 1015 cache_purge_negative(dvp); |
1003 mtx_lock(&np->n_mtx); 1004 timespecclear(&np->n_dmtime); 1005 mtx_unlock(&np->n_mtx); | |
1006 } 1007 | 1016 } 1017 |
1008 /* 1009 * Cache the modification time of the parent directory in case 1010 * the lookup fails and results in adding the first negative 1011 * name cache entry for the directory. Since this is reading 1012 * a single time_t, don't bother with locking. The 1013 * modification time may be a bit stale, but it must be read 1014 * before performing the lookup RPC to prevent a race where 1015 * another lookup updates the timestamp on the directory after 1016 * the lookup RPC has been performed on the server but before 1017 * n_dmtime is set at the end of this function. 1018 */ 1019 dmtime = np->n_vattr.va_mtime; | 1018 attrflag = dattrflag = 0; |
1020 error = 0; 1021 newvp = NULLVP; 1022 nfsstats.lookupcache_misses++; 1023 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1024 len = cnp->cn_namelen; 1025 mreq = nfsm_reqhead(dvp, NFSPROC_LOOKUP, 1026 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 1027 mb = mreq; 1028 bpos = mtod(mb, caddr_t); 1029 nfsm_fhtom(dvp, v3); 1030 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1031 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred); 1032 if (error) { 1033 if (v3) { | 1019 error = 0; 1020 newvp = NULLVP; 1021 nfsstats.lookupcache_misses++; 1022 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1023 len = cnp->cn_namelen; 1024 mreq = nfsm_reqhead(dvp, NFSPROC_LOOKUP, 1025 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 1026 mb = mreq; 1027 bpos = mtod(mb, caddr_t); 1028 nfsm_fhtom(dvp, v3); 1029 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1030 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred); 1031 if (error) { 1032 if (v3) { |
1034 nfsm_postop_attr(dvp, attrflag); | 1033 nfsm_postop_attr_va(dvp, dattrflag, &vattr); |
1035 m_freem(mrep); 1036 } 1037 goto nfsmout; 1038 } 1039 nfsm_getfh(fhp, fhsize, v3); 1040 1041 /* 1042 * Handle RENAME case... --- 79 unchanged lines hidden (view full) --- 1122 !(np->n_flag & NMODIFIED)) { 1123 mtx_lock(&np->n_mtx); 1124 np->n_attrstamp = 0; 1125 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); 1126 mtx_unlock(&np->n_mtx); 1127 } 1128 } 1129 if (v3) { | 1034 m_freem(mrep); 1035 } 1036 goto nfsmout; 1037 } 1038 nfsm_getfh(fhp, fhsize, v3); 1039 1040 /* 1041 * Handle RENAME case... --- 79 unchanged lines hidden (view full) --- 1121 !(np->n_flag & NMODIFIED)) { 1122 mtx_lock(&np->n_mtx); 1123 np->n_attrstamp = 0; 1124 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); 1125 mtx_unlock(&np->n_mtx); 1126 } 1127 } 1128 if (v3) { |
1130 nfsm_postop_attr(newvp, attrflag); 1131 nfsm_postop_attr(dvp, attrflag); 1132 } else 1133 nfsm_loadattr(newvp, NULL); | 1129 nfsm_postop_attr_va(newvp, attrflag, &vattr); 1130 nfsm_postop_attr(dvp, dattrflag); 1131 } else { 1132 nfsm_loadattr(newvp, &vattr); 1133 attrflag = 1; 1134 } |
1134 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 1135 cnp->cn_flags |= SAVENAME; 1136 if ((cnp->cn_flags & MAKEENTRY) && | 1135 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 1136 cnp->cn_flags |= SAVENAME; 1137 if ((cnp->cn_flags & MAKEENTRY) && |
1137 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 1138 np->n_ctime = np->n_vattr.va_ctime; 1139 cache_enter(dvp, newvp, cnp); | 1138 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) && attrflag) { 1139 cache_enter_time(dvp, newvp, cnp, &vattr.va_ctime); |
1140 } 1141 *vpp = newvp; 1142 m_freem(mrep); 1143nfsmout: 1144 if (error) { 1145 if (newvp != NULLVP) { 1146 vput(newvp); 1147 *vpp = NULLVP; --- 11 unchanged lines hidden (view full) --- 1159 * MNT_RDONLY. 1160 */ 1161 if (mp->mnt_flag & MNT_RDONLY) 1162 return (EROFS); 1163 cnp->cn_flags |= SAVENAME; 1164 return (EJUSTRETURN); 1165 } 1166 | 1140 } 1141 *vpp = newvp; 1142 m_freem(mrep); 1143nfsmout: 1144 if (error) { 1145 if (newvp != NULLVP) { 1146 vput(newvp); 1147 *vpp = NULLVP; --- 11 unchanged lines hidden (view full) --- 1159 * MNT_RDONLY. 1160 */ 1161 if (mp->mnt_flag & MNT_RDONLY) 1162 return (EROFS); 1163 cnp->cn_flags |= SAVENAME; 1164 return (EJUSTRETURN); 1165 } 1166 |
1167 if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) { | 1167 if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE && 1168 dattrflag) { |
1168 /* | 1169 /* |
1169 * Maintain n_dmtime as the modification time 1170 * of the parent directory when the oldest -ve 1171 * name cache entry for this directory was 1172 * added. If a -ve cache entry has already 1173 * been added with a newer modification time 1174 * by a concurrent lookup, then don't bother 1175 * adding a cache entry. The modification 1176 * time of the directory might have changed 1177 * due to the file this lookup failed to find 1178 * being created. In that case a subsequent 1179 * lookup would incorrectly use the entry 1180 * added here instead of doing an extra 1181 * lookup. | 1170 * Cache the modification time of the parent 1171 * directory from the post-op attributes in 1172 * the name cache entry. The negative cache 1173 * entry will be ignored once the directory 1174 * has changed. Don't bother adding the entry 1175 * if the directory has already changed. |
1182 */ 1183 mtx_lock(&np->n_mtx); | 1176 */ 1177 mtx_lock(&np->n_mtx); |
1184 if (timespeccmp(&np->n_dmtime, &dmtime, <=)) { 1185 if (!timespecisset(&np->n_dmtime)) { 1186 np->n_dmtime = dmtime; 1187 np->n_dmtime_ticks = ticks; 1188 } | 1178 if (timespeccmp(&np->n_vattr.va_mtime, 1179 &vattr.va_mtime, ==)) { |
1189 mtx_unlock(&np->n_mtx); | 1180 mtx_unlock(&np->n_mtx); |
1190 cache_enter(dvp, NULL, cnp); | 1181 cache_enter_time(dvp, NULL, cnp, 1182 &vattr.va_mtime); |
1191 } else 1192 mtx_unlock(&np->n_mtx); 1193 } 1194 return (ENOENT); 1195 } 1196done: 1197 return (error); 1198} --- 1269 unchanged lines hidden (view full) --- 2468 nfsuint64 *cookiep; 2469 caddr_t bpos, dpos, dpossav1, dpossav2; 2470 struct mbuf *mreq, *mrep, *md, *mb, *mdsav1, *mdsav2; 2471 struct nameidata nami, *ndp = &nami; 2472 struct componentname *cnp = &ndp->ni_cnd; 2473 nfsuint64 cookie; 2474 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2475 struct nfsnode *dnp = VTONFS(vp), *np; | 1183 } else 1184 mtx_unlock(&np->n_mtx); 1185 } 1186 return (ENOENT); 1187 } 1188done: 1189 return (error); 1190} --- 1269 unchanged lines hidden (view full) --- 2460 nfsuint64 *cookiep; 2461 caddr_t bpos, dpos, dpossav1, dpossav2; 2462 struct mbuf *mreq, *mrep, *md, *mb, *mdsav1, *mdsav2; 2463 struct nameidata nami, *ndp = &nami; 2464 struct componentname *cnp = &ndp->ni_cnd; 2465 nfsuint64 cookie; 2466 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2467 struct nfsnode *dnp = VTONFS(vp), *np; |
2468 struct vattr vattr; |
|
2476 nfsfh_t *fhp; 2477 u_quad_t fileno; 2478 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2479 int attrflag, fhsize; 2480 2481#ifndef nolint 2482 dp = NULL; 2483#endif --- 164 unchanged lines hidden (view full) --- 2648 newvp = NFSTOV(np); 2649 } 2650 } 2651 if (doit && bigenough) { 2652 dpossav2 = dpos; 2653 dpos = dpossav1; 2654 mdsav2 = md; 2655 md = mdsav1; | 2469 nfsfh_t *fhp; 2470 u_quad_t fileno; 2471 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2472 int attrflag, fhsize; 2473 2474#ifndef nolint 2475 dp = NULL; 2476#endif --- 164 unchanged lines hidden (view full) --- 2641 newvp = NFSTOV(np); 2642 } 2643 } 2644 if (doit && bigenough) { 2645 dpossav2 = dpos; 2646 dpos = dpossav1; 2647 mdsav2 = md; 2648 md = mdsav1; |
2656 nfsm_loadattr(newvp, NULL); | 2649 nfsm_loadattr(newvp, &vattr); |
2657 dpos = dpossav2; 2658 md = mdsav2; | 2650 dpos = dpossav2; 2651 md = mdsav2; |
2659 dp->d_type = 2660 IFTODT(VTTOIF(np->n_vattr.va_type)); | 2652 dp->d_type = IFTODT(VTTOIF(vattr.va_type)); |
2661 ndp->ni_vp = newvp; | 2653 ndp->ni_vp = newvp; |
2662 /* 2663 * Update n_ctime so subsequent lookup 2664 * doesn't purge entry. 2665 */ 2666 np->n_ctime = np->n_vattr.va_ctime; 2667 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); | 2654 cache_enter_time(ndp->ni_dvp, ndp->ni_vp, cnp, 2655 &vattr.va_ctime); |
2668 } 2669 } else { 2670 /* Just skip over the file handle */ 2671 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); 2672 i = fxdr_unsigned(int, *tl); 2673 if (i) { 2674 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); 2675 fhsize = fxdr_unsigned(int, *tl); --- 862 unchanged lines hidden --- | 2656 } 2657 } else { 2658 /* Just skip over the file handle */ 2659 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); 2660 i = fxdr_unsigned(int, *tl); 2661 if (i) { 2662 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); 2663 fhsize = fxdr_unsigned(int, *tl); --- 862 unchanged lines hidden --- |