tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

vnode lock and v_numoutput



Hello,
I have what looks like a deadlock in a Xen dom0 when using
file-backed virtual disk and HVM domUs (the dom0 is running netbsd-6).
In this setup, a file backing a virtual disk may be acceded by both
a vnd(4) and a qemu-dm userland process.
I end up in this situation:
qemu-dm is blocked on:
trace: pid 5171 lid 5 at 0xffffa0005e744740
sleepq_block() at netbsd:sleepq_block+0xc5
cv_wait() at netbsd:cv_wait+0xf2
genfs_do_putpages() at netbsd:genfs_do_putpages+0xa0e
VOP_PUTPAGES() at netbsd:VOP_PUTPAGES+0x5b
vflushbuf() at netbsd:vflushbuf+0x4b
ffs_full_fsync() at netbsd:ffs_full_fsync+0x143
ffs_fsync() at netbsd:ffs_fsync+0x4b
VOP_FSYNC() at netbsd:VOP_FSYNC+0x5f
sys_fsync() at netbsd:sys_fsync+0x51
syscall() at netbsd:syscall+0xc4

(gdb) l *(genfs_do_putpages+0xa0e)
0xffffffff801bc7d4 is in genfs_do_putpages (../../../../miscfs/genfs/genfs_io.c:1246).
1241    skip_scan:
1242    #endif /* !defined(DEBUG) */
1243    
1244            /* Wait for output to complete. */
1245            if (!wasclean && !async && vp->v_numoutput != 0) {
1246                    while (vp->v_numoutput != 0)
1247                            cv_wait(&vp->v_cv, slock);
1248            }
1249            onworklst = (vp->v_iflag & VI_ONWORKLST) != 0;
1250            mutex_exit(slock);

while the vnd is blocked on:
db>   tr/a ffffa00005416280
trace: pid 0 lid 88 at 0xffffa0005c100a40
sleepq_block() at netbsd:sleepq_block+0xc5
turnstile_block() at netbsd:turnstile_block+0x3c6
rw_vector_enter() at netbsd:rw_vector_enter+0x17a
genfs_lock() at netbsd:genfs_lock+0x9f
VOP_LOCK() at netbsd:VOP_LOCK+0x53
vn_lock() at netbsd:vn_lock+0xd9
vndthread() at netbsd:vndthread+0x43d

(gdb) l *(vndthread+0x43d)
0xffffffff804c8faa is in vndthread (../../../../dev/vnd.c:818).
813                     daddr_t nbn;
814                     int off, nra;
815     
816                     nra = 0;
817                     vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
818                     error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra);
819                     VOP_UNLOCK(vnd->sc_vp);
820     
821                     if (error == 0 && (long)nbn == -1)
822                             error = EIO;


I guess what happens is:
vndthread is blocked trying to get the vn_lock because the  thread
doing the sys_fsync() is holding it.
The thread in sys_fsync() waits for v_numoutput to go down to 0,
but this won't happen because vndthread has increased v_numoutput but
has not queued the I/O yet.

Should a thread hold the vnode lock (vn_lock()) before increasing v_numoutput ?
If so vnd(4) gets it wrong, and it doens't look easy to fix :(
I don't know if handle_with_rdwr() holds the vn_lock() at all.
handle_with_strategy() gets the vn_lock(), but it increases the
v_numoutput grabbing the lock. I guess it should also handle the lock
when calling nestiobuf_setup()

Any idea or comment ?

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--


Home | Main Index | Thread Index | Old Index