aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-06 14:51:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-06 14:51:46 -0400
commitfe7a719b30dfdb4d55680461954b99b257ebe671 (patch)
tree8ca403a39b932c88cfe16f28b78d646fa908746a
parentd484467c860dab3e17893d23b2238e1f581460fa (diff)
parent85435d7a15294f9f7ef23469e6aaf7c5dfcc54f0 (diff)
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Various fixes for stable for CIFS/SMB3 especially for better interoperability for SMB3 to Macs. It also includes Pavel's improvements to SMB3 async i/o support (which is much faster now)" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: CIFS: add misssing SFM mapping for doublequote SMB3: Work around mount failure when using SMB3 dialect to Macs cifs: fix CIFS_IOC_GET_MNT_INFO oops CIFS: fix mapping of SFM_SPACE and SFM_PERIOD CIFS: fix oplock break deadlocks cifs: fix CIFS_ENUMERATE_SNAPSHOTS oops cifs: fix leak in FSCTL_ENUM_SNAPS response handling Set unicode flag on cifs echo request to avoid Mac error CIFS: Add asynchronous write support through kernel AIO CIFS: Add asynchronous read support through kernel AIO CIFS: Add asynchronous context to support kernel AIO cifs: fix IPv6 link local, with scope id, address parsing cifs: small underflow in cnvrtDosUnixTm()
-rw-r--r--fs/cifs/cifs_unicode.c6
-rw-r--r--fs/cifs/cifs_unicode.h5
-rw-r--r--fs/cifs/cifsfs.c15
-rw-r--r--fs/cifs/cifsglob.h20
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c3
-rw-r--r--fs/cifs/connect.c9
-rw-r--r--fs/cifs/file.c357
-rw-r--r--fs/cifs/ioctl.c4
-rw-r--r--fs/cifs/misc.c122
-rw-r--r--fs/cifs/netmisc.c6
-rw-r--r--fs/cifs/smb2misc.c5
-rw-r--r--fs/cifs/smb2ops.c1
-rw-r--r--fs/cifs/smb2pdu.c14
14 files changed, 465 insertions, 105 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 02b071bf3732..a0b3e7d1be48 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -83,6 +83,9 @@ convert_sfm_char(const __u16 src_char, char *target)
83 case SFM_COLON: 83 case SFM_COLON:
84 *target = ':'; 84 *target = ':';
85 break; 85 break;
86 case SFM_DOUBLEQUOTE:
87 *target = '"';
88 break;
86 case SFM_ASTERISK: 89 case SFM_ASTERISK:
87 *target = '*'; 90 *target = '*';
88 break; 91 break;
@@ -418,6 +421,9 @@ static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
418 case ':': 421 case ':':
419 dest_char = cpu_to_le16(SFM_COLON); 422 dest_char = cpu_to_le16(SFM_COLON);
420 break; 423 break;
424 case '"':
425 dest_char = cpu_to_le16(SFM_DOUBLEQUOTE);
426 break;
421 case '*': 427 case '*':
422 dest_char = cpu_to_le16(SFM_ASTERISK); 428 dest_char = cpu_to_le16(SFM_ASTERISK);
423 break; 429 break;
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 3d7298cc0aeb..8a79a34e66b8 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -57,6 +57,7 @@
57 * not conflict (although almost does) with the mapping above. 57 * not conflict (although almost does) with the mapping above.
58 */ 58 */
59 59
60#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
60#define SFM_ASTERISK ((__u16) 0xF021) 61#define SFM_ASTERISK ((__u16) 0xF021)
61#define SFM_QUESTION ((__u16) 0xF025) 62#define SFM_QUESTION ((__u16) 0xF025)
62#define SFM_COLON ((__u16) 0xF022) 63#define SFM_COLON ((__u16) 0xF022)
@@ -64,8 +65,8 @@
64#define SFM_LESSTHAN ((__u16) 0xF023) 65#define SFM_LESSTHAN ((__u16) 0xF023)
65#define SFM_PIPE ((__u16) 0xF027) 66#define SFM_PIPE ((__u16) 0xF027)
66#define SFM_SLASH ((__u16) 0xF026) 67#define SFM_SLASH ((__u16) 0xF026)
67#define SFM_PERIOD ((__u16) 0xF028) 68#define SFM_SPACE ((__u16) 0xF028)
68#define SFM_SPACE ((__u16) 0xF029) 69#define SFM_PERIOD ((__u16) 0xF029)
69 70
70/* 71/*
71 * Mapping mechanism to use when one of the seven reserved characters is 72 * Mapping mechanism to use when one of the seven reserved characters is
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d0d11b73b2af..9a1667e0e8d6 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -88,6 +88,7 @@ extern mempool_t *cifs_req_poolp;
88extern mempool_t *cifs_mid_poolp; 88extern mempool_t *cifs_mid_poolp;
89 89
90struct workqueue_struct *cifsiod_wq; 90struct workqueue_struct *cifsiod_wq;
91struct workqueue_struct *cifsoplockd_wq;
91__u32 cifs_lock_secret; 92__u32 cifs_lock_secret;
92 93
93/* 94/*
@@ -1375,9 +1376,16 @@ init_cifs(void)
1375 goto out_clean_proc; 1376 goto out_clean_proc;
1376 } 1377 }
1377 1378
1379 cifsoplockd_wq = alloc_workqueue("cifsoplockd",
1380 WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
1381 if (!cifsoplockd_wq) {
1382 rc = -ENOMEM;
1383 goto out_destroy_cifsiod_wq;
1384 }
1385
1378 rc = cifs_fscache_register(); 1386 rc = cifs_fscache_register();
1379 if (rc) 1387 if (rc)
1380 goto out_destroy_wq; 1388 goto out_destroy_cifsoplockd_wq;
1381 1389
1382 rc = cifs_init_inodecache(); 1390 rc = cifs_init_inodecache();
1383 if (rc) 1391 if (rc)
@@ -1425,7 +1433,9 @@ out_destroy_inodecache:
1425 cifs_destroy_inodecache(); 1433 cifs_destroy_inodecache();
1426out_unreg_fscache: 1434out_unreg_fscache:
1427 cifs_fscache_unregister(); 1435 cifs_fscache_unregister();
1428out_destroy_wq: 1436out_destroy_cifsoplockd_wq:
1437 destroy_workqueue(cifsoplockd_wq);
1438out_destroy_cifsiod_wq:
1429 destroy_workqueue(cifsiod_wq); 1439 destroy_workqueue(cifsiod_wq);
1430out_clean_proc: 1440out_clean_proc:
1431 cifs_proc_clean(); 1441 cifs_proc_clean();
@@ -1448,6 +1458,7 @@ exit_cifs(void)
1448 cifs_destroy_mids(); 1458 cifs_destroy_mids();
1449 cifs_destroy_inodecache(); 1459 cifs_destroy_inodecache();
1450 cifs_fscache_unregister(); 1460 cifs_fscache_unregister();
1461 destroy_workqueue(cifsoplockd_wq);
1451 destroy_workqueue(cifsiod_wq); 1462 destroy_workqueue(cifsiod_wq);
1452 cifs_proc_clean(); 1463 cifs_proc_clean();
1453} 1464}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 37f5a41cc50c..8be55be70faf 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1115,6 +1115,23 @@ struct cifs_io_parms {
1115 struct cifs_tcon *tcon; 1115 struct cifs_tcon *tcon;
1116}; 1116};
1117 1117
1118struct cifs_aio_ctx {
1119 struct kref refcount;
1120 struct list_head list;
1121 struct mutex aio_mutex;
1122 struct completion done;
1123 struct iov_iter iter;
1124 struct kiocb *iocb;
1125 struct cifsFileInfo *cfile;
1126 struct bio_vec *bv;
1127 loff_t pos;
1128 unsigned int npages;
1129 ssize_t rc;
1130 unsigned int len;
1131 unsigned int total_len;
1132 bool should_dirty;
1133};
1134
1118struct cifs_readdata; 1135struct cifs_readdata;
1119 1136
1120/* asynchronous read support */ 1137/* asynchronous read support */
@@ -1124,6 +1141,7 @@ struct cifs_readdata {
1124 struct completion done; 1141 struct completion done;
1125 struct cifsFileInfo *cfile; 1142 struct cifsFileInfo *cfile;
1126 struct address_space *mapping; 1143 struct address_space *mapping;
1144 struct cifs_aio_ctx *ctx;
1127 __u64 offset; 1145 __u64 offset;
1128 unsigned int bytes; 1146 unsigned int bytes;
1129 unsigned int got_bytes; 1147 unsigned int got_bytes;
@@ -1154,6 +1172,7 @@ struct cifs_writedata {
1154 enum writeback_sync_modes sync_mode; 1172 enum writeback_sync_modes sync_mode;
1155 struct work_struct work; 1173 struct work_struct work;
1156 struct cifsFileInfo *cfile; 1174 struct cifsFileInfo *cfile;
1175 struct cifs_aio_ctx *ctx;
1157 __u64 offset; 1176 __u64 offset;
1158 pid_t pid; 1177 pid_t pid;
1159 unsigned int bytes; 1178 unsigned int bytes;
@@ -1683,6 +1702,7 @@ void cifs_oplock_break(struct work_struct *work);
1683 1702
1684extern const struct slow_work_ops cifs_oplock_break_ops; 1703extern const struct slow_work_ops cifs_oplock_break_ops;
1685extern struct workqueue_struct *cifsiod_wq; 1704extern struct workqueue_struct *cifsiod_wq;
1705extern struct workqueue_struct *cifsoplockd_wq;
1686extern __u32 cifs_lock_secret; 1706extern __u32 cifs_lock_secret;
1687 1707
1688extern mempool_t *cifs_mid_poolp; 1708extern mempool_t *cifs_mid_poolp;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 97e5d236d265..e49958c3f8bb 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -535,4 +535,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
535 struct shash_desc *shash); 535 struct shash_desc *shash);
536enum securityEnum cifs_select_sectype(struct TCP_Server_Info *, 536enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
537 enum securityEnum); 537 enum securityEnum);
538struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
539void cifs_aio_ctx_release(struct kref *refcount);
540int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
538#endif /* _CIFSPROTO_H */ 541#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 5d21f00ae341..205fd94f52fd 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -718,6 +718,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
718 if (rc) 718 if (rc)
719 return rc; 719 return rc;
720 720
721 if (server->capabilities & CAP_UNICODE)
722 smb->hdr.Flags2 |= SMBFLG2_UNICODE;
723
721 /* set up echo request */ 724 /* set up echo request */
722 smb->hdr.Tid = 0xffff; 725 smb->hdr.Tid = 0xffff;
723 smb->hdr.WordCount = 1; 726 smb->hdr.WordCount = 1;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 9bc0b4d6d065..9365c0cf77ad 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1946,9 +1946,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1946 } 1946 }
1947 1947
1948 if (!got_ip) { 1948 if (!got_ip) {
1949 int len;
1950 const char *slash;
1951
1949 /* No ip= option specified? Try to get it from UNC */ 1952 /* No ip= option specified? Try to get it from UNC */
1950 if (!cifs_convert_address(dstaddr, &vol->UNC[2], 1953 /* Use the address part of the UNC. */
1951 strlen(&vol->UNC[2]))) { 1954 slash = strchr(&vol->UNC[2], '\\');
1955 len = slash - &vol->UNC[2];
1956 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
1952 pr_err("Unable to determine destination address.\n"); 1957 pr_err("Unable to determine destination address.\n");
1953 goto cifs_parse_mount_err; 1958 goto cifs_parse_mount_err;
1954 } 1959 }
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 21d404535739..6ef78ad838e6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2458,11 +2458,14 @@ cifs_uncached_writedata_release(struct kref *refcount)
2458 struct cifs_writedata *wdata = container_of(refcount, 2458 struct cifs_writedata *wdata = container_of(refcount,
2459 struct cifs_writedata, refcount); 2459 struct cifs_writedata, refcount);
2460 2460
2461 kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release);
2461 for (i = 0; i < wdata->nr_pages; i++) 2462 for (i = 0; i < wdata->nr_pages; i++)
2462 put_page(wdata->pages[i]); 2463 put_page(wdata->pages[i]);
2463 cifs_writedata_release(refcount); 2464 cifs_writedata_release(refcount);
2464} 2465}
2465 2466
2467static void collect_uncached_write_data(struct cifs_aio_ctx *ctx);
2468
2466static void 2469static void
2467cifs_uncached_writev_complete(struct work_struct *work) 2470cifs_uncached_writev_complete(struct work_struct *work)
2468{ 2471{
@@ -2478,7 +2481,8 @@ cifs_uncached_writev_complete(struct work_struct *work)
2478 spin_unlock(&inode->i_lock); 2481 spin_unlock(&inode->i_lock);
2479 2482
2480 complete(&wdata->done); 2483 complete(&wdata->done);
2481 2484 collect_uncached_write_data(wdata->ctx);
2485 /* the below call can possibly free the last ref to aio ctx */
2482 kref_put(&wdata->refcount, cifs_uncached_writedata_release); 2486 kref_put(&wdata->refcount, cifs_uncached_writedata_release);
2483} 2487}
2484 2488
@@ -2527,7 +2531,8 @@ wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *from,
2527static int 2531static int
2528cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, 2532cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
2529 struct cifsFileInfo *open_file, 2533 struct cifsFileInfo *open_file,
2530 struct cifs_sb_info *cifs_sb, struct list_head *wdata_list) 2534 struct cifs_sb_info *cifs_sb, struct list_head *wdata_list,
2535 struct cifs_aio_ctx *ctx)
2531{ 2536{
2532 int rc = 0; 2537 int rc = 0;
2533 size_t cur_len; 2538 size_t cur_len;
@@ -2595,6 +2600,8 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
2595 wdata->pagesz = PAGE_SIZE; 2600 wdata->pagesz = PAGE_SIZE;
2596 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); 2601 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
2597 wdata->credits = credits; 2602 wdata->credits = credits;
2603 wdata->ctx = ctx;
2604 kref_get(&ctx->refcount);
2598 2605
2599 if (!wdata->cfile->invalidHandle || 2606 if (!wdata->cfile->invalidHandle ||
2600 !(rc = cifs_reopen_file(wdata->cfile, false))) 2607 !(rc = cifs_reopen_file(wdata->cfile, false)))
@@ -2620,81 +2627,61 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
2620 return rc; 2627 return rc;
2621} 2628}
2622 2629
2623ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) 2630static void collect_uncached_write_data(struct cifs_aio_ctx *ctx)
2624{ 2631{
2625 struct file *file = iocb->ki_filp; 2632 struct cifs_writedata *wdata, *tmp;
2626 ssize_t total_written = 0;
2627 struct cifsFileInfo *open_file;
2628 struct cifs_tcon *tcon; 2633 struct cifs_tcon *tcon;
2629 struct cifs_sb_info *cifs_sb; 2634 struct cifs_sb_info *cifs_sb;
2630 struct cifs_writedata *wdata, *tmp; 2635 struct dentry *dentry = ctx->cfile->dentry;
2631 struct list_head wdata_list; 2636 unsigned int i;
2632 struct iov_iter saved_from = *from;
2633 int rc; 2637 int rc;
2634 2638
2635 /* 2639 tcon = tlink_tcon(ctx->cfile->tlink);
2636 * BB - optimize the way when signing is disabled. We can drop this 2640 cifs_sb = CIFS_SB(dentry->d_sb);
2637 * extra memory-to-memory copying and use iovec buffers for constructing
2638 * write request.
2639 */
2640
2641 rc = generic_write_checks(iocb, from);
2642 if (rc <= 0)
2643 return rc;
2644
2645 INIT_LIST_HEAD(&wdata_list);
2646 cifs_sb = CIFS_FILE_SB(file);
2647 open_file = file->private_data;
2648 tcon = tlink_tcon(open_file->tlink);
2649
2650 if (!tcon->ses->server->ops->async_writev)
2651 return -ENOSYS;
2652 2641
2653 rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from, 2642 mutex_lock(&ctx->aio_mutex);
2654 open_file, cifs_sb, &wdata_list);
2655 2643
2656 /* 2644 if (list_empty(&ctx->list)) {
2657 * If at least one write was successfully sent, then discard any rc 2645 mutex_unlock(&ctx->aio_mutex);
2658 * value from the later writes. If the other write succeeds, then 2646 return;
2659 * we'll end up returning whatever was written. If it fails, then 2647 }
2660 * we'll get a new rc value from that.
2661 */
2662 if (!list_empty(&wdata_list))
2663 rc = 0;
2664 2648
2649 rc = ctx->rc;
2665 /* 2650 /*
2666 * Wait for and collect replies for any successful sends in order of 2651 * Wait for and collect replies for any successful sends in order of
2667 * increasing offset. Once an error is hit or we get a fatal signal 2652 * increasing offset. Once an error is hit, then return without waiting
2668 * while waiting, then return without waiting for any more replies. 2653 * for any more replies.
2669 */ 2654 */
2670restart_loop: 2655restart_loop:
2671 list_for_each_entry_safe(wdata, tmp, &wdata_list, list) { 2656 list_for_each_entry_safe(wdata, tmp, &ctx->list, list) {
2672 if (!rc) { 2657 if (!rc) {
2673 /* FIXME: freezable too? */ 2658 if (!try_wait_for_completion(&wdata->done)) {
2674 rc = wait_for_completion_killable(&wdata->done); 2659 mutex_unlock(&ctx->aio_mutex);
2675 if (rc) 2660 return;
2676 rc = -EINTR; 2661 }
2677 else if (wdata->result) 2662
2663 if (wdata->result)
2678 rc = wdata->result; 2664 rc = wdata->result;
2679 else 2665 else
2680 total_written += wdata->bytes; 2666 ctx->total_len += wdata->bytes;
2681 2667
2682 /* resend call if it's a retryable error */ 2668 /* resend call if it's a retryable error */
2683 if (rc == -EAGAIN) { 2669 if (rc == -EAGAIN) {
2684 struct list_head tmp_list; 2670 struct list_head tmp_list;
2685 struct iov_iter tmp_from = saved_from; 2671 struct iov_iter tmp_from = ctx->iter;
2686 2672
2687 INIT_LIST_HEAD(&tmp_list); 2673 INIT_LIST_HEAD(&tmp_list);
2688 list_del_init(&wdata->list); 2674 list_del_init(&wdata->list);
2689 2675
2690 iov_iter_advance(&tmp_from, 2676 iov_iter_advance(&tmp_from,
2691 wdata->offset - iocb->ki_pos); 2677 wdata->offset - ctx->pos);
2692 2678
2693 rc = cifs_write_from_iter(wdata->offset, 2679 rc = cifs_write_from_iter(wdata->offset,
2694 wdata->bytes, &tmp_from, 2680 wdata->bytes, &tmp_from,
2695 open_file, cifs_sb, &tmp_list); 2681 ctx->cfile, cifs_sb, &tmp_list,
2682 ctx);
2696 2683
2697 list_splice(&tmp_list, &wdata_list); 2684 list_splice(&tmp_list, &ctx->list);
2698 2685
2699 kref_put(&wdata->refcount, 2686 kref_put(&wdata->refcount,
2700 cifs_uncached_writedata_release); 2687 cifs_uncached_writedata_release);
@@ -2705,12 +2692,111 @@ restart_loop:
2705 kref_put(&wdata->refcount, cifs_uncached_writedata_release); 2692 kref_put(&wdata->refcount, cifs_uncached_writedata_release);
2706 } 2693 }
2707 2694
2695 for (i = 0; i < ctx->npages; i++)
2696 put_page(ctx->bv[i].bv_page);
2697
2698 cifs_stats_bytes_written(tcon, ctx->total_len);
2699 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags);
2700
2701 ctx->rc = (rc == 0) ? ctx->total_len : rc;
2702
2703 mutex_unlock(&ctx->aio_mutex);
2704
2705 if (ctx->iocb && ctx->iocb->ki_complete)
2706 ctx->iocb->ki_complete(ctx->iocb, ctx->rc, 0);
2707 else
2708 complete(&ctx->done);
2709}
2710
2711ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
2712{
2713 struct file *file = iocb->ki_filp;
2714 ssize_t total_written = 0;
2715 struct cifsFileInfo *cfile;
2716 struct cifs_tcon *tcon;
2717 struct cifs_sb_info *cifs_sb;
2718 struct cifs_aio_ctx *ctx;
2719 struct iov_iter saved_from = *from;
2720 int rc;
2721
2722 /*
2723 * BB - optimize the way when signing is disabled. We can drop this
2724 * extra memory-to-memory copying and use iovec buffers for constructing
2725 * write request.
2726 */
2727
2728 rc = generic_write_checks(iocb, from);
2729 if (rc <= 0)
2730 return rc;
2731
2732 cifs_sb = CIFS_FILE_SB(file);
2733 cfile = file->private_data;
2734 tcon = tlink_tcon(cfile->tlink);
2735
2736 if (!tcon->ses->server->ops->async_writev)
2737 return -ENOSYS;
2738
2739 ctx = cifs_aio_ctx_alloc();
2740 if (!ctx)
2741 return -ENOMEM;
2742
2743 ctx->cfile = cifsFileInfo_get(cfile);
2744
2745 if (!is_sync_kiocb(iocb))
2746 ctx->iocb = iocb;
2747
2748 ctx->pos = iocb->ki_pos;
2749
2750 rc = setup_aio_ctx_iter(ctx, from, WRITE);
2751 if (rc) {
2752 kref_put(&ctx->refcount, cifs_aio_ctx_release);
2753 return rc;
2754 }
2755
2756 /* grab a lock here due to read response handlers can access ctx */
2757 mutex_lock(&ctx->aio_mutex);
2758
2759 rc = cifs_write_from_iter(iocb->ki_pos, ctx->len, &saved_from,
2760 cfile, cifs_sb, &ctx->list, ctx);
2761
2762 /*
2763 * If at least one write was successfully sent, then discard any rc
2764 * value from the later writes. If the other write succeeds, then
2765 * we'll end up returning whatever was written. If it fails, then
2766 * we'll get a new rc value from that.
2767 */
2768 if (!list_empty(&ctx->list))
2769 rc = 0;
2770
2771 mutex_unlock(&ctx->aio_mutex);
2772
2773 if (rc) {
2774 kref_put(&ctx->refcount, cifs_aio_ctx_release);
2775 return rc;
2776 }
2777
2778 if (!is_sync_kiocb(iocb)) {
2779 kref_put(&ctx->refcount, cifs_aio_ctx_release);
2780 return -EIOCBQUEUED;
2781 }
2782
2783 rc = wait_for_completion_killable(&ctx->done);
2784 if (rc) {
2785 mutex_lock(&ctx->aio_mutex);
2786 ctx->rc = rc = -EINTR;
2787 total_written = ctx->total_len;
2788 mutex_unlock(&ctx->aio_mutex);
2789 } else {
2790 rc = ctx->rc;
2791 total_written = ctx->total_len;
2792 }
2793
2794 kref_put(&ctx->refcount, cifs_aio_ctx_release);
2795
2708 if (unlikely(!total_written)) 2796 if (unlikely(!total_written))
2709 return rc; 2797 return rc;
2710 2798
2711 iocb->ki_pos += total_written; 2799 iocb->ki_pos += total_written;
2712 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(file_inode(file))->flags);
2713 cifs_stats_bytes_written(tcon, total_written);
2714 return total_written; 2800 return total_written;
2715} 2801}
2716 2802
@@ -2859,6 +2945,7 @@ cifs_uncached_readdata_release(struct kref *refcount)
2859 struct cifs_readdata, refcount); 2945 struct cifs_readdata, refcount);
2860 unsigned int i; 2946 unsigned int i;
2861 2947
2948 kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release);
2862 for (i = 0; i < rdata->nr_pages; i++) { 2949 for (i = 0; i < rdata->nr_pages; i++) {
2863 put_page(rdata->pages[i]); 2950 put_page(rdata->pages[i]);
2864 rdata->pages[i] = NULL; 2951 rdata->pages[i] = NULL;
@@ -2900,6 +2987,8 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter)
2900 return remaining ? -EFAULT : 0; 2987 return remaining ? -EFAULT : 0;
2901} 2988}
2902 2989
2990static void collect_uncached_read_data(struct cifs_aio_ctx *ctx);
2991
2903static void 2992static void
2904cifs_uncached_readv_complete(struct work_struct *work) 2993cifs_uncached_readv_complete(struct work_struct *work)
2905{ 2994{
@@ -2907,6 +2996,8 @@ cifs_uncached_readv_complete(struct work_struct *work)
2907 struct cifs_readdata, work); 2996 struct cifs_readdata, work);
2908 2997
2909 complete(&rdata->done); 2998 complete(&rdata->done);
2999 collect_uncached_read_data(rdata->ctx);
3000 /* the below call can possibly free the last ref to aio ctx */
2910 kref_put(&rdata->refcount, cifs_uncached_readdata_release); 3001 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2911} 3002}
2912 3003
@@ -2973,7 +3064,8 @@ cifs_uncached_copy_into_pages(struct TCP_Server_Info *server,
2973 3064
2974static int 3065static int
2975cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, 3066cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
2976 struct cifs_sb_info *cifs_sb, struct list_head *rdata_list) 3067 struct cifs_sb_info *cifs_sb, struct list_head *rdata_list,
3068 struct cifs_aio_ctx *ctx)
2977{ 3069{
2978 struct cifs_readdata *rdata; 3070 struct cifs_readdata *rdata;
2979 unsigned int npages, rsize, credits; 3071 unsigned int npages, rsize, credits;
@@ -3020,6 +3112,8 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
3020 rdata->read_into_pages = cifs_uncached_read_into_pages; 3112 rdata->read_into_pages = cifs_uncached_read_into_pages;
3021 rdata->copy_into_pages = cifs_uncached_copy_into_pages; 3113 rdata->copy_into_pages = cifs_uncached_copy_into_pages;
3022 rdata->credits = credits; 3114 rdata->credits = credits;
3115 rdata->ctx = ctx;
3116 kref_get(&ctx->refcount);
3023 3117
3024 if (!rdata->cfile->invalidHandle || 3118 if (!rdata->cfile->invalidHandle ||
3025 !(rc = cifs_reopen_file(rdata->cfile, true))) 3119 !(rc = cifs_reopen_file(rdata->cfile, true)))
@@ -3042,50 +3136,37 @@ error:
3042 return rc; 3136 return rc;
3043} 3137}
3044 3138
3045ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) 3139static void
3140collect_uncached_read_data(struct cifs_aio_ctx *ctx)
3046{ 3141{
3047 struct file *file = iocb->ki_filp; 3142 struct cifs_readdata *rdata, *tmp;
3048 ssize_t rc; 3143 struct iov_iter *to = &ctx->iter;
3049 size_t len;
3050 ssize_t total_read = 0;
3051 loff_t offset = iocb->ki_pos;
3052 struct cifs_sb_info *cifs_sb; 3144 struct cifs_sb_info *cifs_sb;
3053 struct cifs_tcon *tcon; 3145 struct cifs_tcon *tcon;
3054 struct cifsFileInfo *open_file; 3146 unsigned int i;
3055 struct cifs_readdata *rdata, *tmp; 3147 int rc;
3056 struct list_head rdata_list;
3057
3058 len = iov_iter_count(to);
3059 if (!len)
3060 return 0;
3061
3062 INIT_LIST_HEAD(&rdata_list);
3063 cifs_sb = CIFS_FILE_SB(file);
3064 open_file = file->private_data;
3065 tcon = tlink_tcon(open_file->tlink);
3066
3067 if (!tcon->ses->server->ops->async_readv)
3068 return -ENOSYS;
3069 3148
3070 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 3149 tcon = tlink_tcon(ctx->cfile->tlink);
3071 cifs_dbg(FYI, "attempting read on write only file instance\n"); 3150 cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb);
3072 3151
3073 rc = cifs_send_async_read(offset, len, open_file, cifs_sb, &rdata_list); 3152 mutex_lock(&ctx->aio_mutex);
3074 3153
3075 /* if at least one read request send succeeded, then reset rc */ 3154 if (list_empty(&ctx->list)) {
3076 if (!list_empty(&rdata_list)) 3155 mutex_unlock(&ctx->aio_mutex);
3077 rc = 0; 3156 return;
3157 }
3078 3158
3079 len = iov_iter_count(to); 3159 rc = ctx->rc;
3080 /* the loop below should proceed in the order of increasing offsets */ 3160 /* the loop below should proceed in the order of increasing offsets */
3081again: 3161again:
3082 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { 3162 list_for_each_entry_safe(rdata, tmp, &ctx->list, list) {
3083 if (!rc) { 3163 if (!rc) {
3084 /* FIXME: freezable sleep too? */ 3164 if (!try_wait_for_completion(&rdata->done)) {
3085 rc = wait_for_completion_killable(&rdata->done); 3165 mutex_unlock(&ctx->aio_mutex);
3086 if (rc) 3166 return;
3087 rc = -EINTR; 3167 }
3088 else if (rdata->result == -EAGAIN) { 3168
3169 if (rdata->result == -EAGAIN) {
3089 /* resend call if it's a retryable error */ 3170 /* resend call if it's a retryable error */
3090 struct list_head tmp_list; 3171 struct list_head tmp_list;
3091 unsigned int got_bytes = rdata->got_bytes; 3172 unsigned int got_bytes = rdata->got_bytes;
@@ -3111,9 +3192,9 @@ again:
3111 rdata->offset + got_bytes, 3192 rdata->offset + got_bytes,
3112 rdata->bytes - got_bytes, 3193 rdata->bytes - got_bytes,
3113 rdata->cfile, cifs_sb, 3194 rdata->cfile, cifs_sb,
3114 &tmp_list); 3195 &tmp_list, ctx);
3115 3196
3116 list_splice(&tmp_list, &rdata_list); 3197 list_splice(&tmp_list, &ctx->list);
3117 3198
3118 kref_put(&rdata->refcount, 3199 kref_put(&rdata->refcount,
3119 cifs_uncached_readdata_release); 3200 cifs_uncached_readdata_release);
@@ -3131,14 +3212,110 @@ again:
3131 kref_put(&rdata->refcount, cifs_uncached_readdata_release); 3212 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
3132 } 3213 }
3133 3214
3134 total_read = len - iov_iter_count(to); 3215 for (i = 0; i < ctx->npages; i++) {
3216 if (ctx->should_dirty)
3217 set_page_dirty(ctx->bv[i].bv_page);
3218 put_page(ctx->bv[i].bv_page);
3219 }
3220
3221 ctx->total_len = ctx->len - iov_iter_count(to);
3135 3222
3136 cifs_stats_bytes_read(tcon, total_read); 3223 cifs_stats_bytes_read(tcon, ctx->total_len);
3137 3224
3138 /* mask nodata case */ 3225 /* mask nodata case */
3139 if (rc == -ENODATA) 3226 if (rc == -ENODATA)
3140 rc = 0; 3227 rc = 0;
3141 3228
3229 ctx->rc = (rc == 0) ? ctx->total_len : rc;
3230
3231 mutex_unlock(&ctx->aio_mutex);
3232
3233 if (ctx->iocb && ctx->iocb->ki_complete)
3234 ctx->iocb->ki_complete(ctx->iocb, ctx->rc, 0);
3235 else
3236 complete(&ctx->done);
3237}
3238
3239ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
3240{
3241 struct file *file = iocb->ki_filp;
3242 ssize_t rc;
3243 size_t len;
3244 ssize_t total_read = 0;
3245 loff_t offset = iocb->ki_pos;
3246 struct cifs_sb_info *cifs_sb;
3247 struct cifs_tcon *tcon;
3248 struct cifsFileInfo *cfile;
3249 struct cifs_aio_ctx *ctx;
3250
3251 len = iov_iter_count(to);
3252 if (!len)
3253 return 0;
3254
3255 cifs_sb = CIFS_FILE_SB(file);
3256 cfile = file->private_data;
3257 tcon = tlink_tcon(cfile->tlink);
3258
3259 if (!tcon->ses->server->ops->async_readv)
3260 return -ENOSYS;
3261
3262 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
3263 cifs_dbg(FYI, "attempting read on write only file instance\n");
3264
3265 ctx = cifs_aio_ctx_alloc();
3266 if (!ctx)
3267 return -ENOMEM;
3268
3269 ctx->cfile = cifsFileInfo_get(cfile);
3270
3271 if (!is_sync_kiocb(iocb))
3272 ctx->iocb = iocb;
3273
3274 if (to->type & ITER_IOVEC)
3275 ctx->should_dirty = true;
3276
3277 rc = setup_aio_ctx_iter(ctx, to, READ);
3278 if (rc) {
3279 kref_put(&ctx->refcount, cifs_aio_ctx_release);
3280 return rc;
3281 }
3282
3283 len = ctx->len;
3284
3285 /* grab a lock here due to read response handlers can access ctx */
3286 mutex_lock(&ctx->aio_mutex);
3287
3288 rc = cifs_send_async_read(offset, len, cfile, cifs_sb, &ctx->list, ctx);
3289
3290 /* if at least one read request send succeeded, then reset rc */
3291 if (!list_empty(&ctx->list))
3292 rc = 0;
3293
3294 mutex_unlock(&ctx->aio_mutex);
3295
3296 if (rc) {
3297 kref_put(&ctx->refcount, cifs_aio_ctx_release);
3298 return rc;
3299 }
3300
3301 if (!is_sync_kiocb(iocb)) {
3302 kref_put(&ctx->refcount, cifs_aio_ctx_release);
3303 return -EIOCBQUEUED;
3304 }
3305
3306 rc = wait_for_completion_killable(&ctx->done);
3307 if (rc) {
3308 mutex_lock(&ctx->aio_mutex);
3309 ctx->rc = rc = -EINTR;
3310 total_read = ctx->total_len;
3311 mutex_unlock(&ctx->aio_mutex);
3312 } else {
3313 rc = ctx->rc;
3314 total_read = ctx->total_len;
3315 }
3316
3317 kref_put(&ctx->refcount, cifs_aio_ctx_release);
3318
3142 if (total_read) { 3319 if (total_read) {
3143 iocb->ki_pos += total_read; 3320 iocb->ki_pos += total_read;
3144 return total_read; 3321 return total_read;
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 7f4bba574930..76fb0917dc8c 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -209,10 +209,14 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
209 rc = -EOPNOTSUPP; 209 rc = -EOPNOTSUPP;
210 break; 210 break;
211 case CIFS_IOC_GET_MNT_INFO: 211 case CIFS_IOC_GET_MNT_INFO:
212 if (pSMBFile == NULL)
213 break;
212 tcon = tlink_tcon(pSMBFile->tlink); 214 tcon = tlink_tcon(pSMBFile->tlink);
213 rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); 215 rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
214 break; 216 break;
215 case CIFS_ENUMERATE_SNAPSHOTS: 217 case CIFS_ENUMERATE_SNAPSHOTS:
218 if (pSMBFile == NULL)
219 break;
216 if (arg == 0) { 220 if (arg == 0) {
217 rc = -EINVAL; 221 rc = -EINVAL;
218 goto cifs_ioc_exit; 222 goto cifs_ioc_exit;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 843787850435..b08531977daa 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -22,6 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/ctype.h> 23#include <linux/ctype.h>
24#include <linux/mempool.h> 24#include <linux/mempool.h>
25#include <linux/vmalloc.h>
25#include "cifspdu.h" 26#include "cifspdu.h"
26#include "cifsglob.h" 27#include "cifsglob.h"
27#include "cifsproto.h" 28#include "cifsproto.h"
@@ -488,7 +489,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
488 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, 489 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
489 &pCifsInode->flags); 490 &pCifsInode->flags);
490 491
491 queue_work(cifsiod_wq, 492 queue_work(cifsoplockd_wq,
492 &netfile->oplock_break); 493 &netfile->oplock_break);
493 netfile->oplock_break_cancelled = false; 494 netfile->oplock_break_cancelled = false;
494 495
@@ -741,3 +742,122 @@ parse_DFS_referrals_exit:
741 } 742 }
742 return rc; 743 return rc;
743} 744}
745
746struct cifs_aio_ctx *
747cifs_aio_ctx_alloc(void)
748{
749 struct cifs_aio_ctx *ctx;
750
751 ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
752 if (!ctx)
753 return NULL;
754
755 INIT_LIST_HEAD(&ctx->list);
756 mutex_init(&ctx->aio_mutex);
757 init_completion(&ctx->done);
758 kref_init(&ctx->refcount);
759 return ctx;
760}
761
762void
763cifs_aio_ctx_release(struct kref *refcount)
764{
765 struct cifs_aio_ctx *ctx = container_of(refcount,
766 struct cifs_aio_ctx, refcount);
767
768 cifsFileInfo_put(ctx->cfile);
769 kvfree(ctx->bv);
770 kfree(ctx);
771}
772
773#define CIFS_AIO_KMALLOC_LIMIT (1024 * 1024)
774
775int
776setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
777{
778 ssize_t rc;
779 unsigned int cur_npages;
780 unsigned int npages = 0;
781 unsigned int i;
782 size_t len;
783 size_t count = iov_iter_count(iter);
784 unsigned int saved_len;
785 size_t start;
786 unsigned int max_pages = iov_iter_npages(iter, INT_MAX);
787 struct page **pages = NULL;
788 struct bio_vec *bv = NULL;
789
790 if (iter->type & ITER_KVEC) {
791 memcpy(&ctx->iter, iter, sizeof(struct iov_iter));
792 ctx->len = count;
793 iov_iter_advance(iter, count);
794 return 0;
795 }
796
797 if (max_pages * sizeof(struct bio_vec) <= CIFS_AIO_KMALLOC_LIMIT)
798 bv = kmalloc_array(max_pages, sizeof(struct bio_vec),
799 GFP_KERNEL);
800
801 if (!bv) {
802 bv = vmalloc(max_pages * sizeof(struct bio_vec));
803 if (!bv)
804 return -ENOMEM;
805 }
806
807 if (max_pages * sizeof(struct page *) <= CIFS_AIO_KMALLOC_LIMIT)
808 pages = kmalloc_array(max_pages, sizeof(struct page *),
809 GFP_KERNEL);
810
811 if (!pages) {
812 pages = vmalloc(max_pages * sizeof(struct page *));
813 if (!bv) {
814 kvfree(bv);
815 return -ENOMEM;
816 }
817 }
818
819 saved_len = count;
820
821 while (count && npages < max_pages) {
822 rc = iov_iter_get_pages(iter, pages, count, max_pages, &start);
823 if (rc < 0) {
824 cifs_dbg(VFS, "couldn't get user pages (rc=%zd)\n", rc);
825 break;
826 }
827
828 if (rc > count) {
829 cifs_dbg(VFS, "get pages rc=%zd more than %zu\n", rc,
830 count);
831 break;
832 }
833
834 iov_iter_advance(iter, rc);
835 count -= rc;
836 rc += start;
837 cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE);
838
839 if (npages + cur_npages > max_pages) {
840 cifs_dbg(VFS, "out of vec array capacity (%u vs %u)\n",
841 npages + cur_npages, max_pages);
842 break;
843 }
844
845 for (i = 0; i < cur_npages; i++) {
846 len = rc > PAGE_SIZE ? PAGE_SIZE : rc;
847 bv[npages + i].bv_page = pages[i];
848 bv[npages + i].bv_offset = start;
849 bv[npages + i].bv_len = len - start;
850 rc -= len;
851 start = 0;
852 }
853
854 npages += cur_npages;
855 }
856
857 kvfree(pages);
858 ctx->bv = bv;
859 ctx->len = saved_len - count;
860 ctx->npages = npages;
861 iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len);
862 return 0;
863}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index abae6dd2c6b9..cc88f4f0325e 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -980,10 +980,10 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
980 cifs_dbg(VFS, "illegal hours %d\n", st->Hours); 980 cifs_dbg(VFS, "illegal hours %d\n", st->Hours);
981 days = sd->Day; 981 days = sd->Day;
982 month = sd->Month; 982 month = sd->Month;
983 if ((days > 31) || (month > 12)) { 983 if (days < 1 || days > 31 || month < 1 || month > 12) {
984 cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, days); 984 cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, days);
985 if (month > 12) 985 days = clamp(days, 1, 31);
986 month = 12; 986 month = clamp(month, 1, 12);
987 } 987 }
988 month -= 1; 988 month -= 1;
989 days += total_days_of_prev_months[month]; 989 days += total_days_of_prev_months[month];
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 1a04b3a5beb1..7b08a1446a7f 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -499,7 +499,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
499 else 499 else
500 cfile->oplock_break_cancelled = true; 500 cfile->oplock_break_cancelled = true;
501 501
502 queue_work(cifsiod_wq, &cfile->oplock_break); 502 queue_work(cifsoplockd_wq, &cfile->oplock_break);
503 kfree(lw); 503 kfree(lw);
504 return true; 504 return true;
505 } 505 }
@@ -643,7 +643,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
643 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, 643 CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
644 &cinode->flags); 644 &cinode->flags);
645 spin_unlock(&cfile->file_info_lock); 645 spin_unlock(&cfile->file_info_lock);
646 queue_work(cifsiod_wq, &cfile->oplock_break); 646 queue_work(cifsoplockd_wq,
647 &cfile->oplock_break);
647 648
648 spin_unlock(&tcon->open_file_lock); 649 spin_unlock(&tcon->open_file_lock);
649 spin_unlock(&cifs_tcp_ses_lock); 650 spin_unlock(&cifs_tcp_ses_lock);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 152e37f2ad92..c58691834eb2 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -942,6 +942,7 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
942 } 942 }
943 if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) { 943 if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
944 rc = -ERANGE; 944 rc = -ERANGE;
945 kfree(retbuf);
945 return rc; 946 return rc;
946 } 947 }
947 948
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index fb0da096c2ce..48ff7703b919 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -633,8 +633,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
633 } 633 }
634 634
635 if (rsplen != sizeof(struct validate_negotiate_info_rsp)) { 635 if (rsplen != sizeof(struct validate_negotiate_info_rsp)) {
636 cifs_dbg(VFS, "invalid size of protocol negotiate response\n"); 636 cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n",
637 return -EIO; 637 rsplen);
638
639 /* relax check since Mac returns max bufsize allowed on ioctl */
640 if (rsplen > CIFSMaxBufSize)
641 return -EIO;
638 } 642 }
639 643
640 /* check validate negotiate info response matches what we got earlier */ 644 /* check validate negotiate info response matches what we got earlier */
@@ -1854,8 +1858,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
1854 * than one credit. Windows typically sets this smaller, but for some 1858 * than one credit. Windows typically sets this smaller, but for some
1855 * ioctls it may be useful to allow server to send more. No point 1859 * ioctls it may be useful to allow server to send more. No point
1856 * limiting what the server can send as long as fits in one credit 1860 * limiting what the server can send as long as fits in one credit
1861 * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
1862 * (by default, note that it can be overridden to make max larger)
1863 * in responses (except for read responses which can be bigger.
1864 * We may want to bump this limit up
1857 */ 1865 */
1858 req->MaxOutputResponse = cpu_to_le32(0xFF00); /* < 64K uses 1 credit */ 1866 req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize);
1859 1867
1860 if (is_fsctl) 1868 if (is_fsctl)
1861 req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); 1869 req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);