From: Jeff Layton Date: Tue, 18 Jun 2013 13:10:29 +0000 (-0400) Subject: rpc_pipefs: only set rpc_dentry_ops if d_op isn't already set X-Git-Tag: upstream/snapshot3+hdmi~4761^2~19 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e401452d923de5b27f61f707773ec38f5593d985;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git rpc_pipefs: only set rpc_dentry_ops if d_op isn't already set We had a report of a reproducible WARNING: [ 1360.039358] ------------[ cut here ]------------ [ 1360.043978] WARNING: at fs/dcache.c:1355 d_set_d_op+0x8d/0xc0() [ 1360.049880] Hardware name: HP Z200 Workstation [ 1360.054308] Modules linked in: nfsv4 nfs dns_resolver fscache nfsd auth_rpcgss nfs_acl lockd sunrpc sg acpi_cpufreq mperf coretemp kvm_intel kvm snd_hda_codec_realtek snd_hda_intel snd_hda_codec hp_wmi crc32c_intel snd_hwdep e1000e snd_seq snd_seq_device snd_pcm snd_page_alloc snd_timer snd sparse_keymap rfkill soundcore serio_raw ptp iTCO_wdt pps_core pcspkr iTCO_vendor_support mei microcode lpc_ich mfd_core wmi xfs libcrc32c sr_mod sd_mod cdrom crc_t10dif radeon i2c_algo_bit drm_kms_helper ttm ahci libahci drm i2c_core libata dm_mirror dm_region_hash dm_log dm_mod [last unloaded: auth_rpcgss] [ 1360.107406] Pid: 8814, comm: mount.nfs4 Tainted: G I -------------- 3.9.0-0.55.el7.x86_64 #1 [ 1360.116771] Call Trace: [ 1360.119219] [] warn_slowpath_common+0x70/0xa0 [ 1360.125208] [] warn_slowpath_null+0x1a/0x20 [ 1360.131025] [] d_set_d_op+0x8d/0xc0 [ 1360.136159] [] __rpc_lookup_create_exclusive+0x4f/0x80 [sunrpc] [ 1360.143710] [] rpc_mkpipe_dentry+0x86/0x170 [sunrpc] [ 1360.150311] [] nfs_idmap_new+0x96/0x130 [nfsv4] [ 1360.156475] [] nfs4_init_client+0xad/0x2d0 [nfsv4] [ 1360.162902] [] ? idr_get_empty_slot+0x16f/0x3c0 [ 1360.169062] [] ? idr_mark_full+0x52/0x60 [ 1360.174615] [] ? idr_alloc+0x79/0xe0 [ 1360.179826] [] ? __rpc_init_priority_wait_queue+0x81/0xc0 [sunrpc] [ 1360.187635] [] ? rpc_init_wait_queue+0x13/0x20 [sunrpc] [ 1360.194493] [] nfs_get_client+0x27a/0x350 [nfs] [ 1360.200666] [] nfs4_set_client.isra.8+0x78/0x100 [nfsv4] [ 1360.207624] [] nfs4_create_server+0xf3/0x3a0 [nfsv4] [ 1360.214222] [] nfs4_remote_mount+0x2e/0x60 [nfsv4] [ 1360.220644] [] mount_fs+0x39/0x1b0 [ 1360.225691] [] ? __alloc_percpu+0x10/0x20 [ 1360.231348] [] vfs_kern_mount+0x5f/0xf0 [ 1360.236822] [] nfs_do_root_mount+0x86/0xc0 [nfsv4] [ 1360.243246] [] nfs4_try_mount+0x44/0xc0 [nfsv4] [ 1360.249410] [] ? get_nfs_version+0x27/0x80 [nfs] [ 1360.255659] [] nfs_fs_mount+0x5c5/0xd10 [nfs] [ 1360.261650] [] ? nfs_clone_super+0x140/0x140 [nfs] [ 1360.268074] [] ? param_set_portnr+0x60/0x60 [nfs] [ 1360.274406] [] mount_fs+0x39/0x1b0 [ 1360.279443] [] ? __alloc_percpu+0x10/0x20 [ 1360.285088] [] vfs_kern_mount+0x5f/0xf0 [ 1360.290556] [] do_mount+0x1fd/0xa00 [ 1360.295677] [] ? __get_free_pages+0xe/0x50 [ 1360.301405] [] ? copy_mount_options+0x36/0x170 [ 1360.307479] [] sys_mount+0x83/0xc0 [ 1360.312515] [] system_call_fastpath+0x16/0x1b [ 1360.318503] ---[ end trace 8fa1f4cbc36094a7 ]--- The problem is that we're ending up in __rpc_lookup_create_exclusive with a negative dentry that already has d_op set. A little debugging has shown that when we hit this, the d_ops are already set to simple_dentry_operations. I believe that what's happening is that during a mount, idmapd is racing in and doing a lookup of /var/lib/nfs/rpc_pipefs/nfs/clnt???/idmap. Before that dentry reference is released, the kernel races in to create that file and finds the new negative dentry, which already has the d_op set. This patch just avoids setting the d_op if it's already set. simple_dentry_operations and rpc_dentry_operations are functionally equivalent so it shouldn't matter which one it's set to. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index e7ce4b3..a816b3a 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -667,7 +667,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, return ERR_PTR(-ENOMEM); } if (dentry->d_inode == NULL) { - d_set_d_op(dentry, &rpc_dentry_operations); + if (!dentry->d_op) + d_set_d_op(dentry, &rpc_dentry_operations); return dentry; } dput(dentry);