Bug about devfs?
Kohji Okuno
okuno.kohji at jp.panasonic.com
Tue Jul 12 11:34:27 UTC 2011
Hello,
From: Kostik Belousov <kostikbel at gmail.com>
Subject: Re: Bug about devfs?
Date: Tue, 12 Jul 2011 14:19:25 +0300
Message-ID: <20110712111925.GH43872 at deviant.kiev.zoral.com.ua>
> Thank you for the report.
>
> The proposed change would revert r179247, which also caused some issues.
> Are you able to reproduce the problem ?
>
> Could you try the following patch ? I cannot reproduce your situation,
> so the patch is untested by me.
Thank you for quick your comment.
I think that your change is beter than mine.
I will test it, and I will report the result.
> On Tue, Jul 12, 2011 at 07:10:28PM +0900, Kohji Okuno wrote:
>> Hello,
>>
>> I think that devfs has a problem.
>> I encountered the problem that open("/dev/AAA") returned ENOENT.
>> Of course, /dev/AAA exists.
>>
>> ENOENT was created by the point(***) in devfs_allocv().
>> I think that the race condition had occurred between process A and
>> vnlru kernel thread.
>>
>> Please check the following.
>>
>> If vnlru set VI_DOOMED to vp->v_iflag but vnlru didn't still execute
>> VOP_RECLAIM(), process A cat get valid vp from de->de_vnode.
>> But, vget() will return ENOENT, because vp->v_iflag has VI_DOOMED.
>>
>> When I set the break point to (***), I checked that de->de_vnode and
>> vp->v_data were NULL.
>>
>>
>> process A: vnlru:
>>
>> devfs_allocv() {
>> vgonel(vp) {
>> ... ...
>> vp->v_iflag |= VI_DOOMED;
>> mtx_lock(&devfs_de_interlock); ...
>> vp = de->de_vnode;
>> if (vp != NULL) { VI_UNLOCK(vp);
>> _____________/ ...
>> VI_LOCK(vp); ____________/ if (VOP_RECLAIM(vp, td))
>> mtx_unlock(&devfs_de_interlock); ...
>> ... \ devfs_reclaim(ap) {
>> error = vget(vp,...); \
>> ... \______ mtx_lock(&devfs_de_interlock);
>> if (devfs_allocv_drop_refs(...)) { de = vp->v_data;
>> ... if (de != NULL) {
>> } de->de_vnode = NULL;
>> else if (error) { vp->v_data = NULL;
>> ... }
>> rturn (error); (***) mtx_unlock(&devfs_de_interlock);
>> } ...
>> }
>>
>>
>>
>> I think that devfs_allocv() should be fixed as below.
>> How do you think?
>>
>> devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp)
>> {
>> int error;
>> struct vnode *vp;
>> struct cdev *dev;
>> struct devfs_mount *dmp;
>>
>> dmp = VFSTODEVFS(mp);
>> +#if 1
>> + retry:
>> +#endif
>> if (de->de_flags & DE_DOOMED) {
>>
>> ...
>>
>> mtx_lock(&devfs_de_interlock);
>> vp = de->de_vnode;
>> if (vp != NULL) {
>> VI_LOCK(vp);
>> mtx_unlock(&devfs_de_interlock);
>> sx_xunlock(&dmp->dm_lock);
>> error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, curthread);
>> sx_xlock(&dmp->dm_lock);
>> if (devfs_allocv_drop_refs(0, dmp, de)) {
>> if (error == 0)
>> vput(vp);
>> return (ENOENT);
>> }
>> else if (error) {
>> +#if 1
>> + if (error == ENOENT)
>> + goto retry;
>> +#endif
>> sx_xunlock(&dmp->dm_lock);
>> return (error);
>> }
>>
> Thank you for the report.
>
> The proposed change would revert r179247, which also caused some issues.
> Are you able to reproduce the problem ?
>
> Could you try the following patch ? I cannot reproduce your situation,
> so the patch is untested by me.
>
> diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
> index bf6dab8..bbbfff4 100644
> --- a/sys/fs/devfs/devfs_vnops.c
> +++ b/sys/fs/devfs/devfs_vnops.c
> @@ -397,6 +397,7 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
> sx_xunlock(&dmp->dm_lock);
> return (ENOENT);
> }
> +loop:
> DEVFS_DE_HOLD(de);
> DEVFS_DMP_HOLD(dmp);
> mtx_lock(&devfs_de_interlock);
> @@ -412,7 +413,16 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
> vput(vp);
> return (ENOENT);
> }
> - else if (error) {
> + else if (error != 0) {
> + if (error == ENOENT) {
> + mtx_lock(&devfs_de_interlock);
> + while (de->de_vnode != NULL) {
> + msleep(&de->de_vnode,
> + &devfs_de_interlock, 0, "dvall", 0);
> + }
> + mtx_unlock(&devfs_de_interlock);
> + goto loop;
> + }
> sx_xunlock(&dmp->dm_lock);
> return (error);
> }
> @@ -1259,6 +1269,7 @@ devfs_reclaim(struct vop_reclaim_args *ap)
> if (de != NULL) {
> de->de_vnode = NULL;
> vp->v_data = NULL;
> + wakeup(&de->de_vnode);
> }
> mtx_unlock(&devfs_de_interlock);
>
>
>
More information about the freebsd-current
mailing list