Toralf reported the following oops to the linux-nfs mailing list:
-----------------[snip]------------------
NFSD: unable to generate recoverydir name (-2).
NFSD: disabling legacy clientid tracking. Reboot recovery will not function correctly!
BUG: unable to handle kernel NULL pointer dereference at
000003c8
IP: [<
f90a3d91>] nfsd4_client_tracking_exit+0x11/0x50 [nfsd]
*pdpt =
000000002ba33001 *pde =
0000000000000000
Oops: 0000 [#1] SMP
Modules linked in: loop nfsd auth_rpcgss ipt_MASQUERADE xt_owner xt_multiport ipt_REJECT xt_tcpudp xt_recent xt_conntrack nf_conntrack_ftp xt_limit xt_LOG iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_filter ip_tables x_tables af_packet pppoe pppox ppp_generic slhc bridge stp llc tun arc4 iwldvm mac80211 coretemp kvm_intel uvcvideo sdhci_pci sdhci mmc_core videobuf2_vmalloc videobuf2_memops usblp videobuf2_core i915 iwlwifi psmouse videodev cfg80211 kvm fbcon bitblit cfbfillrect acpi_cpufreq mperf evdev softcursor font cfbimgblt i2c_algo_bit cfbcopyarea intel_agp intel_gtt drm_kms_helper snd_hda_codec_conexant drm agpgart fb fbdev tpm_tis thinkpad_acpi tpm nvram e1000e rfkill thermal ptp wmi pps_core tpm_bios 8250_pci processor 8250 ac snd_hda_intel snd_hda_codec snd_pcm battery video i2c_i801 snd_page_alloc snd_timer button serial_core i2c_core snd soundcore thermal_sys hwmon aesni_intel ablk_helper cryp
td lrw aes_i586 xts gf128mul cbc fuse nfs lockd sunrpc dm_crypt dm_mod hid_monterey hid_microsoft hid_logitech hid_ezkey hid_cypress hid_chicony hid_cherry hid_belkin hid_apple hid_a4tech hid_generic usbhid hid sr_mod cdrom sg [last unloaded: microcode]
Pid: 6374, comm: nfsd Not tainted 3.9.1 #6 LENOVO
4180F65/
4180F65
EIP: 0060:[<
f90a3d91>] EFLAGS:
00010202 CPU: 0
EIP is at nfsd4_client_tracking_exit+0x11/0x50 [nfsd]
EAX:
00000000 EBX:
fffffffe ECX:
00000007 EDX:
00000007
ESI:
eb9dcb00 EDI:
eb2991c0 EBP:
eb2bde38 ESP:
eb2bde34
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
CR0:
80050033 CR2:
000003c8 CR3:
2ba80000 CR4:
000407f0
DR0:
00000000 DR1:
00000000 DR2:
00000000 DR3:
00000000
DR6:
ffff0ff0 DR7:
00000400
Process nfsd (pid: 6374, ti=
eb2bc000 task=
eb2711c0 task.ti=
eb2bc000)
Stack:
fffffffe eb2bde4c f90a3e0c f90a7754 fffffffe eb0a9c00 eb2bdea0 f90a41ed
eb2991c0 1b270000 eb2991c0 eb2bde7c f9099ce9 eb2bde98 0129a020 eb29a020
eb2bdecc eb2991c0 eb2bdea8 f9099da5 00000000 eb9dcb00 00000001 67822f08
Call Trace:
[<
f90a3e0c>] legacy_recdir_name_error+0x3c/0x40 [nfsd]
[<
f90a41ed>] nfsd4_create_clid_dir+0x15d/0x1c0 [nfsd]
[<
f9099ce9>] ? nfsd4_lookup_stateid+0x99/0xd0 [nfsd]
[<
f9099da5>] ? nfs4_preprocess_seqid_op+0x85/0x100 [nfsd]
[<
f90a4287>] nfsd4_client_record_create+0x37/0x50 [nfsd]
[<
f909d6ce>] nfsd4_open_confirm+0xfe/0x130 [nfsd]
[<
f90980b1>] ? nfsd4_encode_operation+0x61/0x90 [nfsd]
[<
f909d5d0>] ? nfsd4_free_stateid+0xc0/0xc0 [nfsd]
[<
f908fd0b>] nfsd4_proc_compound+0x41b/0x530 [nfsd]
[<
f9081b7b>] nfsd_dispatch+0x8b/0x1a0 [nfsd]
[<
f857b85d>] svc_process+0x3dd/0x640 [sunrpc]
[<
f908165d>] nfsd+0xad/0x110 [nfsd]
[<
f90815b0>] ? nfsd_destroy+0x70/0x70 [nfsd]
[<
c1054824>] kthread+0x94/0xa0
[<
c1486937>] ret_from_kernel_thread+0x1b/0x28
[<
c1054790>] ? flush_kthread_work+0xd0/0xd0
Code: 86 b0 00 00 00 90 c5 0a f9 c7 04 24 70 76 0a f9 e8 74 a9 3d c8 eb ba 8d 76 00 55 89 e5 53 66 66 66 66 90 8b 15 68 c7 0a f9 85 d2 <8b> 88 c8 03 00 00 74 2c 3b 11 77 28 8b 5c 91 08 85 db 74 22 8b
EIP: [<
f90a3d91>] nfsd4_client_tracking_exit+0x11/0x50 [nfsd] SS:ESP 0068:
eb2bde34
CR2:
00000000000003c8
---[ end trace
09e54015d145c9c6 ]---
The problem appears to be a regression that was introduced in commit
9a9c6478 "nfsd: make NFSv4 recovery client tracking options per net".
Prior to that commit, it was safe to pass a NULL net pointer to
nfsd4_client_tracking_exit in the legacy recdir case, and
legacy_recdir_name_error did so. After that comit, the net pointer must
be valid.
This patch just fixes legacy_recdir_name_error to pass in a valid net
pointer to that function.
Cc: <stable@vger.kernel.org> # v3.8+
Cc: Stanislav Kinsbursky <skinsbursky@parallels.com>
Reported-and-tested-by: Toralf Förster <toralf.foerster@gmx.de>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
* then disable recovery tracking.
*/
static void
-legacy_recdir_name_error(int error)
+legacy_recdir_name_error(struct nfs4_client *clp, int error)
{
printk(KERN_ERR "NFSD: unable to generate recoverydir "
"name (%d).\n", error);
if (error == -ENOENT) {
printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
"Reboot recovery will not function correctly!\n");
-
- /* the argument is ignored by the legacy exit function */
- nfsd4_client_tracking_exit(NULL);
+ nfsd4_client_tracking_exit(clp->net);
}
}
status = nfs4_make_rec_clidname(dname, &clp->cl_name);
if (status)
- return legacy_recdir_name_error(status);
+ return legacy_recdir_name_error(clp, status);
status = nfs4_save_creds(&original_cred);
if (status < 0)
status = nfs4_make_rec_clidname(dname, &clp->cl_name);
if (status)
- return legacy_recdir_name_error(status);
+ return legacy_recdir_name_error(clp, status);
status = mnt_want_write_file(nn->rec_file);
if (status)
status = nfs4_make_rec_clidname(dname, &clp->cl_name);
if (status) {
- legacy_recdir_name_error(status);
+ legacy_recdir_name_error(clp, status);
return status;
}