kern/147890: [ufs] [regression] ufs-related lock problem in
RELENG_8 (18.04.2010 -> 20.04.2010)
Dmitry Pryanishnikov
lynx.ripe at gmail.com
Fri Jun 18 07:18:08 UTC 2010
Hello!
2010/6/17 Kostik Belousov <kostikbel at gmail.com>:
>
> What _could_ happen in your case is the relock in ufs_accessx for QUOTA.
> ufs_delete_denied() calls VOP_ACCESSX for both parent directory
> and target vnode while parent directory is locked. If source directory
> is not exclusively locked, LOR can happen, since ufs_accessx has to
> unlock and lock directory vnode. I am not sure how many similar cases
> of VOP_ACCESS[X] is places in the problematic locations.
>
> Try the (untested) patch below.
Thank you! The kernel with this patch applied (RELENG_8 date =
14.06.2010) has been running for 9 hours, the problem does not
manifest itself (with unpatched kernel the problem typically appear
within 1st hour of uptime).
>
> diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
> index 0030c52..c779491 100644
> --- a/sys/ufs/ufs/ufs_lookup.c
> +++ b/sys/ufs/ufs/ufs_lookup.c
> @@ -77,6 +77,32 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, "");
> /* true if old FS format...*/
> #define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
>
> +#ifdef QUOTA
> +static int
> +ufs_lookup_upgrade_lock(struct vnode *vp)
> +{
> + int error;
> +
> + ASSERT_VOP_LOCKED(vp, __FUNCTION__);
> + if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
> + return (0);
> +
> + error = 0;
> +
> + /*
> + * Upgrade vnode lock, since getinoquota()
> + * requires exclusive lock to modify inode.
> + */
> + vhold(vp);
> + vn_lock(vp, LK_UPGRADE | LK_RETRY);
> + VI_LOCK(vp);
> + if (vp->v_iflag & VI_DOOMED)
> + error = ENOENT;
> + vdropl(vp);
> + return (error);
> +}
> +#endif
> +
> static int
> ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred,
> struct thread *td)
> @@ -232,6 +258,13 @@ ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
> vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread);
>
> bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
> +#ifdef QUOTA
> + if ((nameiop == DELETE || nameiop == RENAME) && (flags & ISLASTCN)) {
> + error = ufs_lookup_upgrade_lock(vdp);
> + if (error != 0)
> + return (error);
> + }
> +#endif
>
> restart:
> bp = NULL;
>
--
Sincerely, Dmitry
nic-hdl: LYNX-RIPE
More information about the freebsd-fs
mailing list