aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/readdir.c2
-rw-r--r--fs/cifs/smb1ops.c7
-rw-r--r--fs/cifs/smb2maperror.c2
-rw-r--r--fs/cifs/smb2ops.c9
-rw-r--r--fs/cifs/smb2pdu.c9
7 files changed, 25 insertions, 8 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index bc20a6ea6754..ce24c1fc2123 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -409,6 +409,8 @@ struct smb_version_operations {
409 /* get mtu credits */ 409 /* get mtu credits */
410 int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int, 410 int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
411 unsigned int *, unsigned int *); 411 unsigned int *, unsigned int *);
412 /* check if we need to issue closedir */
413 bool (*dir_needs_close)(struct cifsFileInfo *);
412}; 414};
413 415
414struct smb_version_values { 416struct smb_version_values {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 4ab2f79ffa7a..d5fec92e0360 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -762,7 +762,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
762 762
763 cifs_dbg(FYI, "Freeing private data in close dir\n"); 763 cifs_dbg(FYI, "Freeing private data in close dir\n");
764 spin_lock(&cifs_file_list_lock); 764 spin_lock(&cifs_file_list_lock);
765 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { 765 if (server->ops->dir_needs_close(cfile)) {
766 cfile->invalidHandle = true; 766 cfile->invalidHandle = true;
767 spin_unlock(&cifs_file_list_lock); 767 spin_unlock(&cifs_file_list_lock);
768 if (server->ops->close_dir) 768 if (server->ops->close_dir)
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b15862e0f68c..798c80a41c88 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
593 /* close and restart search */ 593 /* close and restart search */
594 cifs_dbg(FYI, "search backing up - close and restart search\n"); 594 cifs_dbg(FYI, "search backing up - close and restart search\n");
595 spin_lock(&cifs_file_list_lock); 595 spin_lock(&cifs_file_list_lock);
596 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { 596 if (server->ops->dir_needs_close(cfile)) {
597 cfile->invalidHandle = true; 597 cfile->invalidHandle = true;
598 spin_unlock(&cifs_file_list_lock); 598 spin_unlock(&cifs_file_list_lock);
599 if (server->ops->close) 599 if (server->ops->close)
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 5e8c22d6c7b9..1a6df4b03f67 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -1015,6 +1015,12 @@ cifs_wp_retry_size(struct inode *inode)
1015 return CIFS_SB(inode->i_sb)->wsize; 1015 return CIFS_SB(inode->i_sb)->wsize;
1016} 1016}
1017 1017
1018static bool
1019cifs_dir_needs_close(struct cifsFileInfo *cfile)
1020{
1021 return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
1022}
1023
1018struct smb_version_operations smb1_operations = { 1024struct smb_version_operations smb1_operations = {
1019 .send_cancel = send_nt_cancel, 1025 .send_cancel = send_nt_cancel,
1020 .compare_fids = cifs_compare_fids, 1026 .compare_fids = cifs_compare_fids,
@@ -1086,6 +1092,7 @@ struct smb_version_operations smb1_operations = {
1086 .create_mf_symlink = cifs_create_mf_symlink, 1092 .create_mf_symlink = cifs_create_mf_symlink,
1087 .is_read_op = cifs_is_read_op, 1093 .is_read_op = cifs_is_read_op,
1088 .wp_retry_size = cifs_wp_retry_size, 1094 .wp_retry_size = cifs_wp_retry_size,
1095 .dir_needs_close = cifs_dir_needs_close,
1089#ifdef CONFIG_CIFS_XATTR 1096#ifdef CONFIG_CIFS_XATTR
1090 .query_all_EAs = CIFSSMBQAllEAs, 1097 .query_all_EAs = CIFSSMBQAllEAs,
1091 .set_EA = CIFSSMBSetEA, 1098 .set_EA = CIFSSMBSetEA,
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
index e31a9dfdcd39..a689514e260f 100644
--- a/fs/cifs/smb2maperror.c
+++ b/fs/cifs/smb2maperror.c
@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
214 {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, 214 {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
215 {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, 215 {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
216 {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, 216 {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
217 {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"}, 217 {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
218 {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, 218 {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
219 {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, 219 {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
220 {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"}, 220 {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 85be34ad8d76..3fcd410cee31 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1222,6 +1222,12 @@ smb2_wp_retry_size(struct inode *inode)
1222 SMB2_MAX_BUFFER_SIZE); 1222 SMB2_MAX_BUFFER_SIZE);
1223} 1223}
1224 1224
1225static bool
1226smb2_dir_needs_close(struct cifsFileInfo *cfile)
1227{
1228 return !cfile->invalidHandle;
1229}
1230
1225struct smb_version_operations smb20_operations = { 1231struct smb_version_operations smb20_operations = {
1226 .compare_fids = smb2_compare_fids, 1232 .compare_fids = smb2_compare_fids,
1227 .setup_request = smb2_setup_request, 1233 .setup_request = smb2_setup_request,
@@ -1297,6 +1303,7 @@ struct smb_version_operations smb20_operations = {
1297 .parse_lease_buf = smb2_parse_lease_buf, 1303 .parse_lease_buf = smb2_parse_lease_buf,
1298 .clone_range = smb2_clone_range, 1304 .clone_range = smb2_clone_range,
1299 .wp_retry_size = smb2_wp_retry_size, 1305 .wp_retry_size = smb2_wp_retry_size,
1306 .dir_needs_close = smb2_dir_needs_close,
1300}; 1307};
1301 1308
1302struct smb_version_operations smb21_operations = { 1309struct smb_version_operations smb21_operations = {
@@ -1374,6 +1381,7 @@ struct smb_version_operations smb21_operations = {
1374 .parse_lease_buf = smb2_parse_lease_buf, 1381 .parse_lease_buf = smb2_parse_lease_buf,
1375 .clone_range = smb2_clone_range, 1382 .clone_range = smb2_clone_range,
1376 .wp_retry_size = smb2_wp_retry_size, 1383 .wp_retry_size = smb2_wp_retry_size,
1384 .dir_needs_close = smb2_dir_needs_close,
1377}; 1385};
1378 1386
1379struct smb_version_operations smb30_operations = { 1387struct smb_version_operations smb30_operations = {
@@ -1454,6 +1462,7 @@ struct smb_version_operations smb30_operations = {
1454 .clone_range = smb2_clone_range, 1462 .clone_range = smb2_clone_range,
1455 .validate_negotiate = smb3_validate_negotiate, 1463 .validate_negotiate = smb3_validate_negotiate,
1456 .wp_retry_size = smb2_wp_retry_size, 1464 .wp_retry_size = smb2_wp_retry_size,
1465 .dir_needs_close = smb2_dir_needs_close,
1457}; 1466};
1458 1467
1459struct smb_version_values smb20_values = { 1468struct smb_version_values smb20_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 240c627bc0c6..fa0dd044213b 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2180,6 +2180,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
2180 rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; 2180 rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
2181 2181
2182 if (rc) { 2182 if (rc) {
2183 if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) {
2184 srch_inf->endOfSearch = true;
2185 rc = 0;
2186 }
2183 cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); 2187 cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
2184 goto qdir_exit; 2188 goto qdir_exit;
2185 } 2189 }
@@ -2217,11 +2221,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
2217 else 2221 else
2218 cifs_dbg(VFS, "illegal search buffer type\n"); 2222 cifs_dbg(VFS, "illegal search buffer type\n");
2219 2223
2220 if (rsp->hdr.Status == STATUS_NO_MORE_FILES)
2221 srch_inf->endOfSearch = 1;
2222 else
2223 srch_inf->endOfSearch = 0;
2224
2225 return rc; 2224 return rc;
2226 2225
2227qdir_exit: 2226qdir_exit: