* Insert into list of vnodes for the new mount point, if available. */
| 1927 | * Insert into list of vnodes for the new mount point, if available. |
| 1928 | */ |
| 1929 | int |
| 1930 | insmntque1(struct vnode *vp, struct mount *mp, |
| 1931 | void (*dtr)(struct vnode *, void *), void *dtr_arg) |
| 1932 | { |
| 1933 | |
| 1934 | KASSERT(vp->v_mount == NULL, |
| 1935 | ("insmntque: vnode already on per mount vnode list")); |
| 1936 | VNASSERT(mp != NULL, vp, ("Don't call insmntque(foo, NULL)")); |
| 1937 | ASSERT_VOP_ELOCKED(vp, "insmntque: non-locked vp"); |
| 1938 | |
| 1939 | /* |
| 1940 | * We acquire the vnode interlock early to ensure that the |
| 1941 | * vnode cannot be recycled by another process releasing a |
| 1942 | * holdcnt on it before we get it on both the vnode list |
| 1943 | * and the active vnode list. The mount mutex protects only |
| 1944 | * manipulation of the vnode list and the vnode freelist |
| 1945 | * mutex protects only manipulation of the active vnode list. |
| 1946 | * Hence the need to hold the vnode interlock throughout. |
| 1947 | */ |
| 1948 | MNT_ILOCK(mp); |
| 1949 | VI_LOCK(vp); |
| 1950 | if (((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 && |
| 1951 | ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0 || |
| 1952 | mp->mnt_nvnodelistsize == 0)) && |
| 1953 | (vp->v_vflag & VV_FORCEINSMQ) == 0) { |
| 1954 | VI_UNLOCK(vp); |
| 1955 | MNT_IUNLOCK(mp); |
| 1956 | if (dtr != NULL) |
| 1957 | dtr(vp, dtr_arg); |
| 1958 | return (EBUSY); |
| 1959 | } |
| 1960 | vp->v_mount = mp; |
| 1961 | MNT_REF(mp); |
| 1962 | TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); |
| 1963 | VNASSERT(mp->mnt_nvnodelistsize >= 0, vp, |
| 1964 | ("neg mount point vnode list size")); |
| 1965 | mp->mnt_nvnodelistsize++; |
| 1966 | VI_UNLOCK(vp); |
| 1967 | MNT_IUNLOCK(mp); |
| 1968 | return (0); |
| 1969 | } |
| 1970 | |
| 1971 | int |
| 1972 | insmntque(struct vnode *vp, struct mount *mp) |