Deleted Added
full compact
37c37
< __FBSDID("$FreeBSD: head/sys/fs/tmpfs/tmpfs_vnops.c 232821 2012-03-11 12:19:58Z kib $");
---
> __FBSDID("$FreeBSD: head/sys/fs/tmpfs/tmpfs_vnops.c 232960 2012-03-14 09:15:50Z gleb $");
48a49
> #include <sys/sysctl.h>
59a61,67
> SYSCTL_DECL(_vfs_tmpfs);
>
> static volatile int tmpfs_rename_restarts;
> SYSCTL_INT(_vfs_tmpfs, OID_AUTO, rename_restarts, CTLFLAG_RD,
> __DEVOLATILE(int *, &tmpfs_rename_restarts), 0,
> "Times rename had to restart due to lock contention");
>
920a929,936
> /*
> * We acquire all but fdvp locks using non-blocking acquisitions. If we
> * fail to acquire any lock in the path we will drop all held locks,
> * acquire the new lock in a blocking fashion, and then release it and
> * restart the rename. This acquire/release step ensures that we do not
> * spin on a lock waiting for release. On error release all vnode locks
> * and decrement references the way tmpfs_rename() would do.
> */
921a938,1062
> tmpfs_rename_relock(struct vnode *fdvp, struct vnode **fvpp,
> struct vnode *tdvp, struct vnode **tvpp,
> struct componentname *fcnp, struct componentname *tcnp)
> {
> struct vnode *nvp;
> struct mount *mp;
> struct tmpfs_dirent *de;
> int error, restarts = 0;
>
> VOP_UNLOCK(tdvp, 0);
> if (*tvpp != NULL && *tvpp != tdvp)
> VOP_UNLOCK(*tvpp, 0);
> mp = fdvp->v_mount;
>
> relock:
> restarts += 1;
> error = vn_lock(fdvp, LK_EXCLUSIVE);
> if (error)
> goto releout;
> if (vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
> VOP_UNLOCK(fdvp, 0);
> error = vn_lock(tdvp, LK_EXCLUSIVE);
> if (error)
> goto releout;
> VOP_UNLOCK(tdvp, 0);
> goto relock;
> }
> /*
> * Re-resolve fvp to be certain it still exists and fetch the
> * correct vnode.
> */
> de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(fdvp), NULL, fcnp);
> if (de == NULL) {
> VOP_UNLOCK(fdvp, 0);
> VOP_UNLOCK(tdvp, 0);
> if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
> (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
> error = EINVAL;
> else
> error = ENOENT;
> goto releout;
> }
> error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE | LK_NOWAIT, &nvp);
> if (error != 0) {
> VOP_UNLOCK(fdvp, 0);
> VOP_UNLOCK(tdvp, 0);
> if (error != EBUSY)
> goto releout;
> error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, &nvp);
> if (error != 0)
> goto releout;
> VOP_UNLOCK(nvp, 0);
> /*
> * Concurrent rename race.
> */
> if (nvp == tdvp) {
> vrele(nvp);
> error = EINVAL;
> goto releout;
> }
> vrele(*fvpp);
> *fvpp = nvp;
> goto relock;
> }
> vrele(*fvpp);
> *fvpp = nvp;
> VOP_UNLOCK(*fvpp, 0);
> /*
> * Re-resolve tvp and acquire the vnode lock if present.
> */
> de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(tdvp), NULL, tcnp);
> /*
> * If tvp disappeared we just carry on.
> */
> if (de == NULL && *tvpp != NULL) {
> vrele(*tvpp);
> *tvpp = NULL;
> }
> /*
> * Get the tvp ino if the lookup succeeded. We may have to restart
> * if the non-blocking acquire fails.
> */
> if (de != NULL) {
> nvp = NULL;
> error = tmpfs_alloc_vp(mp, de->td_node,
> LK_EXCLUSIVE | LK_NOWAIT, &nvp);
> if (*tvpp != NULL)
> vrele(*tvpp);
> *tvpp = nvp;
> if (error != 0) {
> VOP_UNLOCK(fdvp, 0);
> VOP_UNLOCK(tdvp, 0);
> if (error != EBUSY)
> goto releout;
> error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE,
> &nvp);
> if (error != 0)
> goto releout;
> VOP_UNLOCK(nvp, 0);
> /*
> * fdvp contains fvp, thus tvp (=fdvp) is not empty.
> */
> if (nvp == fdvp) {
> error = ENOTEMPTY;
> goto releout;
> }
> goto relock;
> }
> }
> tmpfs_rename_restarts += restarts;
>
> return (0);
>
> releout:
> vrele(fdvp);
> vrele(*fvpp);
> vrele(tdvp);
> if (*tvpp != NULL)
> vrele(*tvpp);
> tmpfs_rename_restarts += restarts;
>
> return (error);
> }
>
> static int
929a1071
> struct mount *mp = NULL;
945,946d1086
< tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
<
955,957d1094
< tmp = VFS_TO_TMPFS(tdvp->v_mount);
< tdnode = VP_TO_TMPFS_DIR(tdvp);
<
966,967c1103,1133
< if (fdvp != tdvp && fdvp != tvp)
< vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
---
> if (fdvp != tdvp && fdvp != tvp) {
> if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
> mp = tdvp->v_mount;
> error = vfs_busy(mp, 0);
> if (error != 0) {
> mp = NULL;
> goto out;
> }
> error = tmpfs_rename_relock(fdvp, &fvp, tdvp, &tvp,
> fcnp, tcnp);
> if (error != 0) {
> vfs_unbusy(mp);
> return (error);
> }
> ASSERT_VOP_ELOCKED(fdvp,
> "tmpfs_rename: fdvp not locked");
> ASSERT_VOP_ELOCKED(tdvp,
> "tmpfs_rename: tdvp not locked");
> if (tvp != NULL)
> ASSERT_VOP_ELOCKED(tvp,
> "tmpfs_rename: tvp not locked");
> if (fvp == tvp) {
> error = 0;
> goto out_locked;
> }
> }
> }
>
> tmp = VFS_TO_TMPFS(tdvp->v_mount);
> tdnode = VP_TO_TMPFS_DIR(tdvp);
> tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
1160a1327,1329
> if (mp != NULL)
> vfs_unbusy(mp);
>