NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/50432: NFS client crashes or hangs kernel
>Number: 50432
>Category: kern
>Synopsis: NFS client crashes or hangs kernel
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Nov 15 21:10:00 +0000 2015
>Originator: Rhialto
>Release: NetBSD 7.0
>Organization:
>Environment:
System: NetBSD vargaz.falu.nl 7.0 NetBSD 7.0 (GENERIC.201509250726Z) amd64
Architecture: x86_64
Machine: amd64
>Description:
Following a thread on current-users and tech-kern, I'm filing this PR so
that the issue doesn't get lost. No resolution was reached. I'm
summarizing the useful contents here.
(http://mail-index.netbsd.org/current-users/2015/10/19/msg028233.html)
NFS clients on NetBSD 7.0 (plain GENERIC kernel as distributed) seem to
have a problem with the queue of outstanding requests to the server
(nfs_reqq). As a result, either the kernel crashes because the queue is
traversed while it contains bogus pointers, or processes start to hang
on NFS I/O, because their I/O seemingly never completes. (The reply no
doubt was received, but could not be matched to an outstanding request
and was therefore dropped).
What I'm doing when this happens: I'm mounting a pkg_comp chroot which
is located on NFS. On top of it, I mount a local directory for temporary
files. But lots of NFS traffic still happens, mostly readonly, but
writing when it creates and installs the packages. The extra null mounts
that pkg_comp does may make things more fragile.
All mounts:
/dev/wd0a on / type ffs (local)
/dev/wd0f on /var type ffs (log, local)
/dev/wd0e on /usr type ffs (log, local)
/dev/wd0g on /home type ffs (log, local)
/dev/wd0h on /tmp type ffs (log, local)
kernfs on /kern type kernfs (local)
ptyfs on /dev/pts type ptyfs (local)
procfs on /proc type procfs (local)
procfs on /usr/pkg/emul/linux32/proc type procfs (read-only, local)
nfsserver:/mnt/vol1 on /mnt/vol1 type nfs
nfsserver:/mnt/scratch on /mnt/scratch type nfs
tmpfs on /var/shm type tmpfs (local)
/mnt/vol1/rhialto/cvs/src on /mnt/scratch/scratch/chroot/pkg_comp.amd64-7.0/default/usr/src type null (read-only)
/mnt/vol1/rhialto/cvs/pkgsrc on /mnt/scratch/scratch/chroot/pkg_comp.amd64-7.0/default/usr/pkgsrc type null (read-only)
/mnt/vol1/distfiles on /mnt/scratch/scratch/chroot/pkg_comp.amd64-7.0/default/pkg_comp/distfiles type null
/mnt/scratch/scratch/packages.amd64-7.0 on /mnt/scratch/scratch/chroot/pkg_comp.amd64-7.0/default/pkg_comp/packages type null
/home/rhialto/obj on /mnt/scratch/scratch/chroot/pkg_comp.amd64-7.0/default/pkg_comp/obj/pkgsrc type null (local)
The problem did not go away when I changed the mount from UDP to TCP.
Here is some debugging I've done on this.
I re-tried and with an original GENERIC 7.0 kernel it happened again and
now I have a crash dump. Its dmesg ends with this:
nfs server 10.0.0.16:/mnt/scratch: not responding
nfs server 10.0.0.16:/mnt/scratch: is alive again
fatal page fault in supervisor mode
trap type 6 code 0 rip ffffffff806b94b4 cs 8 rflags 10246 cr2 38 ilevel 2 rsp ff
fffe80b9fc1f28
curlwp 0xfffffe813fb39860 pid 0.5 lowest kstack 0xfffffe80b9fbf2c0
panic: trap
cpu0: Begin traceback...
vpanic() at netbsd:vpanic+0x13c
snprintf() at netbsd:snprintf
startlwp() at netbsd:startlwp
alltraps() at netbsd:alltraps+0x96
callout_softclock() at netbsd:callout_softclock+0x248
softint_dispatch() at netbsd:softint_dispatch+0x79
DDB lost frame for netbsd:Xsoftintr+0x4f, trying 0xfffffe80b9fc1ff0
Xsoftintr() at netbsd:Xsoftintr+0x4f
--- interrupt ---
0:
cpu0: End traceback...
dumping to dev 0,1 (offset=199775, size=1023726):
pid 0.5 is this:
PID LID S CPU FLAGS STRUCT LWP * NAME WAIT
0 > 5 7 0 200 fffffe813fb39860 softclk/0
gdb (without debugging symbols) so far thinks this is in nfs_timer():
(gdb) kvm proc 0xfffffe813fb39860
0xffffffff806b9aab in nfs_timer ()
(gdb) bt
#0 0xffffffff806b9aab in nfs_timer ()
#1 0x0000000000000000 in ?? ()
with a rebuilt netbsd.gdb (hopefully the addresses match)
(gdb) target kvm netbsd.5.core
0xffffffff8063d735 in cpu_reboot (howto=howto@entry=260,
bootstr=bootstr@entry=0x0) at ../../../../arch/amd64/amd64/machdep.c:671
671 dumpsys();
(gdb) bt
#0 0xffffffff8063d735 in cpu_reboot (howto=howto@entry=260,
bootstr=bootstr@entry=0x0) at ../../../../arch/amd64/amd64/machdep.c:671
#1 0xffffffff80865182 in vpanic (fmt=0xffffffff80d123b2 "trap",
fmt@entry=0xffffffff80d123d2 "otection fault",
ap=ap@entry=0xfffffe80b9fc1d10) at ../../../../kern/subr_prf.c:340
#2 0xffffffff8086523d in panic (fmt=fmt@entry=0xffffffff80d123d2
"otection fault") at ../../../../kern/subr_prf.c:256
#3 0xffffffff808a84d6 in trap (frame=0xfffffe80b9fc1e30) at
../../../../arch/amd64/amd64/trap.c:298
#4 0xffffffff80100f46 in alltraps ()
#5 0xffffffff806b94b4 in nfs_sigintr (nmp=0x0, rep=0xfffffe81163730a8,
l=0x0) at ../../../../nfs/nfs_socket.c:871
#6 0xffffffff806b9b0e in nfs_timer (arg=<optimized out>) at
../../../../nfs/nfs_socket.c:752
#7 0xffffffff805e9458 in callout_softclock (v=<optimized out>) at
../../../../kern/kern_timeout.c:736
#8 0xffffffff805df84a in softint_execute (l=<optimized out>,
s=<optimized out>, si=<optimized out>) at
../../../../kern/kern_softint.c:589
#9 softint_dispatch (pinned=<optimized out>, s=2) at
../../../../kern/kern_softint.c:871
#10 0xffffffff8011402f in Xsoftintr ()
(gdb) kvm proc 0xfffffe813fb39860
nfs_timer (arg=<unavailable>) at ../../../../nfs/nfs_socket.c:735
735 {
(gdb) bt
#0 nfs_timer (arg=<unavailable>) at ../../../../nfs/nfs_socket.c:735
#1 0x0000000000000000 in ?? ()
nmp should not be NULL here... let's look at rep, where it comes from
via "nmp = rep->r_nmp;"
(gdb) print *(struct nfsreq *)0xfffffe81163730a8
$1 = {r_chain = {tqe_next = 0xfffffe811edcee40, tqe_prev = 0x1}, r_mreq = 0xffff8000028f9888, r_mrep = 0x0, r_md = 0x0, r_dpos = 0x0, r_nmp = 0x0, r_xid = 0, r_flags = 0, r_retry = 0, r_rexmit = 0, r_procnum = 0, r_rtt = 0,
r_lwp = 0x0}
well, r_chain.tqe_prev looks bogus (unless that's a special marker), so
let's look at tqe_next:
(gdb) print *((struct nfsreq *)0xfffffe81163730a8)->r_chain.tqe_next
$3 = {r_chain = {tqe_next = 0x0, tqe_prev = 0x15aa3c85d}, r_mreq = 0xbd83e8af8fe58282, r_mrep = 0x81e39981e3a781e3, r_md = 0xe39d81e38180e38c, r_dpos = 0x8890e5b4a0e5ae81, r_nmp = 0xe57baf81e3ab81e3, r_xid = 2179183259,
r_flags = -1565268289, r_retry = 0, r_rexmit = 0, r_procnum = 1520683101, r_rtt = 1, r_lwp = 0x80e39981e3a781e3}
well, even more bogus. Too bad that the next frame has its argument
optimized out...
This problem is very repeatable, usually within a few hours, but a few
times now it happened within half an hour.
It seems to me that somehow the nfs_reqq list gets corrupted. Then
either there is a crash when traversing it in nfs_timer() (occurring in
nfs_sigintr() due to being called with a bogus pointer), or there is a
hang when one of the NFS requests gets lost and never retried.
I tried it with a TCP mount for NFS. Still hangs, this time in a bit
under an hour of uptime.
So the cause is likely not packet loss.
Further looking into this by examining where nfs_reqq occurs:
nfs/nfs.h:extern TAILQ_HEAD(nfsreqhead, nfsreq) nfs_reqq;
nfs/nfs_clntsocket.c: TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
nfs/nfs_clntsocket.c: TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
nfs/nfs_clntsocket.c: TAILQ_REMOVE(&nfs_reqq, rep, r_chain);
Protected with
s = splsoftnet();
for match #2 and #3 but #1 seems not protected by anything I can see
nearby. Maybe it is
error = nfs_rcvlock(nmp, myrep);
if that makes any sense.
That function definitely does not use either splsoftnet() OR
mutex_enter(softnet_lock).
nfs/nfs_socket.c:struct nfsreqhead nfs_reqq;
nfs/nfs_socket.c: TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
nfs/nfs_socket.c: TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
match #3 is protected with
mutex_enter(softnet_lock); /* XXX PR 40491 */
but none of the others (visibly nearby).
#2 is called from nfs_receive() which uses nfs_sndlock() which also
doesn't use either splsoftnet() OR mutex_enter(softnet_lock).
nfs/nfs_subs.c: TAILQ_INIT(&nfs_reqq);
presumably doesn't need any extra protection.
softnet_lock is allocated as
./kern/uipc_socket.c:kmutex_t *softnet_lock;
./kern/uipc_socket.c: softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
IPL_NONE seems inconsistent with splsoftnet().
I never studied the inner details of kernel locking, but the diversity
of protections of this list doesn't inspire trust at first sight.
===
And this is how far it got so far.
>How-To-Repeat:
Use pkg_comp with the chroot directory on an NFS-mounted volume.
(see above for more details).
>Fix:
Not known.
-Olaf.
--
___ Olaf 'Rhialto' Seibert -- The Doctor: No, 'eureka' is Greek for
\X/ rhialto/at/xs4all.nl -- 'this bath is too hot.'
>Unformatted:
Home |
Main Index |
Thread Index |
Old Index