tmpfs_vnops.c (232821) | tmpfs_vnops.c (232960) |
---|---|
1/* $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ */ 2 3/*- 4 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code --- 20 unchanged lines hidden (view full) --- 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * tmpfs vnode interface. 35 */ 36#include <sys/cdefs.h> | 1/* $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ */ 2 3/*- 4 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code --- 20 unchanged lines hidden (view full) --- 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * tmpfs vnode interface. 35 */ 36#include <sys/cdefs.h> |
37__FBSDID("$FreeBSD: head/sys/fs/tmpfs/tmpfs_vnops.c 232821 2012-03-11 12:19:58Z kib $"); | 37__FBSDID("$FreeBSD: head/sys/fs/tmpfs/tmpfs_vnops.c 232960 2012-03-14 09:15:50Z gleb $"); |
38 39#include <sys/param.h> 40#include <sys/fcntl.h> 41#include <sys/lockf.h> 42#include <sys/namei.h> 43#include <sys/priv.h> 44#include <sys/proc.h> 45#include <sys/sched.h> 46#include <sys/sf_buf.h> 47#include <sys/stat.h> 48#include <sys/systm.h> | 38 39#include <sys/param.h> 40#include <sys/fcntl.h> 41#include <sys/lockf.h> 42#include <sys/namei.h> 43#include <sys/priv.h> 44#include <sys/proc.h> 45#include <sys/sched.h> 46#include <sys/sf_buf.h> 47#include <sys/stat.h> 48#include <sys/systm.h> |
49#include <sys/sysctl.h> |
|
49#include <sys/unistd.h> 50#include <sys/vnode.h> 51 52#include <vm/vm.h> 53#include <vm/vm_object.h> 54#include <vm/vm_page.h> 55#include <vm/vm_pager.h> 56 57#include <fs/tmpfs/tmpfs_vnops.h> 58#include <fs/tmpfs/tmpfs.h> 59 | 50#include <sys/unistd.h> 51#include <sys/vnode.h> 52 53#include <vm/vm.h> 54#include <vm/vm_object.h> 55#include <vm/vm_page.h> 56#include <vm/vm_pager.h> 57 58#include <fs/tmpfs/tmpfs_vnops.h> 59#include <fs/tmpfs/tmpfs.h> 60 |
61SYSCTL_DECL(_vfs_tmpfs); 62 63static volatile int tmpfs_rename_restarts; 64SYSCTL_INT(_vfs_tmpfs, OID_AUTO, rename_restarts, CTLFLAG_RD, 65 __DEVOLATILE(int *, &tmpfs_rename_restarts), 0, 66 "Times rename had to restart due to lock contention"); 67 |
|
60/* --------------------------------------------------------------------- */ 61 62static int 63tmpfs_lookup(struct vop_cachedlookup_args *v) 64{ 65 struct vnode *dvp = v->a_dvp; 66 struct vnode **vpp = v->a_vpp; 67 struct componentname *cnp = v->a_cnp; --- 845 unchanged lines hidden (view full) --- 913 error = 0; 914 915out: 916 return error; 917} 918 919/* --------------------------------------------------------------------- */ 920 | 68/* --------------------------------------------------------------------- */ 69 70static int 71tmpfs_lookup(struct vop_cachedlookup_args *v) 72{ 73 struct vnode *dvp = v->a_dvp; 74 struct vnode **vpp = v->a_vpp; 75 struct componentname *cnp = v->a_cnp; --- 845 unchanged lines hidden (view full) --- 921 error = 0; 922 923out: 924 return error; 925} 926 927/* --------------------------------------------------------------------- */ 928 |
929/* 930 * We acquire all but fdvp locks using non-blocking acquisitions. If we 931 * fail to acquire any lock in the path we will drop all held locks, 932 * acquire the new lock in a blocking fashion, and then release it and 933 * restart the rename. This acquire/release step ensures that we do not 934 * spin on a lock waiting for release. On error release all vnode locks 935 * and decrement references the way tmpfs_rename() would do. 936 */ |
|
921static int | 937static int |
938tmpfs_rename_relock(struct vnode *fdvp, struct vnode **fvpp, 939 struct vnode *tdvp, struct vnode **tvpp, 940 struct componentname *fcnp, struct componentname *tcnp) 941{ 942 struct vnode *nvp; 943 struct mount *mp; 944 struct tmpfs_dirent *de; 945 int error, restarts = 0; 946 947 VOP_UNLOCK(tdvp, 0); 948 if (*tvpp != NULL && *tvpp != tdvp) 949 VOP_UNLOCK(*tvpp, 0); 950 mp = fdvp->v_mount; 951 952relock: 953 restarts += 1; 954 error = vn_lock(fdvp, LK_EXCLUSIVE); 955 if (error) 956 goto releout; 957 if (vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { 958 VOP_UNLOCK(fdvp, 0); 959 error = vn_lock(tdvp, LK_EXCLUSIVE); 960 if (error) 961 goto releout; 962 VOP_UNLOCK(tdvp, 0); 963 goto relock; 964 } 965 /* 966 * Re-resolve fvp to be certain it still exists and fetch the 967 * correct vnode. 968 */ 969 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(fdvp), NULL, fcnp); 970 if (de == NULL) { 971 VOP_UNLOCK(fdvp, 0); 972 VOP_UNLOCK(tdvp, 0); 973 if ((fcnp->cn_flags & ISDOTDOT) != 0 || 974 (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')) 975 error = EINVAL; 976 else 977 error = ENOENT; 978 goto releout; 979 } 980 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE | LK_NOWAIT, &nvp); 981 if (error != 0) { 982 VOP_UNLOCK(fdvp, 0); 983 VOP_UNLOCK(tdvp, 0); 984 if (error != EBUSY) 985 goto releout; 986 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, &nvp); 987 if (error != 0) 988 goto releout; 989 VOP_UNLOCK(nvp, 0); 990 /* 991 * Concurrent rename race. 992 */ 993 if (nvp == tdvp) { 994 vrele(nvp); 995 error = EINVAL; 996 goto releout; 997 } 998 vrele(*fvpp); 999 *fvpp = nvp; 1000 goto relock; 1001 } 1002 vrele(*fvpp); 1003 *fvpp = nvp; 1004 VOP_UNLOCK(*fvpp, 0); 1005 /* 1006 * Re-resolve tvp and acquire the vnode lock if present. 1007 */ 1008 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(tdvp), NULL, tcnp); 1009 /* 1010 * If tvp disappeared we just carry on. 1011 */ 1012 if (de == NULL && *tvpp != NULL) { 1013 vrele(*tvpp); 1014 *tvpp = NULL; 1015 } 1016 /* 1017 * Get the tvp ino if the lookup succeeded. We may have to restart 1018 * if the non-blocking acquire fails. 1019 */ 1020 if (de != NULL) { 1021 nvp = NULL; 1022 error = tmpfs_alloc_vp(mp, de->td_node, 1023 LK_EXCLUSIVE | LK_NOWAIT, &nvp); 1024 if (*tvpp != NULL) 1025 vrele(*tvpp); 1026 *tvpp = nvp; 1027 if (error != 0) { 1028 VOP_UNLOCK(fdvp, 0); 1029 VOP_UNLOCK(tdvp, 0); 1030 if (error != EBUSY) 1031 goto releout; 1032 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, 1033 &nvp); 1034 if (error != 0) 1035 goto releout; 1036 VOP_UNLOCK(nvp, 0); 1037 /* 1038 * fdvp contains fvp, thus tvp (=fdvp) is not empty. 1039 */ 1040 if (nvp == fdvp) { 1041 error = ENOTEMPTY; 1042 goto releout; 1043 } 1044 goto relock; 1045 } 1046 } 1047 tmpfs_rename_restarts += restarts; 1048 1049 return (0); 1050 1051releout: 1052 vrele(fdvp); 1053 vrele(*fvpp); 1054 vrele(tdvp); 1055 if (*tvpp != NULL) 1056 vrele(*tvpp); 1057 tmpfs_rename_restarts += restarts; 1058 1059 return (error); 1060} 1061 1062static int |
|
922tmpfs_rename(struct vop_rename_args *v) 923{ 924 struct vnode *fdvp = v->a_fdvp; 925 struct vnode *fvp = v->a_fvp; 926 struct componentname *fcnp = v->a_fcnp; 927 struct vnode *tdvp = v->a_tdvp; 928 struct vnode *tvp = v->a_tvp; 929 struct componentname *tcnp = v->a_tcnp; | 1063tmpfs_rename(struct vop_rename_args *v) 1064{ 1065 struct vnode *fdvp = v->a_fdvp; 1066 struct vnode *fvp = v->a_fvp; 1067 struct componentname *fcnp = v->a_fcnp; 1068 struct vnode *tdvp = v->a_tdvp; 1069 struct vnode *tvp = v->a_tvp; 1070 struct componentname *tcnp = v->a_tcnp; |
1071 struct mount *mp = NULL; |
|
930 931 char *newname; 932 int error; 933 struct tmpfs_dirent *de; 934 struct tmpfs_mount *tmp; 935 struct tmpfs_node *fdnode; 936 struct tmpfs_node *fnode; 937 struct tmpfs_node *tnode; 938 struct tmpfs_node *tdnode; 939 940 MPASS(VOP_ISLOCKED(tdvp)); 941 MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp))); 942 MPASS(fcnp->cn_flags & HASBUF); 943 MPASS(tcnp->cn_flags & HASBUF); 944 | 1072 1073 char *newname; 1074 int error; 1075 struct tmpfs_dirent *de; 1076 struct tmpfs_mount *tmp; 1077 struct tmpfs_node *fdnode; 1078 struct tmpfs_node *fnode; 1079 struct tmpfs_node *tnode; 1080 struct tmpfs_node *tdnode; 1081 1082 MPASS(VOP_ISLOCKED(tdvp)); 1083 MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp))); 1084 MPASS(fcnp->cn_flags & HASBUF); 1085 MPASS(tcnp->cn_flags & HASBUF); 1086 |
945 tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); 946 | |
947 /* Disallow cross-device renames. 948 * XXX Why isn't this done by the caller? */ 949 if (fvp->v_mount != tdvp->v_mount || 950 (tvp != NULL && fvp->v_mount != tvp->v_mount)) { 951 error = EXDEV; 952 goto out; 953 } 954 | 1087 /* Disallow cross-device renames. 1088 * XXX Why isn't this done by the caller? */ 1089 if (fvp->v_mount != tdvp->v_mount || 1090 (tvp != NULL && fvp->v_mount != tvp->v_mount)) { 1091 error = EXDEV; 1092 goto out; 1093 } 1094 |
955 tmp = VFS_TO_TMPFS(tdvp->v_mount); 956 tdnode = VP_TO_TMPFS_DIR(tdvp); 957 | |
958 /* If source and target are the same file, there is nothing to do. */ 959 if (fvp == tvp) { 960 error = 0; 961 goto out; 962 } 963 964 /* If we need to move the directory between entries, lock the 965 * source so that we can safely operate on it. */ | 1095 /* If source and target are the same file, there is nothing to do. */ 1096 if (fvp == tvp) { 1097 error = 0; 1098 goto out; 1099 } 1100 1101 /* If we need to move the directory between entries, lock the 1102 * source so that we can safely operate on it. */ |
966 if (fdvp != tdvp && fdvp != tvp) 967 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); | 1103 if (fdvp != tdvp && fdvp != tvp) { 1104 if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { 1105 mp = tdvp->v_mount; 1106 error = vfs_busy(mp, 0); 1107 if (error != 0) { 1108 mp = NULL; 1109 goto out; 1110 } 1111 error = tmpfs_rename_relock(fdvp, &fvp, tdvp, &tvp, 1112 fcnp, tcnp); 1113 if (error != 0) { 1114 vfs_unbusy(mp); 1115 return (error); 1116 } 1117 ASSERT_VOP_ELOCKED(fdvp, 1118 "tmpfs_rename: fdvp not locked"); 1119 ASSERT_VOP_ELOCKED(tdvp, 1120 "tmpfs_rename: tdvp not locked"); 1121 if (tvp != NULL) 1122 ASSERT_VOP_ELOCKED(tvp, 1123 "tmpfs_rename: tvp not locked"); 1124 if (fvp == tvp) { 1125 error = 0; 1126 goto out_locked; 1127 } 1128 } 1129 } 1130 1131 tmp = VFS_TO_TMPFS(tdvp->v_mount); 1132 tdnode = VP_TO_TMPFS_DIR(tdvp); 1133 tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); |
968 fdnode = VP_TO_TMPFS_DIR(fdvp); 969 fnode = VP_TO_TMPFS_NODE(fvp); 970 de = tmpfs_dir_lookup(fdnode, fnode, fcnp); 971 972 /* Entry can disappear before we lock fdvp, 973 * also avoid manipulating '.' and '..' entries. */ 974 if (de == NULL) { 975 if ((fcnp->cn_flags & ISDOTDOT) != 0 || --- 177 unchanged lines hidden (view full) --- 1153 vput(tdvp); 1154 if (tvp != NULL) 1155 vput(tvp); 1156 1157 /* Release source nodes. */ 1158 vrele(fdvp); 1159 vrele(fvp); 1160 | 1134 fdnode = VP_TO_TMPFS_DIR(fdvp); 1135 fnode = VP_TO_TMPFS_NODE(fvp); 1136 de = tmpfs_dir_lookup(fdnode, fnode, fcnp); 1137 1138 /* Entry can disappear before we lock fdvp, 1139 * also avoid manipulating '.' and '..' entries. */ 1140 if (de == NULL) { 1141 if ((fcnp->cn_flags & ISDOTDOT) != 0 || --- 177 unchanged lines hidden (view full) --- 1319 vput(tdvp); 1320 if (tvp != NULL) 1321 vput(tvp); 1322 1323 /* Release source nodes. */ 1324 vrele(fdvp); 1325 vrele(fvp); 1326 |
1327 if (mp != NULL) 1328 vfs_unbusy(mp); 1329 |
|
1161 return error; 1162} 1163 1164/* --------------------------------------------------------------------- */ 1165 1166static int 1167tmpfs_mkdir(struct vop_mkdir_args *v) 1168{ --- 443 unchanged lines hidden --- | 1330 return error; 1331} 1332 1333/* --------------------------------------------------------------------- */ 1334 1335static int 1336tmpfs_mkdir(struct vop_mkdir_args *v) 1337{ --- 443 unchanged lines hidden --- |