diff options
author | Kinglong Mee <kinglongmee@gmail.com> | 2015-07-27 03:31:38 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-07-28 09:07:03 -0400 |
commit | a49c269111a5b3c1fd2a98f36fa27423b94549f8 (patch) | |
tree | cb3c567ca0cd593d0165aec3eb9dab012a9f7450 | |
parent | 3471648a7569512e10f154cdfe5076c341a5c099 (diff) |
nfs: Fix an oops caused by using other thread's stack space in ASYNC mode
An oops caused by using other thread's stack space in sunrpc ASYNC sending thread.
[ 9839.007187] ------------[ cut here ]------------
[ 9839.007923] kernel BUG at fs/nfs/nfs4xdr.c:910!
[ 9839.008069] invalid opcode: 0000 [#1] SMP
[ 9839.008069] Modules linked in: blocklayoutdriver rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache snd_hda_codec_generic snd_hda_intel snd_hda_controller snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm joydev iosf_mbi crct10dif_pclmul snd_timer crc32_pclmul crc32c_intel ghash_clmulni_intel snd soundcore ppdev pvpanic parport_pc i2c_piix4 serio_raw virtio_balloon parport acpi_cpufreq nfsd nfs_acl lockd grace auth_rpcgss sunrpc qxl drm_kms_helper virtio_net virtio_console virtio_blk ttm drm virtio_pci virtio_ring virtio ata_generic pata_acpi
[ 9839.008069] CPU: 0 PID: 308 Comm: kworker/0:1H Not tainted 4.0.0-0.rc4.git1.3.fc23.x86_64 #1
[ 9839.008069] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[ 9839.008069] Workqueue: rpciod rpc_async_schedule [sunrpc]
[ 9839.008069] task: ffff8800d8b4d8e0 ti: ffff880036678000 task.ti: ffff880036678000
[ 9839.008069] RIP: 0010:[<ffffffffa0339cc9>] [<ffffffffa0339cc9>] reserve_space.part.73+0x9/0x10 [nfsv4]
[ 9839.008069] RSP: 0018:ffff88003667ba58 EFLAGS: 00010246
[ 9839.008069] RAX: 0000000000000000 RBX: 000000001fc15e18 RCX: ffff8800c0193800
[ 9839.008069] RDX: ffff8800e4ae3f24 RSI: 000000001fc15e2c RDI: ffff88003667bcd0
[ 9839.008069] RBP: ffff88003667ba58 R08: ffff8800d9173008 R09: 0000000000000003
[ 9839.008069] R10: ffff88003667bcd0 R11: 000000000000000c R12: 0000000000010000
[ 9839.008069] R13: ffff8800d9173350 R14: 0000000000000000 R15: ffff8800c0067b98
[ 9839.008069] FS: 0000000000000000(0000) GS:ffff88011fc00000(0000) knlGS:0000000000000000
[ 9839.008069] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 9839.008069] CR2: 00007f988c9c8bb0 CR3: 00000000d99b6000 CR4: 00000000000407f0
[ 9839.008069] Stack:
[ 9839.008069] ffff88003667bbc8 ffffffffa03412c5 00000000c6c55680 ffff880000000003
[ 9839.008069] 0000000000000088 00000010c6c55680 0001000000000002 ffffffff816e87e9
[ 9839.008069] 0000000000000000 00000000477290e2 ffff88003667bab8 ffffffff81327ba3
[ 9839.008069] Call Trace:
[ 9839.008069] [<ffffffffa03412c5>] encode_attrs+0x435/0x530 [nfsv4]
[ 9839.008069] [<ffffffff816e87e9>] ? inet_sendmsg+0x69/0xb0
[ 9839.008069] [<ffffffff81327ba3>] ? selinux_socket_sendmsg+0x23/0x30
[ 9839.008069] [<ffffffff8164c1df>] ? do_sock_sendmsg+0x9f/0xc0
[ 9839.008069] [<ffffffff8164c278>] ? kernel_sendmsg+0x58/0x70
[ 9839.008069] [<ffffffffa011acc0>] ? xdr_reserve_space+0x20/0x170 [sunrpc]
[ 9839.008069] [<ffffffffa011acc0>] ? xdr_reserve_space+0x20/0x170 [sunrpc]
[ 9839.008069] [<ffffffffa0341b40>] ? nfs4_xdr_enc_open_noattr+0x130/0x130 [nfsv4]
[ 9839.008069] [<ffffffffa03419a5>] encode_open+0x2d5/0x340 [nfsv4]
[ 9839.008069] [<ffffffffa0341b40>] ? nfs4_xdr_enc_open_noattr+0x130/0x130 [nfsv4]
[ 9839.008069] [<ffffffffa011ab89>] ? xdr_encode_opaque+0x19/0x20 [sunrpc]
[ 9839.008069] [<ffffffffa0339cfb>] ? encode_string+0x2b/0x40 [nfsv4]
[ 9839.008069] [<ffffffffa0341bf3>] nfs4_xdr_enc_open+0xb3/0x140 [nfsv4]
[ 9839.008069] [<ffffffffa0110a4c>] rpcauth_wrap_req+0xac/0xf0 [sunrpc]
[ 9839.008069] [<ffffffffa01017db>] call_transmit+0x18b/0x2d0 [sunrpc]
[ 9839.008069] [<ffffffffa0101650>] ? call_decode+0x860/0x860 [sunrpc]
[ 9839.008069] [<ffffffffa0101650>] ? call_decode+0x860/0x860 [sunrpc]
[ 9839.008069] [<ffffffffa010caa0>] __rpc_execute+0x90/0x460 [sunrpc]
[ 9839.008069] [<ffffffffa010ce85>] rpc_async_schedule+0x15/0x20 [sunrpc]
[ 9839.008069] [<ffffffff810b452b>] process_one_work+0x1bb/0x410
[ 9839.008069] [<ffffffff810b47d3>] worker_thread+0x53/0x470
[ 9839.008069] [<ffffffff810b4780>] ? process_one_work+0x410/0x410
[ 9839.008069] [<ffffffff810b4780>] ? process_one_work+0x410/0x410
[ 9839.008069] [<ffffffff810ba7b8>] kthread+0xd8/0xf0
[ 9839.008069] [<ffffffff810ba6e0>] ? kthread_worker_fn+0x180/0x180
[ 9839.008069] [<ffffffff81786418>] ret_from_fork+0x58/0x90
[ 9839.008069] [<ffffffff810ba6e0>] ? kthread_worker_fn+0x180/0x180
[ 9839.008069] Code: 00 00 48 c7 c7 21 fa 37 a0 e8 94 1c d6 e0 c6 05 d2 17 05 00 01 8b 03 eb d7 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 <0f> 0b 0f 1f 44 00 00 66 66 66 66 90 55 48 89 e5 41 54 53 89 f3
[ 9839.008069] RIP [<ffffffffa0339cc9>] reserve_space.part.73+0x9/0x10 [nfsv4]
[ 9839.008069] RSP <ffff88003667ba58>
[ 9839.071114] ---[ end trace cc14c03adb522e94 ]---
Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/internal.h | 21 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 10 |
2 files changed, 30 insertions, 1 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 9e6475bc5ba2..797013822765 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -296,6 +296,22 @@ extern struct rpc_procinfo nfs4_procedures[]; | |||
296 | 296 | ||
297 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 297 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
298 | extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); | 298 | extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); |
299 | static inline struct nfs4_label * | ||
300 | nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) | ||
301 | { | ||
302 | if (!dst || !src) | ||
303 | return NULL; | ||
304 | |||
305 | if (src->len > NFS4_MAXLABELLEN) | ||
306 | return NULL; | ||
307 | |||
308 | dst->lfs = src->lfs; | ||
309 | dst->pi = src->pi; | ||
310 | dst->len = src->len; | ||
311 | memcpy(dst->label, src->label, src->len); | ||
312 | |||
313 | return dst; | ||
314 | } | ||
299 | static inline void nfs4_label_free(struct nfs4_label *label) | 315 | static inline void nfs4_label_free(struct nfs4_label *label) |
300 | { | 316 | { |
301 | if (label) { | 317 | if (label) { |
@@ -316,6 +332,11 @@ static inline void nfs4_label_free(void *label) {} | |||
316 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) | 332 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) |
317 | { | 333 | { |
318 | } | 334 | } |
335 | static inline struct nfs4_label * | ||
336 | nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) | ||
337 | { | ||
338 | return NULL; | ||
339 | } | ||
319 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | 340 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ |
320 | 341 | ||
321 | /* proc.c */ | 342 | /* proc.c */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c85ffe67b5f3..e94a964e9b4f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -912,6 +912,7 @@ struct nfs4_opendata { | |||
912 | struct nfs_open_confirmres c_res; | 912 | struct nfs_open_confirmres c_res; |
913 | struct nfs4_string owner_name; | 913 | struct nfs4_string owner_name; |
914 | struct nfs4_string group_name; | 914 | struct nfs4_string group_name; |
915 | struct nfs4_label *a_label; | ||
915 | struct nfs_fattr f_attr; | 916 | struct nfs_fattr f_attr; |
916 | struct nfs4_label *f_label; | 917 | struct nfs4_label *f_label; |
917 | struct dentry *dir; | 918 | struct dentry *dir; |
@@ -1015,6 +1016,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
1015 | if (IS_ERR(p->f_label)) | 1016 | if (IS_ERR(p->f_label)) |
1016 | goto err_free_p; | 1017 | goto err_free_p; |
1017 | 1018 | ||
1019 | p->a_label = nfs4_label_alloc(server, gfp_mask); | ||
1020 | if (IS_ERR(p->a_label)) | ||
1021 | goto err_free_f; | ||
1022 | |||
1018 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; | 1023 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; |
1019 | p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask); | 1024 | p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask); |
1020 | if (IS_ERR(p->o_arg.seqid)) | 1025 | if (IS_ERR(p->o_arg.seqid)) |
@@ -1043,7 +1048,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
1043 | p->o_arg.server = server; | 1048 | p->o_arg.server = server; |
1044 | p->o_arg.bitmask = nfs4_bitmask(server, label); | 1049 | p->o_arg.bitmask = nfs4_bitmask(server, label); |
1045 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; | 1050 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; |
1046 | p->o_arg.label = label; | 1051 | p->o_arg.label = nfs4_label_copy(p->a_label, label); |
1047 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); | 1052 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); |
1048 | switch (p->o_arg.claim) { | 1053 | switch (p->o_arg.claim) { |
1049 | case NFS4_OPEN_CLAIM_NULL: | 1054 | case NFS4_OPEN_CLAIM_NULL: |
@@ -1076,6 +1081,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
1076 | return p; | 1081 | return p; |
1077 | 1082 | ||
1078 | err_free_label: | 1083 | err_free_label: |
1084 | nfs4_label_free(p->a_label); | ||
1085 | err_free_f: | ||
1079 | nfs4_label_free(p->f_label); | 1086 | nfs4_label_free(p->f_label); |
1080 | err_free_p: | 1087 | err_free_p: |
1081 | kfree(p); | 1088 | kfree(p); |
@@ -1095,6 +1102,7 @@ static void nfs4_opendata_free(struct kref *kref) | |||
1095 | nfs4_put_open_state(p->state); | 1102 | nfs4_put_open_state(p->state); |
1096 | nfs4_put_state_owner(p->owner); | 1103 | nfs4_put_state_owner(p->owner); |
1097 | 1104 | ||
1105 | nfs4_label_free(p->a_label); | ||
1098 | nfs4_label_free(p->f_label); | 1106 | nfs4_label_free(p->f_label); |
1099 | 1107 | ||
1100 | dput(p->dir); | 1108 | dput(p->dir); |