From patchwork Tue Nov 25 07:52:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namjae Jeon X-Patchwork-Id: 5373641 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B1BC39F2F5 for ; Tue, 25 Nov 2014 07:53:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C06EC201C7 for ; Tue, 25 Nov 2014 07:53:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A1F3020123 for ; Tue, 25 Nov 2014 07:53:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752955AbaKYHwz (ORCPT ); Tue, 25 Nov 2014 02:52:55 -0500 Received: from mailout4.samsung.com ([203.254.224.34]:54323 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752938AbaKYHww (ORCPT ); Tue, 25 Nov 2014 02:52:52 -0500 Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NFL00H8M4K2EX50@mailout4.samsung.com> for linux-cifs@vger.kernel.org; Tue, 25 Nov 2014 16:52:50 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.114]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id 6D.FF.17016.25534745; Tue, 25 Nov 2014 16:52:50 +0900 (KST) X-AuditID: cbfee68d-f79296d000004278-f2-5474355292ce Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id F4.9E.09430.25534745; Tue, 25 Nov 2014 16:52:50 +0900 (KST) Received: from DONAMJAEJEO06 ([10.88.104.63]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0NFL00JKZ4K0KF30@mmp1.samsung.com>; Tue, 25 Nov 2014 16:52:50 +0900 (KST) From: Namjae Jeon To: Steve French Cc: linux-cifs@vger.kernel.org, Ashish Sangwan Subject: [PATCH 2/2] cifs: don't add dot and dotdot entry by default at the start of cifs_readdir Date: Tue, 25 Nov 2014 16:52:50 +0900 Message-id: <001301d00884$cf8e0200$6eaa0600$@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-index: AdAIg+ap372hA25yQsGgFUqeeLj2CA== Content-language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAIsWRmVeSWpSXmKPExsWyRsSkSDfItCTEoKnD3GLpxEvMFi/+72K2 ePPiMJsDs8fOWXfZPfq2rGL0+LxJLoA5issmJTUnsyy1SN8ugStj54Qb7AUHFCpOnVnE2MD4 T7KLkZNDQsBE4sadvUwQtpjEhXvr2boYuTiEBJYySnzf+pYNrmjBTHaIxCJGiatP+hkhnL+M EhumHQNyODjYBLQl/mwRBWkQEVCVeNc8lRnEZhZwk3j/+jcrSImwQLJEU3cSSJgFqOTZv9dg JbwClhLrpu1khLAFJX5MvscC0aolsX7ncSYIW15i85q3zBD3KEjsOPuaEWKVnsS5ezcZIWpE JPa9eAd2moTAInaJBzcvsUEsE5D4NvkQC8gNEgKyEpsOQM2RlDi44gbLBEaxWUhWz0KyehaS 1bOQrFjAyLKKUTS1ILmgOCm9yFCvODG3uDQvXS85P3cTIzCiTv971ruD8fYB60OMAhyMSjy8 HWeLQ4RYE8uKK3MPMZoCXTSRWUo0OR8Yt3kl8YbGZkYWpiamxkbmlmZK4ryKUj+DhQTSE0tS s1NTC1KL4otKc1KLDzEycXBKNTD6pIX0FZ/gqn5kYsw9O13d7m6+LdtiS/uTb0Pn7YqImtxx /UzMn/IleicNZ0gYGTXz3dgmveeDJV/Jy+8tjn+LWdZc+7Dqwmt5+SfyyvuPZ5rHq2ZcuLWo 00lD7eilrDzFDDPNOxNn1brMjHRcVn7/tHvs1o6+Kl8TWa3w5wUfRRh6PwZeOKjEUpyRaKjF XFScCABKiWanowIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrFIsWRmVeSWpSXmKPExsVy+t9jAd0g05IQg7W7DSyWTrzEbPHi/y5m izcvDrM5MHvsnHWX3aNvyypGj8+b5AKYoxoYbTJSE1NSixRS85LzUzLz0m2VvIPjneNNzQwM dQ0tLcyVFPISc1NtlVx8AnTdMnOANikplCXmlAKFAhKLi5X07TBNCA1x07WAaYzQ9Q0Jgusx MkADCWsYM3ZOuMFecECh4tSZRYwNjP8kuxg5OSQETCRuLJjJDmGLSVy4t56ti5GLQ0hgEaPE 1Sf9jBDOX0aJDdOOATkcHGwC2hJ/toiCNIgIqEq8a57KDGIzC7hJvH/9mxWkRFggWaKpOwkk zAJU8uzfa7ASXgFLiXXTdjJC2IISPybfY4Fo1ZJYv/M4E4QtL7F5zVtmiHsUJHacfc0IsUpP 4ty9m4wQNSIS+168Y5zAKDALyahZSEbNQjJqFpKWBYwsqxhFUwuSC4qT0nON9IoTc4tL89L1 kvNzNzGC4/WZ9A7GVQ0WhxgFOBiVeHg7zhaHCLEmlhVX5h5ilOBgVhLhjZoHFOJNSaysSi3K jy8qzUktPsRoCvTpRGYp0eR8YCrJK4k3NDYxM7I0Mje0MDI2VxLnvXEzN0RIID2xJDU7NbUg tQimj4mDU6qBsahqtlz1yll/AmfZJnMcXu25Vy5893sG060XpSJTf7n0Tl+ntT/YM2nGtM/P PKX4f0ys3XDdXqb7Of+BvHJby9h1q3dn7At+JiFt9OP+xBdGJXd+LFk1k1v315t9QkEOIsIX Dd4a5J/aWqzoxXzoXsvXs7sWlJ6suH+451nk/tTvVSfmsn4tW6zEUpyRaKjFXFScCADBDNRI 7QIAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, dot and dotdot are added by default at the start of cifs_readdir. This works well for the servers which send dot and dotdot entries at the start in readdir query response. For servers which do not send these two entries at the beginning, this behavior creates 2 problems. 1) adding dot and dotdot increments ctx->pos by 2 hence the valid first 2 entries are missed in readdir output at client side. 2) Currently when we encounter dot or dotdot, the entry is simple skipped. In case of smb2, if some buggy server sends only 1 entry in response per cifs_query_dir_next request, and if that entry is happen to be dot OR dotdot, getdents call return 0 bytes to user app making it falsely believe that there are no more directory entries left. This patch tries to solve the above issues by processing dot and dotdot entries when they are encountered. This will have no effect on servers which already sends these 2 entries at the start. Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Reviewed-by: Shirish Pargaonkar --- fs/cifs/cifsglob.h | 2 ++ fs/cifs/cifssmb.c | 4 ++-- fs/cifs/readdir.c | 43 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 6e13911..864ea1a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -987,6 +987,8 @@ struct cifs_search_info { bool emptyDir:1; bool unicode:1; bool smallBuf:1; /* so we know which buf_release function to call */ + bool gotdot:1; + bool gotdotdot:1; }; struct cifs_open_parms { diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index fa13d5e..db49633 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -4475,8 +4475,8 @@ findFirstRetry: psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); - psrch_inf->index_of_last_entry = 2 /* skip . and .. */ + - psrch_inf->entries_in_buffer; + psrch_inf->index_of_last_entry = + psrch_inf->entries_in_buffer; lnoff = le16_to_cpu(parms->LastNameOffset); if (CIFSMaxBufSize < lnoff) { cifs_dbg(VFS, "ignoring corrupt resume name\n"); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 8eaf20a..ab0639a 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -698,9 +698,26 @@ static int cifs_filldir(char *find_entry, struct file *file, return -EINVAL; } - /* skip . and .. since we added them first */ - if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) + if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode) == 1) { + if (file_info->srch_inf.gotdot == true) + return -EINVAL; + if (!dir_emit_dot(file, ctx)) { + cifs_dbg(VFS, "Filldir for current dir failed\n"); + return -ENOMEM; + } + file_info->srch_inf.gotdot = true; + return 0; + } + if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode) == 2) { + if (file_info->srch_inf.gotdotdot == true) + return -EINVAL; + if (!dir_emit_dotdot(file, ctx)) { + cifs_dbg(VFS, "Filldir for parent dir failed\n"); + return -ENOMEM; + } + file_info->srch_inf.gotdotdot = true; return 0; + } if (file_info->srch_inf.unicode) { struct nls_table *nlt = cifs_sb->local_nls; @@ -786,9 +803,6 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) goto rddir2_exit; } - if (!dir_emit_dots(file, ctx)) - goto rddir2_exit; - /* 1) If search is active, is in current search buffer? if it before then restart search @@ -864,6 +878,25 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) kfree(tmp_buf); rddir2_exit: + if (cifsFile->srch_inf.endOfSearch) { + if (cifsFile->srch_inf.gotdot != true) { + if (!dir_emit_dot(file, ctx)) { + cifs_dbg(VFS, + "Filldir for current dir failed\n"); + rc = -ENOMEM; + } + ctx->pos++; + } + + if (cifsFile->srch_inf.gotdotdot != true) { + if (!dir_emit_dotdot(file, ctx)) { + cifs_dbg(VFS, + "Filldir for parent dir failed\n"); + rc = -ENOMEM; + } + ctx->pos++; + } + } free_xid(xid); return rc; }