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