]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Oct 2014 00:08:41 +0000 (17:08 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Oct 2014 00:08:41 +0000 (17:08 -0700)
added patches:
cifs-fix-smb2-readdir-error-handling.patch

queue-3.14/cifs-fix-smb2-readdir-error-handling.patch [new file with mode: 0644]
queue-3.14/series

diff --git a/queue-3.14/cifs-fix-smb2-readdir-error-handling.patch b/queue-3.14/cifs-fix-smb2-readdir-error-handling.patch
new file mode 100644 (file)
index 0000000..470051f
--- /dev/null
@@ -0,0 +1,166 @@
+From 52755808d4525f4d5b86d112d36ffc7a46f3fb48 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilovsky@samba.org>
+Date: Mon, 18 Aug 2014 20:49:57 +0400
+Subject: CIFS: Fix SMB2 readdir error handling
+
+From: Pavel Shilovsky <pshilovsky@samba.org>
+
+commit 52755808d4525f4d5b86d112d36ffc7a46f3fb48 upstream.
+
+SMB2 servers indicates the end of a directory search with
+STATUS_NO_MORE_FILE error code that is not processed now.
+This causes generic/257 xfstest to fail. Fix this by triggering
+the end of search by this error code in SMB2_query_directory.
+
+Also when negotiating CIFS protocol we tell the server to close
+the search automatically at the end and there is no need to do
+it itself. In the case of SMB2 protocol, we need to close it
+explicitly - separate close directory checks for different
+protocols.
+
+Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/cifs/cifsglob.h     |    2 ++
+ fs/cifs/file.c         |    2 +-
+ fs/cifs/readdir.c      |    2 +-
+ fs/cifs/smb1ops.c      |    7 +++++++
+ fs/cifs/smb2maperror.c |    2 +-
+ fs/cifs/smb2ops.c      |    9 +++++++++
+ fs/cifs/smb2pdu.c      |    9 ++++-----
+ 7 files changed, 25 insertions(+), 8 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -399,6 +399,8 @@ struct smb_version_operations {
+                       const struct cifs_fid *, u32 *);
+       int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
+                       int);
++      /* check if we need to issue closedir */
++      bool (*dir_needs_close)(struct cifsFileInfo *);
+ };
+ struct smb_version_values {
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -762,7 +762,7 @@ int cifs_closedir(struct inode *inode, s
+       cifs_dbg(FYI, "Freeing private data in close dir\n");
+       spin_lock(&cifs_file_list_lock);
+-      if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
++      if (server->ops->dir_needs_close(cfile)) {
+               cfile->invalidHandle = true;
+               spin_unlock(&cifs_file_list_lock);
+               if (server->ops->close_dir)
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid,
+               /* close and restart search */
+               cifs_dbg(FYI, "search backing up - close and restart search\n");
+               spin_lock(&cifs_file_list_lock);
+-              if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
++              if (server->ops->dir_needs_close(cfile)) {
+                       cfile->invalidHandle = true;
+                       spin_unlock(&cifs_file_list_lock);
+                       if (server->ops->close_dir)
+--- a/fs/cifs/smb1ops.c
++++ b/fs/cifs/smb1ops.c
+@@ -1009,6 +1009,12 @@ cifs_is_read_op(__u32 oplock)
+       return oplock == OPLOCK_READ;
+ }
++static bool
++cifs_dir_needs_close(struct cifsFileInfo *cfile)
++{
++      return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
++}
++
+ struct smb_version_operations smb1_operations = {
+       .send_cancel = send_nt_cancel,
+       .compare_fids = cifs_compare_fids,
+@@ -1078,6 +1084,7 @@ struct smb_version_operations smb1_opera
+       .query_mf_symlink = cifs_query_mf_symlink,
+       .create_mf_symlink = cifs_create_mf_symlink,
+       .is_read_op = cifs_is_read_op,
++      .dir_needs_close = cifs_dir_needs_close,
+ #ifdef CONFIG_CIFS_XATTR
+       .query_all_EAs = CIFSSMBQAllEAs,
+       .set_EA = CIFSSMBSetEA,
+--- a/fs/cifs/smb2maperror.c
++++ b/fs/cifs/smb2maperror.c
+@@ -214,7 +214,7 @@ static const struct status_to_posix_erro
+       {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
+       {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
+       {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
+-      {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"},
++      {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
+       {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
+       {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
+       {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1102,6 +1102,12 @@ smb3_parse_lease_buf(void *buf, unsigned
+       return le32_to_cpu(lc->lcontext.LeaseState);
+ }
++static bool
++smb2_dir_needs_close(struct cifsFileInfo *cfile)
++{
++      return !cfile->invalidHandle;
++}
++
+ struct smb_version_operations smb20_operations = {
+       .compare_fids = smb2_compare_fids,
+       .setup_request = smb2_setup_request,
+@@ -1175,6 +1181,7 @@ struct smb_version_operations smb20_oper
+       .create_lease_buf = smb2_create_lease_buf,
+       .parse_lease_buf = smb2_parse_lease_buf,
+       .clone_range = smb2_clone_range,
++      .dir_needs_close = smb2_dir_needs_close,
+ };
+ struct smb_version_operations smb21_operations = {
+@@ -1250,6 +1257,7 @@ struct smb_version_operations smb21_oper
+       .create_lease_buf = smb2_create_lease_buf,
+       .parse_lease_buf = smb2_parse_lease_buf,
+       .clone_range = smb2_clone_range,
++      .dir_needs_close = smb2_dir_needs_close,
+ };
+ struct smb_version_operations smb30_operations = {
+@@ -1328,6 +1336,7 @@ struct smb_version_operations smb30_oper
+       .parse_lease_buf = smb3_parse_lease_buf,
+       .clone_range = smb2_clone_range,
+       .validate_negotiate = smb3_validate_negotiate,
++      .dir_needs_close = smb2_dir_needs_close,
+ };
+ struct smb_version_values smb20_values = {
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -2136,6 +2136,10 @@ SMB2_query_directory(const unsigned int
+       rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
+       if (rc) {
++              if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) {
++                      srch_inf->endOfSearch = true;
++                      rc = 0;
++              }
+               cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+               goto qdir_exit;
+       }
+@@ -2173,11 +2177,6 @@ SMB2_query_directory(const unsigned int
+       else
+               cifs_dbg(VFS, "illegal search buffer type\n");
+-      if (rsp->hdr.Status == STATUS_NO_MORE_FILES)
+-              srch_inf->endOfSearch = 1;
+-      else
+-              srch_inf->endOfSearch = 0;
+-
+       return rc;
+ qdir_exit:
index 6eeaaf503d7ab581625951d6ae74975df0db8914..b7cecfc758a8cf6385d6a444bec9a1ca9d436600 100644 (file)
@@ -7,3 +7,4 @@ drm-i915-flush-the-ptes-after-updating-them-before-suspend.patch
 fix-problem-recognizing-symlinks.patch
 init-kconfig-fix-have_futex_cmpxchg-to-not-break-up-the-expert-menu.patch
 ring-buffer-fix-infinite-spin-in-reading-buffer.patch
+cifs-fix-smb2-readdir-error-handling.patch