Deleted Added
full compact
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 ---