From a49c269111a5b3c1fd2a98f36fa27423b94549f8 Mon Sep 17 00:00:00 2001 From: Kinglong Mee Date: Mon, 27 Jul 2015 15:31:38 +0800 Subject: 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:[] [] 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] [] encode_attrs+0x435/0x530 [nfsv4] [ 9839.008069] [] ? inet_sendmsg+0x69/0xb0 [ 9839.008069] [] ? selinux_socket_sendmsg+0x23/0x30 [ 9839.008069] [] ? do_sock_sendmsg+0x9f/0xc0 [ 9839.008069] [] ? kernel_sendmsg+0x58/0x70 [ 9839.008069] [] ? xdr_reserve_space+0x20/0x170 [sunrpc] [ 9839.008069] [] ? xdr_reserve_space+0x20/0x170 [sunrpc] [ 9839.008069] [] ? nfs4_xdr_enc_open_noattr+0x130/0x130 [nfsv4] [ 9839.008069] [] encode_open+0x2d5/0x340 [nfsv4] [ 9839.008069] [] ? nfs4_xdr_enc_open_noattr+0x130/0x130 [nfsv4] [ 9839.008069] [] ? xdr_encode_opaque+0x19/0x20 [sunrpc] [ 9839.008069] [] ? encode_string+0x2b/0x40 [nfsv4] [ 9839.008069] [] nfs4_xdr_enc_open+0xb3/0x140 [nfsv4] [ 9839.008069] [] rpcauth_wrap_req+0xac/0xf0 [sunrpc] [ 9839.008069] [] call_transmit+0x18b/0x2d0 [sunrpc] [ 9839.008069] [] ? call_decode+0x860/0x860 [sunrpc] [ 9839.008069] [] ? call_decode+0x860/0x860 [sunrpc] [ 9839.008069] [] __rpc_execute+0x90/0x460 [sunrpc] [ 9839.008069] [] rpc_async_schedule+0x15/0x20 [sunrpc] [ 9839.008069] [] process_one_work+0x1bb/0x410 [ 9839.008069] [] worker_thread+0x53/0x470 [ 9839.008069] [] ? process_one_work+0x410/0x410 [ 9839.008069] [] ? process_one_work+0x410/0x410 [ 9839.008069] [] kthread+0xd8/0xf0 [ 9839.008069] [] ? kthread_worker_fn+0x180/0x180 [ 9839.008069] [] ret_from_fork+0x58/0x90 [ 9839.008069] [] ? 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 [] reserve_space.part.73+0x9/0x10 [nfsv4] [ 9839.008069] RSP [ 9839.071114] ---[ end trace cc14c03adb522e94 ]--- Signed-off-by: Kinglong Mee Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'fs/nfs/internal.h') 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[]; #ifdef CONFIG_NFS_V4_SECURITY_LABEL extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); +static inline struct nfs4_label * +nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) +{ + if (!dst || !src) + return NULL; + + if (src->len > NFS4_MAXLABELLEN) + return NULL; + + dst->lfs = src->lfs; + dst->pi = src->pi; + dst->len = src->len; + memcpy(dst->label, src->label, src->len); + + return dst; +} static inline void nfs4_label_free(struct nfs4_label *label) { if (label) { @@ -316,6 +332,11 @@ static inline void nfs4_label_free(void *label) {} static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) { } +static inline struct nfs4_label * +nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src) +{ + return NULL; +} #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ /* proc.c */ -- cgit v1.2.3 From 86d80f973434de24d8a807a92cd59d5ced7bd519 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 31 Jul 2015 16:24:30 -0400 Subject: NFSv4.1/pnfs: Fix atomicity of commit list updates pnfs_layout_mark_request_commit() needs to ensure that it adds the request to the commit list atomically with all the other updates in order to prevent corruption to buckets[ds_commit_idx].wlseg due to races with pnfs_generic_clear_request_commit(). Fixes: 338d00cfef07d ("pnfs: Refactor the *_layout_mark_request_commit...") Cc: stable@vger.kernel.org # v4.0+ Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 9b372b845f6a..1dad18105ed0 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -490,6 +490,9 @@ void nfs_retry_commit(struct list_head *page_list, void nfs_commitdata_release(struct nfs_commit_data *data); void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, struct nfs_commit_info *cinfo); +void nfs_request_add_commit_list_locked(struct nfs_page *req, + struct list_head *dst, + struct nfs_commit_info *cinfo); void nfs_request_remove_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo); void nfs_init_cinfo(struct nfs_commit_info *cinfo, @@ -623,13 +626,15 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) * Record the page as unstable and mark its inode as dirty. */ static inline -void nfs_mark_page_unstable(struct page *page) +void nfs_mark_page_unstable(struct page *page, struct nfs_commit_info *cinfo) { - struct inode *inode = page_file_mapping(page)->host; + if (!cinfo->dreq) { + struct inode *inode = page_file_mapping(page)->host; - inc_zone_page_state(page, NR_UNSTABLE_NFS); - inc_wb_stat(&inode_to_bdi(inode)->wb, WB_RECLAIMABLE); - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + inc_zone_page_state(page, NR_UNSTABLE_NFS); + inc_wb_stat(&inode_to_bdi(inode)->wb, WB_RECLAIMABLE); + __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + } } /* -- cgit v1.2.3 From d8efa4e62505f5113e363572b5438b7be0d08b12 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Mon, 13 Jul 2015 14:01:28 -0400 Subject: NFS: Use RPC functions for matching sockaddrs They already exist and do the exact same thing. Let's save ourselves several lines of code! Signed-off-by: Anna Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 1dad18105ed0..9ab3b1c21bb4 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -219,10 +219,6 @@ static inline void nfs_fs_proc_exit(void) } #endif -#ifdef CONFIG_NFS_V4_1 -int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *); -#endif - /* callback_xdr.c */ extern struct svc_version nfs4_callback_version1; extern struct svc_version nfs4_callback_version4; -- cgit v1.2.3 From 5445b1fbd123420bffed5e629a420aa2a16bf849 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 5 Sep 2015 19:06:58 -0400 Subject: NFSv4: Respect the server imposed limit on how many changes we may cache The NFSv4 delegation spec allows the server to tell a client to limit how much data it cache after the file is closed. In return, the server guarantees enough free space to avoid ENOSPC situations, etc. Prior to this patch, we assumed we could always cache aggressively after close. Unfortunately, this causes problems with servers that set the limit to 0 and therefore do not offer any ENOSPC guarantees. Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 9ab3b1c21bb4..56cfde26fb9c 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -360,7 +360,6 @@ int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *) /* file.c */ int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int); loff_t nfs_file_llseek(struct file *, loff_t, int); -int nfs_file_flush(struct file *, fl_owner_t); ssize_t nfs_file_read(struct kiocb *, struct iov_iter *); ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -- cgit v1.2.3